diff --git a/__pycache__/app.cpython-310.pyc b/__pycache__/app.cpython-310.pyc index 76d9cf49e33a7b703ac3d6408a209a9934151f8a..aea3ec86d0a6c9480ad966848537aeb83ecc9d13 100644 Binary files a/__pycache__/app.cpython-310.pyc and b/__pycache__/app.cpython-310.pyc differ diff --git a/app.py b/app.py index eda1d80aaedc230b82f607cb5c0a372833520548..2ace287b4b440c53831cff11ad5b00e72d2956cf 100644 --- a/app.py +++ b/app.py @@ -1,6 +1,6 @@ import json -from flask import Flask, render_template, request, redirect, make_response, jsonify +from flask import Flask, render_template, request, redirect, make_response, jsonify, session from flask_babel import Babel, get_locale, gettext from jwcrypto import jwk, jwt from jwcrypto.jwk import JWKSet, JWK @@ -12,17 +12,15 @@ babel = Babel(app) with open("config_templates/config-template.yaml", "r") as ymlfile: cfg = yaml.safe_load(ymlfile) -CSS_FRAMEWORK = cfg.get('css_framework', 'bootstrap') -MUNI_FACULTY = cfg.get('MUNI_faculty', None) +if 'css_framework' not in cfg: + cfg['css_framework'] = 'bootstrap' +app.secret_key = cfg["secret_key"] TOKEN_ALG = cfg['token_alg'] KEY_ID = cfg['key_id'] KEYSTORE = cfg['keystore'] -FOOTER = cfg.get('footer', None) -LANGUAGES = cfg.get('languages', None) -LOGO = cfg.get('logo', None) -NAME = cfg.get('name', None) +REDIRECT_URL = cfg['redirect_url'] def import_keys(file_path: str) -> JWKSet: @@ -42,14 +40,21 @@ def verify_jwt(token): return jwt.JWT(jwt=token, key=jwk_key).claims +@app.context_processor +def inject_conf_var(): + return dict(cfg=cfg, lang=get_locale()) + + @babel.localeselector -def select_locale(): - return request.accept_languages.best_match(["en", "cs"]) +def get_locale(): + if request.args.get('lang'): + session['lang'] = request.args.get('lang') + return session.get('lang', 'en') @app.route('/') def index(): - return redirect('/IsTestingSP?language=en') + return redirect('/IsTestingSP') @app.route('/authorization/<message>') @@ -57,48 +62,36 @@ def authorization(message): message = json.load(verify_jwt(message)) email = message.get('email') service = message.get('service') + registration_url = message.get('registration_url') if not email or not service: - return make_response(jsonify({"fail": "Missing request parameter"}), 400) + return make_response(jsonify({gettext("fail"): gettext("Missing request parameter")}), 400) return render_template( "authorization.html", email=email, service=service, - css_framework=CSS_FRAMEWORK, - faculty=MUNI_FACULTY, - locale=get_locale() + registration_url=registration_url, ) @app.route('/SPAuthorization/<message>') def sp_authorization(message): message = json.load(verify_jwt(message)) + email = message.get('email') + service = message.get('service') registration_url = message.get('registration_url') return render_template( "SPAuthorization.html", + email=email, + service=service, registration_url=registration_url, - css_framework=CSS_FRAMEWORK, - faculty=MUNI_FACULTY, - locale=get_locale() ) @app.route('/IsTestingSP') def is_testing_sp(): - language = request.args.get('language', get_locale()) return render_template( "IsTestingSP.html", - css_framework=CSS_FRAMEWORK, - faculty=MUNI_FACULTY, - locale=language, - footer=FOOTER, - sections=FOOTER['sections'], - format=FOOTER['format'], - current_section=FOOTER['sections'][str(language)], - languages=LANGUAGES, - current_language=LANGUAGES[str(language)], - logo=LOGO, - name=NAME, - queryParams=dict() + redirect_url=REDIRECT_URL ) diff --git a/babel.cfg b/babel.cfg new file mode 100644 index 0000000000000000000000000000000000000000..155a6fa8d394317b2ea8e4c23a45cc91b2790ec0 --- /dev/null +++ b/babel.cfg @@ -0,0 +1,2 @@ +[python: **.py] +[jinja2: **/templates/**.html] \ No newline at end of file diff --git a/config_templates/config-template.yaml b/config_templates/config-template.yaml index dc146948721f337ded4281ef497d0569a35e04aa..bf08f9794e5b976dfffbba672c5988a0ff3fed49 100644 --- a/config_templates/config-template.yaml +++ b/config_templates/config-template.yaml @@ -1,4 +1,4 @@ -css_framework: MUNI +css_framework: bootstrap MUNI_faculty: keystore: path key_id: id @@ -7,13 +7,19 @@ footer: format: HTML sections: cs: - - Zprava - - Zprava2 + - Máte problém s přihlášením? + - Službu Autentizační brána zajišťuje Ústav výpočetní techniky. en: - - message - - message2 + - Having trouble logging in? + - The Authentication Gateway service is provided by the Institute of Computer Science. + de: + - de1 + - de2 languages: - cs: Cestina + cs: Čeština en: English -logo: -name: MUNI \ No newline at end of file + de: Deutsch +logo: static/MuniWeb/img/favicon.ico +name: MUNI +secret_key: secret +redirect_url: url \ No newline at end of file diff --git a/setup.py b/setup.py index 8dd07ce194d585f43bef867a272e429e5891f10f..5f9e60cdf627220a984e3a473d95650b066c23ac 100644 --- a/setup.py +++ b/setup.py @@ -7,6 +7,10 @@ setup( description="Module with gui for perun proxy", packages=find_packages(), install_requires=[ - "setuptools" + "setuptools", + "PyYAML>=6.0<7", + "Flask>=2.2.2<3", + "jwcrypto>=1.3.1<2", + "Flask-Babel>=2.0.0<3", ], ) diff --git a/templates/IsTestingSP.html b/templates/IsTestingSP.html index 2532b93cfeee289bd056653cec10caa916889ffc..bcfb2c49c680c39c13efa55ca3cb924bb7ff18b0 100644 --- a/templates/IsTestingSP.html +++ b/templates/IsTestingSP.html @@ -1,11 +1,12 @@ {% extends 'base.html' %} {% block head %} -<title>Authorization page</title> +<title></title> {% endblock %} {% block content %} <div class="content"> - <h1 style="text-align: center">IsTestingSp page</h1> + <h1 style="text-align: center"><span>{{ _("You are about to access service, which is in testing environment.") }}</span></h1> +<h1 style="text-align: center"> <a href="{{ redirect_url }}"><span>{{ _("Continue") }}</span></a></h1> </div> {% endblock %} \ No newline at end of file diff --git a/templates/SPAuthorization.html b/templates/SPAuthorization.html index 6ab2cddc3f0c26a4399392bc24a4951be19710e3..2ac833991d0302bf9a36374ea472fa02ee7aa8a9 100644 --- a/templates/SPAuthorization.html +++ b/templates/SPAuthorization.html @@ -4,9 +4,10 @@ <title>Authorization page</title> {% endblock %} -{% block body %} +{% block content %} <div class="content"> - <h1 style="text-align: center">SPAuthorization page</h1> - <h1 style="text-align: center"> <a href="{{ registration_url }}">register here</a></h1> + <h1 style="text-align: center"><span>{{ _("You are not authorized to access the service ") }}</span> {{ _("service") }}</h1> + <h1 style="text-align: center"><span>{{ _('We will now redirect you to a registration page, where you will apply for the access.') }}</span></h1> + <h1 style="text-align: center"> <a href="{{ registration_url }}"><span>{{ _("Proceed to registration") }}</span></a></h1> </div> {% endblock %} \ No newline at end of file diff --git a/templates/_footer.html b/templates/_footer.html index a76e4b6436dd7381550a5e26fcecff4ed0e4a9ac..b8fa36acdc05bf53fd4e7d3fe0fd74e5816728e8 100644 --- a/templates/_footer.html +++ b/templates/_footer.html @@ -1,40 +1,40 @@ <!DOCTYPE html> -{% if footer is not none and sections is not none %} - {% if css_framework == 'MUNI' %} - {% if current_section is not none %} - {% set colSize = 4 / current_section | length %} +{% if cfg.footer is not none and cfg.footer.sections is not none %} + {% if cfg.css_framework == 'MUNI' %} + {% if cfg.footer.sections[lang] is not none %} + {% set colSize = 4 / cfg.footer.sections[lang] | length %} {% else %} - {% set colSize = 4 / sections | length %} + {% set colSize = 4 / cfg.sections | length %} {% endif %} {% else %} - {% if current_section is not none %} - {% set colSize = 12 / current_section | length %} + {% if cfg.footer.sections[lang] is not none %} + {% set colSize = 12 / cfg.footer.sections[lang] | length %} {% else %} - {% set colSize = 12 / sections | length %} + {% set colSize = 12 / cfg.footer.sections | length %} {% endif %} {% endif %} - <footer class="footer text-left{% if not css_framework == 'MUNI' %} bg-secondary secondary-contrast-color{% endif %}"> - <div class="{% if css_framework == 'MUNI' %}grid{% else %}row{% endif%} footer-margin"> - {% if current_section is not none %} - {% for block in current_section %} - {% if format is not none and (format == 'HTML' or format == 'markdown') %} - <div class="{% if css_framework == 'MUNI' %}grid__cell size--m--{{ colSize }}-4{% else %}col-padding-0 col-md-{{ colSize }}{% endif %}"> - {{ block }} + <footer class="footer text-left{% if not cfg.css_framework == 'MUNI' %} bg-secondary secondary-contrast-color{% endif %}"> + <div class="{% if cfg.css_framework == 'MUNI' %}grid{% else %}row{% endif%} footer-margin"> + {% if cfg.footer.sections[lang] is not none %} + {% for block in cfg.footer.sections[lang] %} + {% if cfg.footer.format is not none and (cfg.footer.format == 'HTML' or cfg.footer.format == 'markdown') %} + <div class="{% if cfg.css_framework == 'MUNI' %}grid__cell size--m--{{ colSize }}-4{% else %}col-padding-0 col-md-{{ colSize }}{% endif %}"> + {{ block |safe}} </div> {% else %} - <div class="{% if css_framework == 'MUNI' %}grid__cell size--m--{{ colSize }}-4{% else %}col-padding-0 col-md-{{ colSize }}{% endif %}"> + <div class="{% if cfg.css_framework == 'MUNI' %}grid__cell size--m--{{ colSize }}-4{% else %}col-padding-0 col-md-{{ colSize }}{% endif %}"> {{ block }} </div> {% endif %} {% endfor %} {% else %} - {% for block in sections %} - {% if format is not none and (format == 'HTML' or format == 'markdown') %} - <div class="{% if css_framework == 'MUNI' %}grid__cell size--m--{{ colSize }}-4{% else %}col-padding-0 col-md-{{ colSize }}{% endif %}"> - {{ block }} + {% for block in cfg.footer.sections %} + {% if cfg.footer.format is not none and (cfg.footer.format == 'HTML' or cfg.footer.format == 'markdown') %} + <div class="{% if cfg.css_framework == 'MUNI' %}grid__cell size--m--{{ colSize }}-4{% else %}col-padding-0 col-md-{{ colSize }}{% endif %}"> + {{ block |safe}} </div> {% else %} - <div class="{% if css_framework == 'MUNI'%}grid__cell size--m--{{ colSize }}-4{% else %}col-padding-0 col-md-{{ colSize }}{% endif %}"> + <div class="{% if cfg.css_framework == 'MUNI'%}grid__cell size--m--{{ colSize }}-4{% else %}col-padding-0 col-md-{{ colSize }}{% endif %}"> {{ block }} </div> {% endif %} diff --git a/templates/_header.html b/templates/_header.html index 1c05f0defa87291b0a2ce41b3f49d2a83930eb20..4a2143268b20fc4f1163aa837a1f5dd98041e857 100644 --- a/templates/_header.html +++ b/templates/_header.html @@ -1,36 +1,36 @@ <!DOCTYPE html> -{% if css_framework == 'MUNI' %} +{% if cfg.css_framework == 'MUNI' %} <header class="header"> <div class="row-main header__wrap"> <div class="grid"> <div class="grid__cell size--m--2-4 push--m--2-4 center"> <div class="header__side"> - {% if languages | length > 2 %} + {% if cfg.languages | length > 2 %} <nav class="menu-lang menu-lang--select" aria-label="{{ _('lang_selection') }}"> <p class="menu-lang__selected"> - {% if current_language is not none %} + {% if lang in cfg.languages %} <a href="#" class="menu-lang__selected__link"> - {{ current_language }} + {{ cfg.languages[lang] }} </a> {% endif %} </p> <p class="menu-lang__popup"> - {% for langKey, langName in languages.items() %} - {% if langName != current_language and currentUrl ~ "&language=" ~ langKey %} - <a href="{{ currentUrl ~ "?language=" ~ langKey }}{%- for name, value in queryParams.items() %}{{ "&" ~ name ~ "=" ~ value }}{%- endfor %}" + {% for langKey, langName in cfg.languages.items() %} + {% if langName != cfg.languages[lang] and request.base_url ~ "&lang=" ~ langKey %} + <a href="{{ request.base_url ~ "?lang=" ~ langKey }}{%- for name, value in request.args.items() %}{{ '' if name == "lang" else "&" ~ name ~ "=" ~ value }}{%- endfor %}" rel="alternate" hreflang="{{ langKey }}" lang="{{ langKey }}" class="menu-lang__popup__link"> {{ langName }} </a> {% endif %} {% endfor %} - </p> b + </p> </nav> {% else %} <nav class="menu-lang" aria-label="{{ _('lang_selection') }}"> <p class="menu-lang__selected"> - {% for langKey, langName in languages.items() %} - {% if langName != current_language and currentUrl ~ "&language=" ~ langKey %} - <a href="{{ currentUrl ~ "?language=" ~ langKey }}{%- for name, value in queryParams.items() %}{{ "&" ~ name ~ "=" ~ value }}{%- endfor %}" + {% for langKey, langName in cfg.languages.items() %} + {% if langName != cfg.languages[lang] and request.base_url ~ "&lang=" ~ langKey %} + <a href="{{ request.base_url ~ "?lang=" ~ langKey }}{%- for name, value in request.args.items() %}{{ '' if name == "lang" else "&" ~ name ~ "=" ~ value }}{%- endfor %}" rel="alternate" hreflang="{{ langKey }}" lang="{{ langKey }}" class="menu-lang__selected__link"> {{ langName }} </a> @@ -44,10 +44,10 @@ <div class="row-main"> <ul class="menu-mobile__list"> {% set counter = 0 %} - {% for langKey, langName in languages.items() %} - {% if counter < 5 and langName != current_language and currentUrl ~ "&language=" ~ langKey %} + {% for langKey, langName in cfg.languages.items() %} + {% if counter < 5 and langName != cfg.languages[lang] and request.base_url ~ "&lang=" ~ langKey %} <li class="menu-mobile__item"> - <a href="{{ currentUrl ~ "?language=" ~ langKey }}{%- for name, value in queryParams.items() %}{{ "&" ~ name ~ "=" ~ value }}{%- endfor %}" + <a href="{{ request.base_url ~ "?lang=" ~ langKey }}{%- for name, value in request.args.items() %}{{ '' if name == "lang" else "&" ~ name ~ "=" ~ value }}{%- endfor %}" rel="alternate" hreflang="{{ langKey }}" lang="{{ langKey }}" class="menu-mobile__link menu-mobile__link--lang"> {{ langKey|upper }} </a> @@ -62,7 +62,7 @@ </div> </div> <div class="grid__cell size--m--2-4 pull--m--2-4 center"> - <img src="{% if logo is not none %}{{ logo }}{% endif %}" class="header-img" alt="{% if name is not none %}{{ name }}{% endif %}"/> + <img src="{% if cfg.logo is not none %}{{ cfg.logo }}{% endif %}" class="header-img" alt="{% if cfg.name is not none %}{{ cfg.name }}{% endif %}"/> </div> </div> </div> @@ -72,20 +72,20 @@ <div class="container"> <div class="row"> <div class="col-md-6 order-md-last text-md-end"> - {% if languages | length > 2 %} + {% if cfg.languages | length > 2 %} <div class="dropdown language-bar mt-3"> <a id="dropdown-language" class="btn btn-secondary dropdown-toggle text-primary bg-white border-0" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false"> - {% if current_language is not none %} - <span class="d-md-none">{{ current_language | upper }}</span><span class="d-none d-md-inline">{{ attribute(languages, current_language) }}</span> + {% if lang in cfg.languages %} + <span class="d-md-none">{{ cfg.languages[lang] | upper }}</span><span class="d-none d-md-inline">{{ cfg.languages[lang] }}</span> {% else %} {{ current_language | upper }} {% endif %} </a> <ul class="dropdown-menu" aria-labelledby="dropdown-language"> - {% for langKey, langName in languages.items() %} - {% if langName != current_language %} + {% for langKey, langName in cfg.languages.items() %} + {% if langName != cfg.languages[lang] %} <li> - <a class="dropdown-item text-primary" href="{{ currentUrl ~ "?language=" ~ langKey }}{%- for name, value in queryParams.items() %}{{ "&" ~ name ~ "=" ~ value }}{%- endfor %}"> + <a class="dropdown-item text-primary" href="{{ request.base_url ~ "?lang=" ~ langKey }}{%- for name, value in request.args.items() %}{{ '' if name == "lang" else "&" ~ name ~ "=" ~ value }}{%- endfor %}"> <span class="d-md-none">{{ langKey | upper }}</span><span class="d-none d-md-inline">{{ langName }}</span> </a> </li> @@ -95,9 +95,9 @@ </div> {% else %} <p class="language-bar mt-3"> - {% for langKey, langName in languages.items() %} - {% if langName != current_language and currentUrl ~ "&language=" ~ langKey %} - <a href="{{ currentUrl ~ "?language=" ~ langKey }}{%- for name, value in queryParams.items() %}{{ "&" ~ name ~ "=" ~ value }}{%- endfor %}" + {% for langKey, langName in cfg.languages.items() %} + {% if langName != cfg.languages[lang] and request.base_url ~ "&lang=" ~ langKey %} + <a href="{{ request.base_url ~ "?lang=" ~ langKey }}{%- for name, value in request.args.items() %}{{ '' if name == "lang" else "&" ~ name ~ "=" ~ value }}{%- endfor %}" rel="alternate" hreflang="{{ langKey }}" lang="{{ langKey }}" class="text-decoration-none text-primary"> <span class="d-md-none">{{ langKey | upper }}</span><span class="d-none d-md-inline">{{ langName }}</span> </a> @@ -107,7 +107,7 @@ {% endif %} </div> <div class="col-md-6 order-md-first text-md-start"> - <img src="{% if logo is not none %}{{ logo }}{% endif %}" class="header-img mt-3" alt="{% if name is not none %}{{ name }}{% endif %}"/> + <img src="{% if cfg.logo is not none %}{{ cfg.logo }}{% endif %}" class="header-img mt-3" alt="{% if cfg.name is not none %}{{ cfg.name }}{% endif %}"/> </div> </div> </div> diff --git a/templates/authorization.html b/templates/authorization.html index 79f28044b57f350764c8e791d56349ad07d36aa7..c08054e12c5fa64ce1c3ac783b223da4baf2f20b 100644 --- a/templates/authorization.html +++ b/templates/authorization.html @@ -4,10 +4,10 @@ <title>Authorization page</title> {% endblock %} -{% block body %} +{% block content %} <div class="content"> - <h1 style="text-align: center">Authorization page</h1> - <h1 style="text-align: center"><span>{{ _('service') }}</span>: {{service}}</h1> - <h1 style="text-align: center">email: {{email}}</h1> + <h1 style="text-align: center"><span>{{ _("You are not authorized to access the service ") }}</span> <span>{{ _("service") }}</span></h1> + <h1 style="text-align: center"><span>{{ _('We will now redirect you to a registration page, where you will apply for the access.') }}</span></h1> + <h1 style="text-align: center"> <a href="{{ registration_url }}"><span>{{ _("Proceed to registration") }}</span></a></h1> </div> {% endblock %} \ No newline at end of file diff --git a/templates/base.html b/templates/base.html index 4d54fa4ffa805a663013c3379c3bbfe83c2c7155..5aa9de53d883156f755a4625b625f0bebf2ed341 100644 --- a/templates/base.html +++ b/templates/base.html @@ -8,14 +8,14 @@ {# skip default CSS, favicon and JavaScript #} <meta name="robots" content="noindex, nofollow"> {% block preload %} - {% if css_framework == 'MUNI' %} - <link rel="stylesheet" type="text/css" href="/static/MuniWeb/css/style{% if faculty is not none%}-{{ faculty }}{% endif %}.css" /> + {% if cfg.css_framework == 'MUNI' %} + <link rel="stylesheet" type="text/css" href="/static/MuniWeb/css/style{% if cfg.MUNI_faculty is not none%}-{{ cfg.MUNI_faculty }}{% endif %}.css" /> {% else %} <link href="/static/bootstrap/css/bootstrap.min.css" rel="stylesheet"> {% endif %} {% endblock %} </head> - <body id="{{ templateId }}" class="{% if css_framework == 'MUNI' %}framework_muni{% else %}framework_bootstrap5{% endif %}"> + <body id="{{ templateId }}" class="{% if cfg.css_framework == 'MUNI' %}framework_muni{% else %}framework_bootstrap5{% endif %}"> <div id="layout"> {% block header %}{% include "_header.html" %}{% endblock %} {% block contentwrapper %} @@ -31,7 +31,7 @@ {% block footer %}{% include "_footer.html" %}{% endblock %} </div> {% block postload %} - {% if css_framework == 'MUNI' %} + {% if cfg.css_framework == 'MUNI' %} <script src="/static/jquery-3.6.0.min.js"></script> <script src="/static/MuniWeb/js/app.js"></script> <script src="/static/campus-idp-muni.js"></script> diff --git a/translations/cs/LC_MESSAGES/messages.po b/translations/cs/LC_MESSAGES/messages.po new file mode 100644 index 0000000000000000000000000000000000000000..9386759a3dd28647ebd167a86a8b50611b9c6ff7 --- /dev/null +++ b/translations/cs/LC_MESSAGES/messages.po @@ -0,0 +1,61 @@ +# Czech translations for PROJECT. +# Copyright (C) 2022 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR <EMAIL@ADDRESS>, 2022. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2022-09-19 01:27+0200\n" +"PO-Revision-Date: 2022-09-12 21:11+0200\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language: cs\n" +"Language-Team: cs <LL@li.org>\n" +"Plural-Forms: nplurals=3; plural=((n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2);\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.10.3\n" + +#: app.py:67 +msgid "fail" +msgstr "selhání" + +#: app.py:67 +msgid "Missing request parameter" +msgstr "Chybí požadovaný parametr" + +#: templates/IsTestingSP.html:9 +msgid "You are about to access service, which is in testing environment." +msgstr "Přistupujete ke službě, která je v testovacím režimu." + +#: templates/IsTestingSP.html:10 +msgid "Continue" +msgstr "Pokračovat" + +#: templates/SPAuthorization.html:9 templates/authorization.html:9 +msgid "You are not authorized to access the service " +msgstr "Nesplňujete autorizační pravidla pro přístup ke službě " + +#: templates/SPAuthorization.html:9 templates/authorization.html:9 +msgid "service" +msgstr "služba" + +#: templates/SPAuthorization.html:10 templates/authorization.html:10 +msgid "" +"We will now redirect you to a registration page, where you will apply for" +" the access." +msgstr "Budete přesmerován(a) na stránku, kde můžete o p%rístup na službu zažádat." + +#: templates/SPAuthorization.html:11 templates/authorization.html:11 +msgid "Proceed to registration" +msgstr "Pokračovat na registrační stránk" + +#: templates/_header.html:9 templates/_header.html:29 +msgid "lang_selection" +msgstr "" + +#: templates/_header.html:42 +msgid "mobile_lang_selection" +msgstr ""