Integrate MAS with Synapse
This commit is contained in:
27
mas/share/templates/pages/404.html
Normal file
27
mas/share/templates/pages/404.html
Normal file
@@ -0,0 +1,27 @@
|
||||
{#
|
||||
Copyright 2024, 2025 New Vector Ltd.
|
||||
Copyright 2023, 2024 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
-#}
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<main class="w-96 flex-1 flex flex-col gap-2 justify-center">
|
||||
<h1 class="text-xl font-semibold">{{ _("mas.not_found.heading") }}</h1>
|
||||
<p>{{ _("mas.not_found.description") }}</p>
|
||||
<div>
|
||||
{{ button.link_text(text=_("mas.back_to_homepage"), href="/") }}
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<code>
|
||||
<pre class="whitespace-pre-wrap break-all">{{ method }} {{ uri }} {{ version }}
|
||||
|
||||
{{ version }} 404 Not Found</pre>
|
||||
</code>
|
||||
</main>
|
||||
{% endblock %}
|
||||
26
mas/share/templates/pages/account/deactivated.html
Normal file
26
mas/share/templates/pages/account/deactivated.html
Normal file
@@ -0,0 +1,26 @@
|
||||
{#
|
||||
Copyright 2025 New Vector Ltd.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
-#}
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<main class="flex flex-col gap-6">
|
||||
<header class="page-heading">
|
||||
<div class="icon invalid">
|
||||
{{ icon.delete() }}
|
||||
</div>
|
||||
|
||||
<div class="header">
|
||||
<h1 class="title">{{ _("mas.account.deactivated.heading") }}</h1>
|
||||
{% set mxid = "@" + user.username + ":" + branding.server_name %}
|
||||
<p class="text">{{ _("mas.account.deactivated.description", mxid=mxid) }}</p>
|
||||
</div>
|
||||
|
||||
{{ logout.button(text=_("action.sign_in"), csrf_token=csrf_token) }}
|
||||
</header>
|
||||
</main>
|
||||
{% endblock %}
|
||||
26
mas/share/templates/pages/account/locked.html
Normal file
26
mas/share/templates/pages/account/locked.html
Normal file
@@ -0,0 +1,26 @@
|
||||
{#
|
||||
Copyright 2025 New Vector Ltd.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
-#}
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<main class="flex flex-col gap-6">
|
||||
<header class="page-heading">
|
||||
<div class="icon invalid">
|
||||
{{ icon.block() }}
|
||||
</div>
|
||||
|
||||
<div class="header">
|
||||
<h1 class="title">{{ _("mas.account.locked.heading") }}</h1>
|
||||
{% set mxid = "@" + user.username + ":" + branding.server_name %}
|
||||
<p class="text">{{ _("mas.account.locked.description", mxid=mxid) }}</p>
|
||||
</div>
|
||||
|
||||
{{ logout.button(text=_("action.sign_in"), csrf_token=csrf_token) }}
|
||||
</header>
|
||||
</main>
|
||||
{% endblock %}
|
||||
25
mas/share/templates/pages/account/logged_out.html
Normal file
25
mas/share/templates/pages/account/logged_out.html
Normal file
@@ -0,0 +1,25 @@
|
||||
{#
|
||||
Copyright 2025 New Vector Ltd.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
-#}
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<main class="flex flex-col gap-6">
|
||||
<header class="page-heading">
|
||||
<div class="icon invalid">
|
||||
{{ icon.leave() }}
|
||||
</div>
|
||||
|
||||
<div class="header">
|
||||
<h1 class="title">{{ _("mas.account.logged_out.heading") }}</h1>
|
||||
<p class="text">{{ _("mas.account.logged_out.description") }}</p>
|
||||
</div>
|
||||
|
||||
{{ logout.button(text=_("action.sign_out"), csrf_token=csrf_token) }}
|
||||
</header>
|
||||
</main>
|
||||
{% endblock %}
|
||||
76
mas/share/templates/pages/consent.html
Normal file
76
mas/share/templates/pages/consent.html
Normal file
@@ -0,0 +1,76 @@
|
||||
{#
|
||||
Copyright 2024, 2025 New Vector Ltd.
|
||||
Copyright 2022-2024 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
-#}
|
||||
|
||||
{% set consent_page = true %}
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
{% set client_name = client.client_name or client.client_id %}
|
||||
<header class="page-heading">
|
||||
{% if client.logo_uri %}
|
||||
<img class="consent-client-icon image" referrerpolicy="no-referrer" src="{{ client.logo_uri }}" />
|
||||
{% else %}
|
||||
<div class="consent-client-icon generic">
|
||||
{{ icon.web_browser() }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="header">
|
||||
<h1 class="title">{{ _("mas.consent.heading") }}</h1>
|
||||
<p class="text [&>span]:whitespace-nowrap">
|
||||
{{ _("mas.consent.client_wants_access", client_name=client_name, redirect_uri=(grant.redirect_uri | simplify_url)) }}
|
||||
{{ _("mas.consent.this_will_allow", client_name=client_name) }}
|
||||
</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section class="consent-scope-list">
|
||||
{{ scope.list(scopes=grant.scope) }}
|
||||
</section>
|
||||
|
||||
<section class="text-center cpd-text-secondary cpd-text-body-md-regular [&>span]:whitespace-nowrap">
|
||||
<strong class="font-semibold cpd-text-primary [&>span]:whitespace-nowrap">{{ _("mas.consent.make_sure_you_trust", client_name=client_name) }}</strong>
|
||||
{{ _("mas.consent.you_may_be_sharing") }}
|
||||
{% if client.policy_uri or client.tos_uri %}
|
||||
Find out how <span>{{ client_name }}</span> will handle your data by reviewing its
|
||||
{% if client.policy_uri %}
|
||||
<a target="_blank" href="{{ client.policy_uri }}" class="cpd-link" data-kind="primary">privacy policy</a>{% if not client.tos_uri %}.{% endif %}
|
||||
{% endif %}
|
||||
{% if client.policy_uri and client.tos_uri%}
|
||||
and
|
||||
{% endif %}
|
||||
{% if client.tos_uri %}
|
||||
<a target="_blank" href="{{ client.tos_uri }}" class="cpd-link" data-kind="primary">terms of service</a>.
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</section>
|
||||
|
||||
<section class="flex flex-col gap-6">
|
||||
<form method="POST" class="cpd-form-root">
|
||||
<input type="hidden" name="csrf" value="{{ csrf_token }}" />
|
||||
{{ button.button(text=_("action.continue")) }}
|
||||
</form>
|
||||
|
||||
<div class="flex gap-1 justify-center items-center">
|
||||
<p class="cpd-text-secondary cpd-text-body-md-regular">
|
||||
{{ _("mas.not_you", username=current_session.user.username) }}
|
||||
</p>
|
||||
|
||||
{{ logout.button(text=_("action.sign_out"), csrf_token=csrf_token, post_logout_action=action, as_link=true) }}
|
||||
</div>
|
||||
|
||||
{{ back_to_client.link(
|
||||
text=_("action.cancel"),
|
||||
kind="tertiary",
|
||||
uri=grant.redirect_uri,
|
||||
mode=grant.response_mode,
|
||||
params=dict(error="access_denied", state=grant.state)
|
||||
) }}
|
||||
</section>
|
||||
{% endblock content %}
|
||||
162
mas/share/templates/pages/device_consent.html
Normal file
162
mas/share/templates/pages/device_consent.html
Normal file
@@ -0,0 +1,162 @@
|
||||
{#
|
||||
Copyright 2024, 2025 New Vector Ltd.
|
||||
Copyright 2023, 2024 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
-#}
|
||||
|
||||
{% set consent_page = true %}
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
{% set client_name = client.client_name or client.client_id %}
|
||||
{% set user_agent = grant.user_agent | parse_user_agent() %}
|
||||
|
||||
{% if grant.state == "pending" %}
|
||||
<header class="page-heading">
|
||||
{% if client.logo_uri %}
|
||||
<img class="consent-client-icon image" referrerpolicy="no-referrer" src="{{ client.logo_uri }}" />
|
||||
{% else %}
|
||||
<div class="consent-client-icon generic">
|
||||
{{ icon.web_browser() }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="header">
|
||||
<h1 class="title">{{ _("mas.consent.heading") }}</h1>
|
||||
|
||||
<div class="session-card my-4">
|
||||
<div class="card-header" {%- if user_agent %} title="{{ user_agent.raw }}"{% endif %}>
|
||||
<div class="device-type-icon">
|
||||
{% if user_agent.device_type == "mobile" %}
|
||||
{{ icon.mobile() }}
|
||||
{% elif user_agent.device_type == "tablet" %}
|
||||
{{ icon.web_browser() }}
|
||||
{% elif user_agent.device_type == "pc" %}
|
||||
{{ icon.computer() }}
|
||||
{% else %}
|
||||
{{ icon.unknown_solid() }}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="content auto">
|
||||
{% if user_agent.model %}
|
||||
<div>{{ user_agent.model }}</div>
|
||||
{% endif %}
|
||||
|
||||
{% if user_agent.os %}
|
||||
<div>
|
||||
{{ user_agent.os }}
|
||||
{% if user_agent.os_version %}
|
||||
{{ user_agent.os_version }}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# If we haven't detected a model, it's probably a browser, so show the name #}
|
||||
{% if not user_agent.model and user_agent.name %}
|
||||
<div>
|
||||
{{ user_agent.name }}
|
||||
{% if user_agent.version %}
|
||||
{{ user_agent.version }}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# If we couldn't detect anything, show a generic "Device" #}
|
||||
{% if not user_agent.model and not user_agent.name and not user_agent.os %}
|
||||
<div>{{ _("mas.device_card.generic_device") }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="metadata">
|
||||
{% if grant.ip_address %}
|
||||
<div>
|
||||
<div class="key">{{ _("mas.device_card.ip_address") }}</div>
|
||||
<div class="value">{{ grant.ip_address }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div>
|
||||
<div class="key">{{ _("mas.device_card.access_requested") }}</div>
|
||||
<div class="value">{{ _.relative_date(grant.created_at) | title }} {{ _.short_time(grant.created_at) }}</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="key">{{ _("mas.device_card.device_code") }}</div>
|
||||
<div class="value">{{ grant.user_code }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="text [&>span]:whitespace-nowrap">
|
||||
{{ _("mas.device_consent.another_device_access") }}
|
||||
{{ _("mas.consent.this_will_allow", client_name=client_name) }}
|
||||
</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section class="consent-scope-list">
|
||||
{{ scope.list(scopes=grant.scope) }}
|
||||
</section>
|
||||
|
||||
<section class="text-center text-balance cpd-text-secondary cpd-text-body-md-regular [&>span]:whitespace-nowrap">
|
||||
<strong class="font-semibold cpd-text-primary [&>span]:whitespace-nowrap">{{ _("mas.consent.make_sure_you_trust", client_name=client_name) }}</strong>
|
||||
{{ _("mas.consent.you_may_be_sharing") }}
|
||||
{% if client.policy_uri or client.tos_uri %}
|
||||
Find out how <span>{{ client_name }}</span> will handle your data by reviewing its
|
||||
{% if client.policy_uri %}
|
||||
<a target="_blank" href="{{ client.policy_uri }}" class="cpd-link" data-kind="primary">privacy policy</a>{% if not client.tos_uri %}.{% endif %}
|
||||
{% endif %}
|
||||
{% if client.policy_uri and client.tos_uri%}
|
||||
and
|
||||
{% endif %}
|
||||
{% if client.tos_uri %}
|
||||
<a target="_blank" href="{{ client.tos_uri }}" class="cpd-link" data-kind="primary">terms of service</a>.
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</section>
|
||||
|
||||
<section class="flex flex-col gap-6">
|
||||
<form method="POST" class="cpd-form-root">
|
||||
<input type="hidden" name="csrf" value="{{ csrf_token }}" />
|
||||
<button type="submit" name="action" value="consent" class="cpd-button" data-kind="primary" data-size="lg">
|
||||
{{ _("action.continue") }}
|
||||
</button>
|
||||
<button type="submit" name="action" value="reject" class="cpd-button destructive" data-kind="secondary" data-size="lg">
|
||||
{{ _("action.cancel") }}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<div class="flex gap-1 justify-center items-center">
|
||||
<p class="cpd-text-secondary cpd-text-body-md-regular">
|
||||
{{ _("mas.not_you", username=current_session.user.username) }}
|
||||
</p>
|
||||
|
||||
{{ logout.button(text=_("action.sign_out"), csrf_token=csrf_token, post_logout_action=action, as_link=true) }}
|
||||
</div>
|
||||
</section>
|
||||
{% elif grant.state == "rejected" %}
|
||||
<header class="page-heading">
|
||||
<div class="icon invalid">
|
||||
{{ icon.block() }}
|
||||
</div>
|
||||
|
||||
<div class="header">
|
||||
<h1 class="title">{{ _("mas.device_consent.denied.heading") }}</h1>
|
||||
<p class="text">{{ _("mas.device_consent.denied.description", client_name=client_name) }}</p>
|
||||
</div>
|
||||
</header>
|
||||
{% else %}
|
||||
<header class="page-heading">
|
||||
<div class="icon success">
|
||||
{{ icon.check() }}
|
||||
</div>
|
||||
|
||||
<div class="header">
|
||||
<h1 class="title">{{ _("mas.device_consent.granted.heading") }}</h1>
|
||||
<p class="text">{{ _("mas.device_consent.granted.description", client_name=client_name) }}</p>
|
||||
</div>
|
||||
</header>
|
||||
{% endif %}
|
||||
{% endblock content %}
|
||||
42
mas/share/templates/pages/device_link.html
Normal file
42
mas/share/templates/pages/device_link.html
Normal file
@@ -0,0 +1,42 @@
|
||||
{#
|
||||
Copyright 2024, 2025 New Vector Ltd.
|
||||
Copyright 2023, 2024 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
-#}
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<header class="page-heading">
|
||||
<div class="icon">
|
||||
{{ icon.link() }}
|
||||
</div>
|
||||
|
||||
<div class="header">
|
||||
<h1 class="title">{{ _("mas.device_code_link.headline") }}</h1>
|
||||
<p class="text">{{ _("mas.device_code_link.description") }}</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<form method="GET" class="cpd-form-root">
|
||||
{% call(f) field.field(label="Device code", name="code", class="mb-4 self-center", form_state=form_state) %}
|
||||
<div class="cpd-mfa-container">
|
||||
<input {{ field.attributes(f) }}
|
||||
id="mfa-code-input"
|
||||
type="text"
|
||||
minlength="0"
|
||||
maxlength="6"
|
||||
class="cpd-mfa-control uppercase"
|
||||
required>
|
||||
|
||||
{% for _ in range(6) %}
|
||||
<div class="cpd-mfa-digit" aria-hidden="true"></div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endcall %}
|
||||
|
||||
{{ button.button(text=_("action.continue")) }}
|
||||
</form>
|
||||
{% endblock content %}
|
||||
42
mas/share/templates/pages/error.html
Normal file
42
mas/share/templates/pages/error.html
Normal file
@@ -0,0 +1,42 @@
|
||||
{#
|
||||
Copyright 2024, 2025 New Vector Ltd.
|
||||
Copyright 2021-2024 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
-#}
|
||||
|
||||
{# Sometimes we don't have the language set, so we default to english #}
|
||||
{% set lang = lang or "en" %}
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<main class="flex flex-col gap-6">
|
||||
<header class="page-heading">
|
||||
<div class="icon invalid">
|
||||
{{ icon.error_solid() }}
|
||||
</div>
|
||||
|
||||
<div class="header">
|
||||
<h1 class="title">{{ _("error.unexpected") }}</h1>
|
||||
{% if code %}
|
||||
<p class="text font-semibold font-mono">
|
||||
{{ code }}
|
||||
</p>
|
||||
{% endif %}
|
||||
{% if description %}
|
||||
<p class="text">
|
||||
{{ description }}
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</header>
|
||||
|
||||
{% if details %}
|
||||
<hr />
|
||||
{# caution: do not introduce whitespace between <pre> and <code> #}
|
||||
<pre><code class="font-mono whitespace-pre-wrap break-all">{{ details }}</code></pre>
|
||||
{% endif %}
|
||||
</main>
|
||||
{% endblock %}
|
||||
37
mas/share/templates/pages/index.html
Normal file
37
mas/share/templates/pages/index.html
Normal file
@@ -0,0 +1,37 @@
|
||||
{#
|
||||
Copyright 2024, 2025 New Vector Ltd.
|
||||
Copyright 2021-2024 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
-#}
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<main class="flex flex-col justify-center gap-6">
|
||||
<header class="page-heading">
|
||||
<div class="header">
|
||||
<h1 class="title">{{ _("app.human_name") }}</h1>
|
||||
<p class="text">
|
||||
{{ _("app.technical_description", discovery_url=discovery_url) }}
|
||||
</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
{% if current_session is not none %}
|
||||
<p class="cpd-text-body-md-regular">
|
||||
{{ _("mas.navbar.signed_in_as", username=current_session.user.username) }}
|
||||
</p>
|
||||
|
||||
{{ button.link(text=_("mas.navbar.my_account"), href="/account/") }}
|
||||
{{ logout.button(text=_("action.sign_out"), csrf_token=csrf_token) }}
|
||||
{% else %}
|
||||
{{ button.link(text=_("action.sign_in"), href="/login") }}
|
||||
|
||||
{% if features.password_registration %}
|
||||
{{ button.link_outline(text=_("mas.navbar.register"), href="/register") }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</main>
|
||||
{% endblock content %}
|
||||
104
mas/share/templates/pages/login.html
Normal file
104
mas/share/templates/pages/login.html
Normal file
@@ -0,0 +1,104 @@
|
||||
{#
|
||||
Copyright 2024, 2025 New Vector Ltd.
|
||||
Copyright 2021-2024 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
-#}
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% from "components/idp_brand.html" import logo %}
|
||||
|
||||
{% block content %}
|
||||
<form method="POST" class="flex flex-col gap-10">
|
||||
<header class="page-heading">
|
||||
<div class="icon">
|
||||
{{ icon.user_profile_solid() }}
|
||||
</div>
|
||||
|
||||
{% if next and next.kind == "link_upstream" %}
|
||||
<div class="header">
|
||||
<h1 class="title">{{ _("mas.login.link.headline") }}</h1>
|
||||
{% set name = provider.human_name or (provider.issuer | simplify_url(keep_path=True)) or provider.id %}
|
||||
<p class="text">{{ _("mas.login.link.description", provider=name) }}</p>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="header">
|
||||
<h1 class="title">{{ _("mas.login.headline") }}</h1>
|
||||
<p class="text">{{ _("mas.login.description") }}</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</header>
|
||||
|
||||
<div class="cpd-form-root">
|
||||
{% if form.errors is not empty %}
|
||||
{% for error in form.errors %}
|
||||
<div class="text-critical font-medium">
|
||||
{{ errors.form_error_message(error=error) }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<input type="hidden" name="csrf" value="{{ csrf_token }}" />
|
||||
|
||||
{% if features.login_with_email_allowed %}
|
||||
{% call(f) field.field(label=_("mas.login.username_or_email"), name="username", form_state=form) %}
|
||||
<input {{ field.attributes(f) }} class="cpd-text-control" type="text" autocomplete="username" autocorrect="off" autocapitalize="off" required />
|
||||
{% endcall %}
|
||||
{% else %}
|
||||
{% call(f) field.field(label=_("common.username"), name="username", form_state=form) %}
|
||||
<input {{ field.attributes(f) }} class="cpd-text-control" type="text" autocomplete="username" autocorrect="off" autocapitalize="off" required />
|
||||
{% endcall %}
|
||||
{% endif %}
|
||||
|
||||
{% if features.password_login %}
|
||||
{% call(f) field.field(label=_("common.password"), name="password", form_state=form) %}
|
||||
<input {{ field.attributes(f) }} class="cpd-text-control" type="password" autocomplete="password" required />
|
||||
{% endcall %}
|
||||
|
||||
{% if features.account_recovery %}
|
||||
{{ button.link_text(text=_("mas.login.forgot_password"), href="/recover", class="self-center") }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="cpd-form-root">
|
||||
{% if features.password_login %}
|
||||
{{ button.button(text=_("action.continue")) }}
|
||||
{% endif %}
|
||||
|
||||
{% if features.password_login and providers %}
|
||||
{{ field.separator() }}
|
||||
{% endif %}
|
||||
|
||||
{% if providers %}
|
||||
{% set params = next["params"] | default({}) | to_params(prefix="?") %}
|
||||
{% for provider in providers %}
|
||||
{% set name = provider.human_name or (provider.issuer | simplify_url(keep_path=True)) or provider.id %}
|
||||
<a class="cpd-button {%- if provider.brand_name %} has-icon {%- endif %}" data-kind="secondary" data-size="lg" href="{{ ('/upstream/authorize/' ~ provider.id ~ params) | prefix_url }}">
|
||||
{{ logo(provider.brand_name) }}
|
||||
{{ _("mas.login.continue_with_provider", provider=name) }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if (not next or next.kind != "link_upstream") and features.password_registration %}
|
||||
<div class="flex gap-1 justify-center items-center cpd-text-body-md-regular">
|
||||
<p class="cpd-text-secondary">
|
||||
{{ _("mas.login.call_to_register") }}
|
||||
</p>
|
||||
|
||||
{% set params = next["params"] | default({}) | to_params(prefix="?") %}
|
||||
{{ button.link_text(text=_("action.create_account"), href="/register" ~ params) }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if not providers and not features.password_login %}
|
||||
<div class="text-center">
|
||||
{{ _("mas.login.no_login_methods") }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</form>
|
||||
{% endblock content %}
|
||||
52
mas/share/templates/pages/policy_violation.html
Normal file
52
mas/share/templates/pages/policy_violation.html
Normal file
@@ -0,0 +1,52 @@
|
||||
{#
|
||||
Copyright 2024, 2025 New Vector Ltd.
|
||||
Copyright 2022-2024 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
-#}
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<header class="page-heading">
|
||||
<div class="icon invalid">
|
||||
{{ icon.error_solid() }}
|
||||
</div>
|
||||
|
||||
<div class="header">
|
||||
<h1 class="title">{{ _("mas.policy_violation.heading") }}</h1>
|
||||
<p class="text">{{ _("mas.policy_violation.description") }}</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="flex flex-col gap-10">
|
||||
<div class="flex items-center justify-center gap-4">
|
||||
<div class="bg-white rounded w-16 h-16 overflow-hidden">
|
||||
{% if client.logo_uri %}
|
||||
<img referrerpolicy="no-referrer" class="w-16 h-16" src="{{ client.logo_uri }}" />
|
||||
{% endif %}
|
||||
</div>
|
||||
<a target="_blank" href="{{ client.client_uri }}" class="cpd-link" data-kind="primary">{{ client.client_name or client.client_id }}</a>
|
||||
</div>
|
||||
|
||||
<div class="flex gap-1 justify-center items-center">
|
||||
<p class="cpd-text-secondary cpd-text-body-md-regular">
|
||||
{{ _("mas.policy_violation.logged_as", username=current_session.user.username) }}
|
||||
</p>
|
||||
|
||||
{{ logout.button(text=_("action.sign_out"), csrf_token=csrf_token, post_logout_action=action, as_link=True) }}
|
||||
</div>
|
||||
|
||||
{# We only show the cancel button if we're in an authorization code flow, not in the device code flow. #}
|
||||
{% if grant.grant_type == "authorization_code" %}
|
||||
{{ back_to_client.link(
|
||||
text=_("action.cancel"),
|
||||
destructive=True,
|
||||
uri=grant.redirect_uri,
|
||||
mode=grant.response_mode,
|
||||
params=dict(error="access_denied", state=grant.state)
|
||||
) }}
|
||||
{% endif %}
|
||||
</main>
|
||||
{% endblock content %}
|
||||
54
mas/share/templates/pages/reauth.html
Normal file
54
mas/share/templates/pages/reauth.html
Normal file
@@ -0,0 +1,54 @@
|
||||
{#
|
||||
Copyright 2024, 2025 New Vector Ltd.
|
||||
Copyright 2021-2024 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
-#}
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<header class="page-heading">
|
||||
<div class="icon">
|
||||
{{ icon.lock() }}
|
||||
</div>
|
||||
|
||||
<div class="header">
|
||||
<h1 class="title">Hi {{ current_session.user.username }}</h1>
|
||||
<p class="text">To continue, please verify it's you:</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="flex flex-col gap-6">
|
||||
<form method="POST" class="cpd-form-root">
|
||||
<input type="hidden" name="csrf" value="{{ csrf_token }}" />
|
||||
{# TODO: errors #}
|
||||
|
||||
{% call(f) field.field(label=_("common.password"), name="password", form_state=form) %}
|
||||
<input {{ field.attributes(f) }} class="cpd-text-control" type="password" autocomplete="password" required />
|
||||
{% endcall %}
|
||||
|
||||
{{ button.button(text=_("action.continue")) }}
|
||||
</form>
|
||||
|
||||
{% if next and next.kind == "continue_authorization_grant" %}
|
||||
{{ back_to_client.link(
|
||||
text="Cancel",
|
||||
destructive=True,
|
||||
uri=next.grant.redirect_uri,
|
||||
mode=next.grant.response_mode,
|
||||
params=dict(error="access_denied", state=next.grant.state)
|
||||
) }}
|
||||
{% endif %}
|
||||
|
||||
<div class="flex gap-1 justify-center items-center">
|
||||
<p class="cpd-text-secondary cpd-text-body-md-regular">
|
||||
Not {{ current_session.user.username }}?
|
||||
</p>
|
||||
|
||||
{% set post_logout_action = next["params"] | default({}) %}
|
||||
{{ logout.button(text="Sign out", csrf_token=csrf_token, post_logout_action=post_logout_action, as_link=true) }}
|
||||
</div>
|
||||
</main>
|
||||
{% endblock content %}
|
||||
24
mas/share/templates/pages/recovery/consumed.html
Normal file
24
mas/share/templates/pages/recovery/consumed.html
Normal file
@@ -0,0 +1,24 @@
|
||||
{#
|
||||
Copyright 2024, 2025 New Vector Ltd.
|
||||
Copyright 2024 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
-#}
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<header class="page-heading">
|
||||
<div class="icon invalid">
|
||||
{{ icon.error_solid() }}
|
||||
</div>
|
||||
|
||||
<div class="header">
|
||||
<h1 class="title">{{ _("mas.recovery.consumed.heading") }}</h1>
|
||||
<p class="text">{{ _("mas.recovery.consumed.description") }}</p>
|
||||
</div>
|
||||
|
||||
{{ button.link_outline(text=_("action.start_over"), href="/login") }}
|
||||
</header>
|
||||
{% endblock content %}
|
||||
24
mas/share/templates/pages/recovery/disabled.html
Normal file
24
mas/share/templates/pages/recovery/disabled.html
Normal file
@@ -0,0 +1,24 @@
|
||||
{#
|
||||
Copyright 2024, 2025 New Vector Ltd.
|
||||
Copyright 2024 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
-#}
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<header class="page-heading">
|
||||
<div class="icon invalid">
|
||||
{{ icon.lock_solid() }}
|
||||
</div>
|
||||
|
||||
<div class="header">
|
||||
<h1 class="title">{{ _("mas.recovery.disabled.heading") }}</h1>
|
||||
<p class="text">{{ _("mas.recovery.disabled.description") }}</p>
|
||||
</div>
|
||||
|
||||
{{ button.link_outline(text=_("action.back"), href="/login") }}
|
||||
</header>
|
||||
{% endblock content %}
|
||||
32
mas/share/templates/pages/recovery/expired.html
Normal file
32
mas/share/templates/pages/recovery/expired.html
Normal file
@@ -0,0 +1,32 @@
|
||||
{#
|
||||
Copyright 2024, 2025 New Vector Ltd.
|
||||
Copyright 2024 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
-#}
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<header class="page-heading">
|
||||
<div class="icon invalid">
|
||||
{{ icon.error_solid() }}
|
||||
</div>
|
||||
|
||||
<div class="header">
|
||||
<h1 class="title">{{ _("mas.recovery.expired.heading") }}</h1>
|
||||
<p class="text [&>span]:font-medium">{{ _("mas.recovery.expired.description", email=session.email) }}</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="flex flex-col gap-6">
|
||||
<form class="cpd-form-root" method="POST" action="{{ '/recover/progress/' + session.id | prefix_url }}">
|
||||
<input type="hidden" name="csrf" value="{{ csrf_token }}" />
|
||||
|
||||
{{ button.button(text=_("mas.recovery.expired.resend_email"), type="submit") }}
|
||||
</form>
|
||||
|
||||
{{ button.link_outline(text=_("action.start_over"), href="/login") }}
|
||||
</div>
|
||||
{% endblock content %}
|
||||
47
mas/share/templates/pages/recovery/finish.html
Normal file
47
mas/share/templates/pages/recovery/finish.html
Normal file
@@ -0,0 +1,47 @@
|
||||
{#
|
||||
Copyright 2024, 2025 New Vector Ltd.
|
||||
Copyright 2024 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
-#}
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<header class="page-heading">
|
||||
<div class="icon">
|
||||
{{ icon.lock_solid() }}
|
||||
</div>
|
||||
|
||||
<div class="header">
|
||||
<h1 class="title">{{ _("mas.recovery.finish.heading") }}</h1>
|
||||
<p class="text">{{ _("mas.recovery.finish.description") }}</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<form class="cpd-form-root" method="POST">
|
||||
{# Hidden username field so that password manager can save the username #}
|
||||
<input class="hidden" aria-hidden="true" type="text" name="username" autocomplete="username" value="{{ user.username }}" />
|
||||
|
||||
{% if form.errors is not empty %}
|
||||
{% for error in form.errors %}
|
||||
<div class="text-critical font-medium">
|
||||
{{ errors.form_error_message(error=error) }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<input type="hidden" name="csrf" value="{{ csrf_token }}" />
|
||||
|
||||
{% call(f) field.field(label=_("mas.recovery.finish.new"), name="new_password", form_state=form) %}
|
||||
<input {{ field.attributes(f) }} class="cpd-text-control" type="password" autofocus autocomplete="new-password" required />
|
||||
{% endcall %}
|
||||
|
||||
{% call(f) field.field(label=_("mas.recovery.finish.confirm"), name="new_password_confirm", form_state=form) %}
|
||||
<input {{ field.attributes(f) }} class="cpd-text-control" type="password" autocomplete="new-password" required />
|
||||
{% endcall %}
|
||||
|
||||
{{ button.button(text=_("mas.recovery.finish.save_and_continue"), type="submit") }}
|
||||
</form>
|
||||
{% endblock content %}
|
||||
37
mas/share/templates/pages/recovery/progress.html
Normal file
37
mas/share/templates/pages/recovery/progress.html
Normal file
@@ -0,0 +1,37 @@
|
||||
{#
|
||||
Copyright 2024, 2025 New Vector Ltd.
|
||||
Copyright 2024 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
-#}
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<header class="page-heading">
|
||||
<div class="icon">
|
||||
{{ icon.send_solid() }}
|
||||
</div>
|
||||
|
||||
<div class="header">
|
||||
<h1 class="title">{{ _("mas.recovery.progress.heading") }}</h1>
|
||||
<p class="text [&>span]:font-medium">{{ _("mas.recovery.progress.description", email=session.email) }}</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="flex flex-col gap-6">
|
||||
{% if resend_failed_due_to_rate_limit | default(false) %}
|
||||
<div class="text-critical font-medium">
|
||||
{{ _("mas.errors.rate_limit_exceeded") }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<form class="cpd-form-root" method="POST">
|
||||
<input type="hidden" name="csrf" value="{{ csrf_token }}" />
|
||||
|
||||
{{ button.button_outline(text=_("mas.recovery.progress.resend_email"), type="submit") }}
|
||||
</form>
|
||||
|
||||
{{ button.link_tertiary(text=_("mas.recovery.progress.change_email"), href="/recover") }}
|
||||
</div>
|
||||
{% endblock content %}
|
||||
40
mas/share/templates/pages/recovery/start.html
Normal file
40
mas/share/templates/pages/recovery/start.html
Normal file
@@ -0,0 +1,40 @@
|
||||
{#
|
||||
Copyright 2024, 2025 New Vector Ltd.
|
||||
Copyright 2024 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
-#}
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<header class="page-heading">
|
||||
<div class="icon">
|
||||
{{ icon.email_solid() }}
|
||||
</div>
|
||||
|
||||
<div class="header">
|
||||
<h1 class="title">{{ _("mas.recovery.start.heading") }}</h1>
|
||||
<p class="text">{{ _("mas.recovery.start.description") }}</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<form class="cpd-form-root" method="POST">
|
||||
{% if form.errors is not empty %}
|
||||
{% for error in form.errors %}
|
||||
<div class="text-critical font-medium">
|
||||
{{ errors.form_error_message(error=error) }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<input type="hidden" name="csrf" value="{{ csrf_token }}" />
|
||||
|
||||
{% call(f) field.field(label=_("common.email_address"), name="email", form_state=form) %}
|
||||
<input {{ field.attributes(f) }} class="cpd-text-control" type="email" autocomplete="email" required />
|
||||
{% endcall %}
|
||||
|
||||
{{ button.button(text=_("action.continue"), type="submit") }}
|
||||
</form>
|
||||
{% endblock content %}
|
||||
66
mas/share/templates/pages/register/index.html
Normal file
66
mas/share/templates/pages/register/index.html
Normal file
@@ -0,0 +1,66 @@
|
||||
{#
|
||||
Copyright 2024, 2025 New Vector Ltd.
|
||||
Copyright 2021-2024 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
-#}
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% from "components/idp_brand.html" import logo %}
|
||||
|
||||
{% block content %}
|
||||
<form method="GET" class="flex flex-col gap-10" action="{{ '/register/password' | prefix_url }}">
|
||||
<header class="page-heading">
|
||||
<div class="icon">
|
||||
{{ icon.user_profile_solid() }}
|
||||
</div>
|
||||
|
||||
<div class="header">
|
||||
<h1 class="title">{{ _("mas.register.create_account.heading") }}</h1>
|
||||
|
||||
{% if features.password_registration %}
|
||||
<p class="text">{{ _("mas.register.create_account.description") }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</header>
|
||||
|
||||
{% if features.password_registration %}
|
||||
{% call(f) field.field(label=_("common.username"), name="username", form_state=form) %}
|
||||
<input {{ field.attributes(f) }} class="cpd-text-control" type="text" autocomplete="username" autocorrect="off" autocapitalize="off" data-choose-username />
|
||||
<div class="cpd-form-message cpd-form-help-message" id="{{ f.id }}-help">
|
||||
@username:{{ branding.server_name }}
|
||||
</div>
|
||||
{% endcall %}
|
||||
{% endif %}
|
||||
|
||||
<div class="cpd-form-root">
|
||||
{% for key, value in next["params"] | default({}) | items %}
|
||||
<input type="hidden" name="{{ key }}" value="{{ value }}" />
|
||||
{% endfor %}
|
||||
|
||||
{% if features.password_registration %}
|
||||
{% if features.password_registration_email_required %}
|
||||
{{ button.button(text=_("mas.register.continue_with_email")) }}
|
||||
{% else %}
|
||||
{{ button.button(text=_("mas.register.continue_with_password")) }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if providers %}
|
||||
{% set params = next["params"] | default({}) | to_params(prefix="?") %}
|
||||
{% for provider in providers %}
|
||||
{% set name = provider.human_name or (provider.issuer | simplify_url(keep_path=True)) or provider.id %}
|
||||
<a class="cpd-button {%- if provider.brand_name %} has-icon {%- endif %}" data-kind="secondary" data-size="lg" href="{{ ('/upstream/authorize/' ~ provider.id ~ params) | prefix_url }}">
|
||||
{{ logo(provider.brand_name) }}
|
||||
{{ _("mas.login.continue_with_provider", provider=name) }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{% set params = next["params"] | default({}) | to_params(prefix="?") %}
|
||||
{{ button.link_tertiary(text=_("mas.register.call_to_login"), href="/login" ~ params) }}
|
||||
</div>
|
||||
</form>
|
||||
{% endblock content %}
|
||||
82
mas/share/templates/pages/register/password.html
Normal file
82
mas/share/templates/pages/register/password.html
Normal file
@@ -0,0 +1,82 @@
|
||||
{#
|
||||
Copyright 2024, 2025 New Vector Ltd.
|
||||
Copyright 2021-2024 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
-#}
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<header class="page-heading">
|
||||
<div class="icon">
|
||||
{{ icon.user_profile_solid() }}
|
||||
</div>
|
||||
|
||||
<div class="header">
|
||||
<h1 class="title">{{ _("mas.register.create_account.heading") }}</h1>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<form method="POST" class="cpd-form-root">
|
||||
{% for error in form.errors %}
|
||||
{# Special case for the captcha error, as we want to put it at the bottom #}
|
||||
{% if error.kind != "captcha" %}
|
||||
<div class="text-critical font-medium">
|
||||
{{ errors.form_error_message(error=error) }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
<input type="hidden" name="csrf" value="{{ csrf_token }}" />
|
||||
|
||||
{% call(f) field.field(label=_("common.username"), name="username", form_state=form) %}
|
||||
<input {{ field.attributes(f) }} class="cpd-text-control" type="text" autocomplete="username" autocorrect="off" autocapitalize="none" required data-choose-username />
|
||||
{{ field.error(error={"kind": "policy", "code": "username-invalid-chars"}, hidden=true) }}
|
||||
{% endcall %}
|
||||
|
||||
{% if features.password_registration_email_required %}
|
||||
{% call(f) field.field(label=_("common.email_address"), name="email", form_state=form) %}
|
||||
<input {{ field.attributes(f) }} class="cpd-text-control" type="email" autocomplete="email" required />
|
||||
{% endcall %}
|
||||
{% endif %}
|
||||
|
||||
{% call(f) field.field(label=_("common.password"), name="password", form_state=form) %}
|
||||
<input {{ field.attributes(f) }} class="cpd-text-control" type="password" autocomplete="new-password" required />
|
||||
{% endcall %}
|
||||
|
||||
{% call(f) field.field(label=_("common.password_confirm"), name="password_confirm", form_state=form) %}
|
||||
<input {{ field.attributes(f) }} class="cpd-text-control" type="password" autocomplete="new-password" required />
|
||||
{% endcall %}
|
||||
|
||||
{% if branding.tos_uri is not none %}
|
||||
{% call(f) field.field(label=_("mas.register.terms_of_service", tos_uri=branding.tos_uri), name="accept_terms", form_state=form, inline=true, class="my-4") %}
|
||||
<div class="cpd-form-inline-field-control">
|
||||
<div class="cpd-checkbox-container">
|
||||
<input {{ field.attributes(f) }} class="cpd-checkbox-input" type="checkbox" required />
|
||||
<div class="cpd-checkbox-ui">
|
||||
{{ icon.check() }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endcall %}
|
||||
{% endif %}
|
||||
|
||||
{{ captcha.form(class="mb-4 self-center") }}
|
||||
|
||||
{% for error in form.errors %}
|
||||
{# Special case for the captcha error #}
|
||||
{% if error.kind == "captcha" %}
|
||||
<div class="text-critical font-medium text-center -mt-4 mb-4">
|
||||
{{ errors.form_error_message(error=error) }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{{ button.button(text=_("action.continue")) }}
|
||||
|
||||
{% set params = next["params"] | default({}) | to_params(prefix="?") %}
|
||||
{{ button.link_tertiary(text=_("mas.register.call_to_login"), href="/login" ~ params) }}
|
||||
</form>
|
||||
{% endblock content %}
|
||||
52
mas/share/templates/pages/register/steps/display_name.html
Normal file
52
mas/share/templates/pages/register/steps/display_name.html
Normal file
@@ -0,0 +1,52 @@
|
||||
{#
|
||||
Copyright 2025 New Vector Ltd.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
-#}
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<header class="page-heading">
|
||||
<div class="icon">
|
||||
{{ icon.visibility_on() }}
|
||||
</div>
|
||||
<div class="header">
|
||||
<h1 class="title">{{ _("mas.choose_display_name.headline") }}</h1>
|
||||
<p class="text">{{ _("mas.choose_display_name.description") }}</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="cpd-form-root">
|
||||
<form method="POST" class="cpd-form-root">
|
||||
{% if form.errors is not empty %}
|
||||
{% for error in form.errors %}
|
||||
<div class="text-critical font-medium">
|
||||
{{ errors.form_error_message(error=error) }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<input type="hidden" name="csrf" value="{{ csrf_token }}" />
|
||||
<input type="hidden" name="action" value="set" />
|
||||
|
||||
{% call(f) field.field(label=_("common.display_name"), name="display_name", form_state=form, class="mb-4") %}
|
||||
<input {{ field.attributes(f) }}
|
||||
id="cpd-text-control"
|
||||
type="text"
|
||||
maxlength="256"
|
||||
class="cpd-text-control"
|
||||
required />
|
||||
{% endcall %}
|
||||
|
||||
{{ button.button(text=_("action.continue")) }}
|
||||
</form>
|
||||
|
||||
<form method="POST" class="cpd-form-root">
|
||||
<input type="hidden" name="csrf" value="{{ csrf_token }}" />
|
||||
<input type="hidden" name="action" value="skip" />
|
||||
{{ button.button(text=_("action.skip"), kind="tertiary") }}
|
||||
</form>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
30
mas/share/templates/pages/register/steps/email_in_use.html
Normal file
30
mas/share/templates/pages/register/steps/email_in_use.html
Normal file
@@ -0,0 +1,30 @@
|
||||
{#
|
||||
Copyright 2025 New Vector Ltd.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
-#}
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<main class="flex flex-col gap-6">
|
||||
<header class="page-heading">
|
||||
<div class="icon invalid">
|
||||
{{ icon.error_solid() }}
|
||||
</div>
|
||||
|
||||
<div class="header">
|
||||
<h1 class="title">
|
||||
{{ _("mas.email_in_use.title", email=email) }}
|
||||
</h1>
|
||||
<p class="text">
|
||||
{{ _("mas.email_in_use.description") }}
|
||||
</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
{% set params = action | default({}) | to_params(prefix="?") %}
|
||||
{{ button.link_outline(text=_("action.start_over"), href="/register" ~ params) }}
|
||||
</main>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,44 @@
|
||||
{#
|
||||
Copyright 2025 New Vector Ltd.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
-#}
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<header class="page-heading">
|
||||
<div class="icon">
|
||||
{{ icon.key_solid() }}
|
||||
</div>
|
||||
<div class="header">
|
||||
<h1 class="title">{{ _("mas.registration_token.headline") }}</h1>
|
||||
<p class="text">{{ _("mas.registration_token.description") }}</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="cpd-form-root">
|
||||
<form method="POST" class="cpd-form-root">
|
||||
{% if form.errors is not empty %}
|
||||
{% for error in form.errors %}
|
||||
<div class="text-critical font-medium">
|
||||
{{ errors.form_error_message(error=error) }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<input type="hidden" name="csrf" value="{{ csrf_token }}" />
|
||||
|
||||
{% call(f) field.field(label=_("mas.registration_token.field"), name="token", form_state=form, class="mb-4") %}
|
||||
<input {{ field.attributes(f) }}
|
||||
id="cpd-text-control"
|
||||
type="text"
|
||||
class="cpd-text-control"
|
||||
required />
|
||||
{% endcall %}
|
||||
|
||||
{{ button.button(text=_("action.continue")) }}
|
||||
</form>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
53
mas/share/templates/pages/register/steps/verify_email.html
Normal file
53
mas/share/templates/pages/register/steps/verify_email.html
Normal file
@@ -0,0 +1,53 @@
|
||||
{#
|
||||
Copyright 2024, 2025 New Vector Ltd.
|
||||
Copyright 2022-2024 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
-#}
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<header class="page-heading">
|
||||
<div class="icon">
|
||||
{{ icon.send_solid() }}
|
||||
</div>
|
||||
<div class="header">
|
||||
<h1 class="title">{{ _("mas.verify_email.headline") }}</h1>
|
||||
<p class="text">{{ _("mas.verify_email.description", email=authentication.email) }}</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<form method="POST" class="cpd-form-root">
|
||||
{% if form.errors is not empty %}
|
||||
{% for error in form.errors %}
|
||||
<div class="text-critical font-medium">
|
||||
{{ errors.form_error_message(error=error) }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<input type="hidden" name="csrf" value="{{ csrf_token }}" />
|
||||
|
||||
{% call(f) field.field(label=_("mas.verify_email.6_digit_code"), name="code", form_state=form, class="mb-4 self-center") %}
|
||||
<div class="cpd-mfa-container">
|
||||
<input {{ field.attributes(f) }}
|
||||
inputmode="numeric"
|
||||
type="text"
|
||||
minlength="0"
|
||||
maxlength="6"
|
||||
class="cpd-mfa-control"
|
||||
pattern="\d{6}"
|
||||
required
|
||||
autocomplete="one-time-code">
|
||||
|
||||
{% for _ in range(6) %}
|
||||
<div class="cpd-mfa-digit" aria-hidden="true"></div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endcall %}
|
||||
|
||||
{{ button.button(text=_("action.continue")) }}
|
||||
</form>
|
||||
{% endblock content %}
|
||||
48
mas/share/templates/pages/sso.html
Normal file
48
mas/share/templates/pages/sso.html
Normal file
@@ -0,0 +1,48 @@
|
||||
{#
|
||||
Copyright 2024, 2025 New Vector Ltd.
|
||||
Copyright 2022-2024 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
-#}
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
{% set client_name = login.redirect_uri | simplify_url %}
|
||||
|
||||
<header class="page-heading">
|
||||
<div class="consent-client-icon generic">
|
||||
{{ icon.web_browser() }}
|
||||
</div>
|
||||
|
||||
<div class="header">
|
||||
<h1 class="title">Allow access to your account?</h1>
|
||||
<p class="text"><span class="whitespace-nowrap">{{ client_name }}</span> wants to access your account. This will allow <span class="whitespace-nowrap">{{ client_name }}</span> to:</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section class="consent-scope-list">
|
||||
{{ scope.list(scopes="openid urn:matrix:client:api:*") }}
|
||||
</section>
|
||||
|
||||
<section class="text-center cpd-text-secondary cpd-text-body-md-regular">
|
||||
<span class="font-semibold cpd-text-primary">Make sure that you trust <span class="whitespace-nowrap">{{ client_name }}</span>.</span>
|
||||
You may be sharing sensitive information with this site or app.
|
||||
</section>
|
||||
|
||||
<section class="flex flex-col gap-6">
|
||||
<form method="POST" class="cpd-form-root">
|
||||
<input type="hidden" name="csrf" value="{{ csrf_token }}" />
|
||||
{{ button.button(text=_("action.continue")) }}
|
||||
</form>
|
||||
|
||||
<div class="flex gap-1 justify-center items-center">
|
||||
<p class="cpd-text-secondary cpd-text-body-md-regular">
|
||||
{{ _("mas.not_you", username=current_session.user.username) }}
|
||||
</p>
|
||||
|
||||
{{ logout.button(text=_("action.sign_out"), csrf_token=csrf_token, post_logout_action=action, as_link=true) }}
|
||||
</div>
|
||||
</section>
|
||||
{% endblock content %}
|
||||
194
mas/share/templates/pages/upstream_oauth2/do_register.html
Normal file
194
mas/share/templates/pages/upstream_oauth2/do_register.html
Normal file
@@ -0,0 +1,194 @@
|
||||
{#
|
||||
Copyright 2024, 2025 New Vector Ltd.
|
||||
Copyright 2022-2024 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
-#}
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% from "components/idp_brand.html" import logo %}
|
||||
|
||||
{% block content %}
|
||||
{% if force_localpart %}
|
||||
<header class="page-heading">
|
||||
<div class="icon">
|
||||
{{ icon.download() }}
|
||||
</div>
|
||||
|
||||
<div class="header">
|
||||
<h1 class="title">
|
||||
{{ _("mas.upstream_oauth2.register.import_data.heading") }}
|
||||
</h1>
|
||||
<p class="text">
|
||||
{{ _("mas.upstream_oauth2.register.import_data.description", server_name=branding.server_name) }}
|
||||
</p>
|
||||
</div>
|
||||
</header>
|
||||
{% elif upstream_oauth_provider.human_name is not none %}
|
||||
<header class="page-heading">
|
||||
<div class="icon">
|
||||
{{ icon.user_profile_solid() }}
|
||||
</div>
|
||||
|
||||
<div class="header">
|
||||
<h1 class="title">
|
||||
{{ _("mas.upstream_oauth2.register.signup_with_upstream.heading", human_name=upstream_oauth_provider.human_name) }}
|
||||
</h1>
|
||||
</div>
|
||||
</header>
|
||||
{% else %}
|
||||
<header class="page-heading">
|
||||
<div class="icon">
|
||||
{{ icon.mention() }}
|
||||
</div>
|
||||
|
||||
<div class="header">
|
||||
<h1 class="title">
|
||||
{{ _("mas.upstream_oauth2.register.choose_username.heading") }}
|
||||
</h1>
|
||||
<p class="text">
|
||||
{{ _("mas.upstream_oauth2.register.choose_username.description") }}
|
||||
</p>
|
||||
</div>
|
||||
</header>
|
||||
{% endif %}
|
||||
|
||||
{% if upstream_oauth_provider.human_name is not none %}
|
||||
<section class="upstream-oauth2-provider-account">
|
||||
{% if upstream_oauth_provider.brand_name is not none %}
|
||||
{{ logo(brand=upstream_oauth_provider.brand_name, class="brand") }}
|
||||
{% else %}
|
||||
{{ icon.user_profile() }}
|
||||
{% endif %}
|
||||
|
||||
<div class="infos">
|
||||
<h3 class="provider">
|
||||
{{- _("mas.upstream_oauth2.register.provider_name", human_name=upstream_oauth_provider.human_name) -}}
|
||||
</h3>
|
||||
{% if upstream_oauth_link.human_account_name is not none %}
|
||||
<p class="account">
|
||||
{{- upstream_oauth_link.human_account_name -}}
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</section>
|
||||
{% endif %}
|
||||
|
||||
<form method="POST" class="cpd-form-root">
|
||||
<input type="hidden" name="csrf" value="{{ csrf_token }}" />
|
||||
<input type="hidden" name="action" value="register" />
|
||||
|
||||
{% if form_state.errors is not empty %}
|
||||
{% for error in form_state.errors %}
|
||||
<div class="text-critical font-medium">
|
||||
{{- errors.form_error_message(error=error) -}}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if force_localpart %}
|
||||
{% call(f) field.field(label=_("common.mxid"), name="mxid") %}
|
||||
<input {{ field.attributes(f) }} class="cpd-text-control" type="text" value="@{{ imported_localpart }}:{{ branding.server_name }}" readonly aria-describedby="{{ f.id }}-help" />
|
||||
|
||||
<div class="cpd-form-message cpd-form-help-message" id="{{ f.id }}-help">
|
||||
{{- _("mas.upstream_oauth2.register.enforced_by_policy") -}}
|
||||
</div>
|
||||
{% endcall %}
|
||||
{% else %}
|
||||
{% call(f) field.field(label=_("common.username"), name="username", form_state=form_state) %}
|
||||
<input {{ field.attributes(f) }} class="cpd-text-control" type="text" autocomplete="username" autocorrect="off" autocapitalize="none" value="{{ imported_localpart or '' }}" aria-describedby="{{ f.id }}-help" data-choose-username />
|
||||
{{ field.error(error={"kind": "policy", "code": "username-invalid-chars"}, hidden=true) }}
|
||||
|
||||
{% if f.errors is empty %}
|
||||
<div class="cpd-form-message cpd-form-help-message" id="{{ f.id }}-help">
|
||||
@{{ imported_localpart or (_("common.username") | lower) }}:{{ branding.server_name }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endcall %}
|
||||
{% endif %}
|
||||
|
||||
{% if imported_email %}
|
||||
<div class="flex gap-6 items-center">
|
||||
{% call(f) field.field(label=_("common.email_address"), name="email", class="flex-1") %}
|
||||
<input {{ field.attributes(f) }} class="cpd-text-control" type="email" value="{{ imported_email }}" readonly aria-describedby="{{ f.id }}-help" />
|
||||
|
||||
<div class="cpd-form-message cpd-form-help-message" id="{{ f.id }}-help">
|
||||
{% if upstream_oauth_provider.human_name %}
|
||||
{{- _("mas.upstream_oauth2.register.imported_from_upstream_with_name", human_name=upstream_oauth_provider.human_name) -}}
|
||||
{% else %}
|
||||
{{- _("mas.upstream_oauth2.register.imported_from_upstream") -}}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endcall %}
|
||||
|
||||
{% if not force_email %}
|
||||
<div class="cpd-form-inline-field">
|
||||
<div class="cpd-form-inline-field-control">
|
||||
<div class="cpd-checkbox-container">
|
||||
<input class="cpd-checkbox-input" type="checkbox" name="import_email" id="import_email" checked="checked" />
|
||||
<div class="cpd-checkbox-ui">
|
||||
{{ icon.check() }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<label class="cpd-form-label" for="import_email">
|
||||
{{- _("mas.upstream_oauth2.register.use") -}}
|
||||
</label>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if imported_display_name %}
|
||||
<div class="flex gap-6 items-center">
|
||||
{% call(f) field.field(label=_("common.display_name"), name="display_name", class="flex-1") %}
|
||||
<input {{ field.attributes(f) }} class="cpd-text-control" type="text" value="{{ imported_display_name }}" readonly />
|
||||
|
||||
<div class="cpd-form-message cpd-form-help-message">
|
||||
{% if upstream_oauth_provider.human_name is not none %}
|
||||
{{- _("mas.upstream_oauth2.register.imported_from_upstream_with_name", human_name=upstream_oauth_provider.human_name) -}}
|
||||
{% else %}
|
||||
{{- _("mas.upstream_oauth2.register.imported_from_upstream") -}}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endcall %}
|
||||
|
||||
{% if not force_display_name %}
|
||||
<div class="cpd-form-inline-field">
|
||||
<div class="cpd-form-inline-field-control">
|
||||
<div class="cpd-checkbox-container">
|
||||
<input class="cpd-checkbox-input" type="checkbox" name="import_display_name" id="import_display_name" checked="checked" />
|
||||
<div class="cpd-checkbox-ui">
|
||||
{{ icon.check() }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cpd-form-inline-field-body">
|
||||
<label class="cpd-form-label" for="import_display_name">
|
||||
{{- _("mas.upstream_oauth2.register.use") -}}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if branding.tos_uri is not none %}
|
||||
{% call(f) field.field(label=_("mas.register.terms_of_service", tos_uri=branding.tos_uri), name="accept_terms", form_state=form_state, inline=true, class="my-4") %}
|
||||
<div class="cpd-form-inline-field-control">
|
||||
<div class="cpd-checkbox-container">
|
||||
<input {{ field.attributes(f) }} class="cpd-checkbox-input" type="checkbox" required />
|
||||
<div class="cpd-checkbox-ui">
|
||||
{{ icon.check() }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endcall %}
|
||||
{% endif %}
|
||||
|
||||
{{ button.button(text=_("action.create_account")) }}
|
||||
</form>
|
||||
{% endblock content %}
|
||||
25
mas/share/templates/pages/upstream_oauth2/link_mismatch.html
Normal file
25
mas/share/templates/pages/upstream_oauth2/link_mismatch.html
Normal file
@@ -0,0 +1,25 @@
|
||||
{#
|
||||
Copyright 2024, 2025 New Vector Ltd.
|
||||
Copyright 2022-2024 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
-#}
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<header class="page-heading">
|
||||
<div class="icon invalid">
|
||||
{{ icon.warning() }}
|
||||
</div>
|
||||
|
||||
<div class="header">
|
||||
<h1 class="title">
|
||||
{{ _("mas.upstream_oauth2.link_mismatch.heading") }}
|
||||
</h1>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
{{ logout.button(text=_("action.sign_out"), csrf_token=csrf_token) }}
|
||||
{% endblock content %}
|
||||
31
mas/share/templates/pages/upstream_oauth2/login_link.html
Normal file
31
mas/share/templates/pages/upstream_oauth2/login_link.html
Normal file
@@ -0,0 +1,31 @@
|
||||
{#
|
||||
Copyright 2025 New Vector Ltd.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE in the repository root for full details.
|
||||
-#}
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<header class="page-heading">
|
||||
<div class="icon">
|
||||
{{ icon.link() }}
|
||||
</div>
|
||||
|
||||
<div class="header">
|
||||
<h1 class="title">{{ _("mas.upstream_oauth2.login_link.heading") }}</h1>
|
||||
</div>
|
||||
</header>
|
||||
<section class="flex flex-col gap-6 justify-center">
|
||||
{{ _("mas.upstream_oauth2.login_link.description", username=linked_user.username) }}
|
||||
|
||||
<form method="POST" class="cpd-form-root">
|
||||
<input type="hidden" name="csrf" value="{{ csrf_token }}" />
|
||||
<input type="hidden" name="action" value="link" />
|
||||
|
||||
{{ button.button(text=_("mas.upstream_oauth2.login_link.action")) }}
|
||||
</form>
|
||||
|
||||
</section>
|
||||
{% endblock content %}
|
||||
34
mas/share/templates/pages/upstream_oauth2/suggest_link.html
Normal file
34
mas/share/templates/pages/upstream_oauth2/suggest_link.html
Normal file
@@ -0,0 +1,34 @@
|
||||
{#
|
||||
Copyright 2024, 2025 New Vector Ltd.
|
||||
Copyright 2022-2024 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
-#}
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<header class="page-heading">
|
||||
<div class="icon">
|
||||
{{ icon.link() }}
|
||||
</div>
|
||||
|
||||
<div class="header">
|
||||
<h1 class="title">{{ _("mas.upstream_oauth2.suggest_link.heading") }}</h1>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section class="flex flex-col gap-6 justify-center">
|
||||
<form method="POST" class="cpd-form-root">
|
||||
<input type="hidden" name="csrf" value="{{ csrf_token }}" />
|
||||
<input type="hidden" name="action" value="link" />
|
||||
|
||||
{{ button.button(text=_("mas.upstream_oauth2.suggest_link.action")) }}
|
||||
</form>
|
||||
|
||||
{{ field.separator() }}
|
||||
|
||||
{{ logout.button(text=_("action.sign_out"), csrf_token=csrf_token, post_logout_action=post_logout_action) }}
|
||||
</section>
|
||||
{% endblock content %}
|
||||
Reference in New Issue
Block a user