|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
# Copyright 2010 - 2017 RhodeCode GmbH and the AppEnlight project authors
|
|
|
#
|
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
# you may not use this file except in compliance with the License.
|
|
|
# You may obtain a copy of the License at
|
|
|
#
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
|
#
|
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
# See the License for the specific language governing permissions and
|
|
|
# limitations under the License.
|
|
|
|
|
|
import hashlib
|
|
|
import os
|
|
|
|
|
|
from pyramid.i18n import TranslationStringFactory
|
|
|
from pyramid import threadlocal
|
|
|
|
|
|
_ = TranslationStringFactory("pyramid")
|
|
|
|
|
|
from appenlight import security
|
|
|
from appenlight.lib import helpers, generate_random_string
|
|
|
from appenlight.models.services.config import ConfigService
|
|
|
|
|
|
|
|
|
def gen_urls(request):
|
|
|
urls = {
|
|
|
"baseUrl": request.route_url("/"),
|
|
|
"applicationsNoId": request.route_url("applications_no_id"),
|
|
|
"applications": request.route_url(
|
|
|
"applications", resource_id="REPLACE_ID"
|
|
|
).replace("REPLACE_ID", ":resourceId"),
|
|
|
"applicationsProperty": request.route_url(
|
|
|
"applications_property", key="REPLACE_KEY", resource_id="REPLACE_ID"
|
|
|
)
|
|
|
.replace("REPLACE_ID", ":resourceId")
|
|
|
.replace("REPLACE_KEY", ":key"),
|
|
|
"configsNoId": request.route_url("admin_configs"),
|
|
|
"configs": request.route_url(
|
|
|
"admin_config", key="REPLACE_KEY", section="REPLACE_SECTION"
|
|
|
)
|
|
|
.replace("REPLACE_SECTION", ":section")
|
|
|
.replace("REPLACE_KEY", ":key"),
|
|
|
"docs": "http://getappenlight.com/page/api/main.html",
|
|
|
"eventsNoId": request.route_url("events_no_id"),
|
|
|
"events": request.route_url("events", event_id="REPLACE_ID").replace(
|
|
|
"REPLACE_ID", ":eventId"
|
|
|
),
|
|
|
"eventsProperty": request.route_url(
|
|
|
"events_property", key="REPLACE_KEY", event_id="REPLACE_ID"
|
|
|
)
|
|
|
.replace("REPLACE_ID", ":eventId")
|
|
|
.replace("REPLACE_KEY", ":key"),
|
|
|
"groupsNoId": request.route_url("groups_no_id"),
|
|
|
"groups": request.route_url("groups", group_id="REPLACE_ID").replace(
|
|
|
"REPLACE_ID", ":groupId"
|
|
|
),
|
|
|
"groupsProperty": request.route_url(
|
|
|
"groups_property", key="REPLACE_KEY", group_id="REPLACE_ID"
|
|
|
)
|
|
|
.replace("REPLACE_ID", ":groupId")
|
|
|
.replace("REPLACE_KEY", ":key"),
|
|
|
"logsNoId": request.route_url("logs_no_id"),
|
|
|
"integrationAction": request.route_url(
|
|
|
"integrations_id",
|
|
|
action="REPLACE_ACT",
|
|
|
resource_id="REPLACE_RID",
|
|
|
integration="REPLACE_IID",
|
|
|
)
|
|
|
.replace("REPLACE_RID", ":resourceId")
|
|
|
.replace("REPLACE_ACT", ":action")
|
|
|
.replace("REPLACE_IID", ":integration"),
|
|
|
"usersNoId": request.route_url("users_no_id"),
|
|
|
"users": request.route_url("users", user_id="REPLACE_ID").replace(
|
|
|
"REPLACE_ID", ":userId"
|
|
|
),
|
|
|
"usersProperty": request.route_url(
|
|
|
"users_property", key="REPLACE_KEY", user_id="REPLACE_ID"
|
|
|
)
|
|
|
.replace("REPLACE_ID", ":userId")
|
|
|
.replace("REPLACE_KEY", ":key"),
|
|
|
"userSelf": request.route_url("users_self"),
|
|
|
"userSelfProperty": request.route_url(
|
|
|
"users_self_property", key="REPLACE_KEY"
|
|
|
).replace("REPLACE_KEY", ":key"),
|
|
|
"reports": request.route_url("reports"),
|
|
|
"reportGroup": request.route_url(
|
|
|
"report_groups", group_id="REPLACE_RID"
|
|
|
).replace("REPLACE_RID", ":groupId"),
|
|
|
"reportGroupProperty": request.route_url(
|
|
|
"report_groups_property", key="REPLACE_KEY", group_id="REPLACE_GID"
|
|
|
)
|
|
|
.replace("REPLACE_KEY", ":key")
|
|
|
.replace("REPLACE_GID", ":groupId"),
|
|
|
"pluginConfigsNoId": request.route_url(
|
|
|
"plugin_configs", plugin_name="REPLACE_TYPE"
|
|
|
).replace("REPLACE_TYPE", ":plugin_name"),
|
|
|
"pluginConfigs": request.route_url(
|
|
|
"plugin_config", id="REPLACE_ID", plugin_name="REPLACE_TYPE"
|
|
|
)
|
|
|
.replace("REPLACE_ID", ":id")
|
|
|
.replace("REPLACE_TYPE", ":plugin_name"),
|
|
|
"resourceProperty": request.route_url(
|
|
|
"resources_property", key="REPLACE_KEY", resource_id="REPLACE_ID"
|
|
|
)
|
|
|
.replace("REPLACE_ID", ":resourceId")
|
|
|
.replace("REPLACE_KEY", ":key"),
|
|
|
"slowReports": request.route_url("slow_reports"),
|
|
|
"sectionView": request.route_url(
|
|
|
"section_view", section="REPLACE_S", view="REPLACE_V"
|
|
|
)
|
|
|
.replace("REPLACE_S", ":section")
|
|
|
.replace("REPLACE_V", ":view"),
|
|
|
"otherRoutes": {
|
|
|
"register": request.route_url("register"),
|
|
|
"lostPassword": request.route_url("lost_password"),
|
|
|
"lostPasswordGenerate": request.route_url("lost_password_generate"),
|
|
|
"signOut": request.route_url("ziggurat.routes.sign_out"),
|
|
|
},
|
|
|
"social_auth": {
|
|
|
"google": request.route_url("social_auth", provider="google"),
|
|
|
"twitter": request.route_url("social_auth", provider="twitter"),
|
|
|
"bitbucket": request.route_url("social_auth", provider="bitbucket"),
|
|
|
"github": request.route_url("social_auth", provider="github"),
|
|
|
},
|
|
|
"plugins": {},
|
|
|
"adminAction": request.route_url("admin", action="REPLACE_ACT").replace(
|
|
|
"REPLACE_ACT", ":action"
|
|
|
),
|
|
|
}
|
|
|
return urls
|
|
|
|
|
|
|
|
|
def new_request(event):
|
|
|
environ = event.request.environ
|
|
|
event.request.response.headers["X-Frame-Options"] = "SAMEORIGIN"
|
|
|
event.request.response.headers["X-XSS-Protection"] = "1; mode=block"
|
|
|
# can this be enabled on non https deployments?
|
|
|
# event.request.response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubdomains;'
|
|
|
|
|
|
# do not send XSRF token with /api calls
|
|
|
if not event.request.path.startswith("/api"):
|
|
|
if environ["wsgi.url_scheme"] == "https":
|
|
|
event.request.response.set_cookie(
|
|
|
"XSRF-TOKEN", event.request.session.get_csrf_token(), secure=True
|
|
|
)
|
|
|
else:
|
|
|
event.request.response.set_cookie(
|
|
|
"XSRF-TOKEN", event.request.session.get_csrf_token()
|
|
|
)
|
|
|
if event.request.user:
|
|
|
event.request.response.headers["x-appenlight-uid"] = (
|
|
|
"%s" % event.request.user.id
|
|
|
)
|
|
|
|
|
|
|
|
|
def add_renderer_globals(event):
|
|
|
request = event.get("request") or threadlocal.get_current_request()
|
|
|
|
|
|
renderer_globals = event
|
|
|
renderer_globals["h"] = helpers
|
|
|
renderer_globals["js_hash"] = request.registry.js_hash
|
|
|
renderer_globals["css_hash"] = request.registry.css_hash
|
|
|
renderer_globals["_"] = _
|
|
|
renderer_globals["security"] = security
|
|
|
renderer_globals["flash_msgs"] = []
|
|
|
renderer_globals["appenlight_plugins"] = []
|
|
|
|
|
|
if "jinja" in event["renderer_info"].type:
|
|
|
renderer_globals["url_list"] = gen_urls(request)
|
|
|
# add footer html and some other global vars to renderer
|
|
|
for module, config in request.registry.appenlight_plugins.items():
|
|
|
if config["url_gen"]:
|
|
|
urls = config["url_gen"](request)
|
|
|
renderer_globals["url_list"]["plugins"][module] = urls
|
|
|
|
|
|
renderer_globals["appenlight_plugins"].append(
|
|
|
{
|
|
|
"name": module,
|
|
|
"config": {
|
|
|
"javascript": config["javascript"],
|
|
|
"header_html": config["header_html"],
|
|
|
},
|
|
|
}
|
|
|
)
|
|
|
|
|
|
footer_config = ConfigService.by_key_and_section(
|
|
|
"template_footer_html", "global", default_value=""
|
|
|
)
|
|
|
|
|
|
renderer_globals["template_footer_html"] = footer_config.value
|
|
|
try:
|
|
|
renderer_globals["root_administrator"] = request.has_permission(
|
|
|
"root_administration", security.RootFactory(request)
|
|
|
)
|
|
|
except AttributeError:
|
|
|
renderer_globals["root_administrator"] = False
|
|
|
|
|
|
renderer_globals["_mail_url"] = request.registry.settings["_mail_url"]
|
|
|
|
|
|
if not request:
|
|
|
return
|
|
|
|
|
|
# do not sens flash headers with /api calls
|
|
|
if not request.path.startswith("/api"):
|
|
|
flash_msgs = helpers.get_type_formatted_flash(request)
|
|
|
renderer_globals["flash_msgs"] = flash_msgs
|
|
|
request.add_flash_to_headers()
|
|
|
|
|
|
|
|
|
def application_created(app):
|
|
|
webassets_dir = app.app.registry.settings.get("webassets.dir")
|
|
|
js_hash = generate_random_string()
|
|
|
css_hash = generate_random_string()
|
|
|
if webassets_dir:
|
|
|
js_hasher = hashlib.md5()
|
|
|
css_hasher = hashlib.md5()
|
|
|
for root, dirs, files in os.walk(webassets_dir):
|
|
|
for name in files:
|
|
|
filename = os.path.join(root, name)
|
|
|
if name.endswith("css"):
|
|
|
with open(filename, "r", encoding="utf8", errors="replace") as f:
|
|
|
for line in f:
|
|
|
css_hasher.update(line.encode("utf8"))
|
|
|
elif name.endswith("js"):
|
|
|
with open(filename, "r", encoding="utf8", errors="replace") as f:
|
|
|
for line in f:
|
|
|
js_hasher.update(line.encode("utf8"))
|
|
|
js_hash = js_hasher.hexdigest()
|
|
|
css_hash = css_hasher.hexdigest()
|
|
|
app.app.registry.js_hash = js_hash
|
|
|
app.app.registry.css_hash = css_hash
|
|
|
|