From cb6d89e308a020386eb748aa9c75e7a2e9d3d75a Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Wed, 6 Sep 2023 13:58:00 +0200 Subject: [PATCH] Compoundify the consent screens --- crates/templates/src/functions.rs | 27 +++-- frontend/src/templates.css | 91 +++++++++++++++++ templates/app.html | 2 +- templates/base.html | 3 +- templates/components/back_to_client.html | 14 ++- templates/components/icon.html | 124 +++++++++++++++++++++++ templates/components/scope.html | 20 ++-- templates/pages/consent.html | 96 +++++++++--------- templates/pages/sso.html | 46 +++++---- 9 files changed, 332 insertions(+), 91 deletions(-) create mode 100644 templates/components/icon.html diff --git a/crates/templates/src/functions.rs b/crates/templates/src/functions.rs index e4a3c4870..dcecca482 100644 --- a/crates/templates/src/functions.rs +++ b/crates/templates/src/functions.rs @@ -14,7 +14,10 @@ //! Additional functions, tests and filters used in templates -use std::{collections::HashMap, str::FromStr}; +use std::{ + collections::{BTreeSet, HashMap}, + str::FromStr, +}; use camino::Utf8Path; use mas_router::UrlBuilder; @@ -196,6 +199,12 @@ impl tera::Function for IncludeAsset { let path = args.get("path").ok_or(tera::Error::msg( "Function `include_asset` was missing parameter `path`", ))?; + + let preload = args + .get("preload") + .and_then(Value::as_bool) + .unwrap_or(false); + let path: &Utf8Path = path .as_str() .ok_or_else(|| { @@ -212,12 +221,16 @@ impl tera::Function for IncludeAsset { ) })?; - let preloads = self.vite_manifest.preload_for(path).map_err(|e| { - tera::Error::chain( - "Invalid assets manifest while calling function `include_asset`", - e.to_string(), - ) - })?; + let preloads = if preload { + self.vite_manifest.preload_for(path).map_err(|e| { + tera::Error::chain( + "Invalid assets manifest while calling function `include_asset`", + e.to_string(), + ) + })? + } else { + BTreeSet::new() + }; let tags: Vec = preloads .iter() diff --git a/frontend/src/templates.css b/frontend/src/templates.css index fc4571ce2..7205a4c8b 100644 --- a/frontend/src/templates.css +++ b/frontend/src/templates.css @@ -38,3 +38,94 @@ body { color: var(--cpd-color-text-primary); letter-spacing: var(--cpd-font-letter-spacing-body-md); } + +.cpd-text-body-lg-regular { + font: var(--cpd-font-body-lg-regular); + letter-spacing: var(--cpd-font-letter-spacing-body-lg); +} + +.cpd-text-heading-xl-semibold { + font: var(--cpd-font-heading-xl-semibold); + letter-spacing: var(--cpd-font-letter-spacing-heading-xl); +} + +.cpd-text-body-md-regular { + font: var(--cpd-font-body-md-regular); + letter-spacing: var(--cpd-font-letter-spacing-body-md); +} + +.cpd-text-primary { + color: var(--cpd-color-text-primary); +} + +.cpd-text-secondary { + color: var(--cpd-color-text-secondary); +} + +.consent-client-icon { + display: block; + height: var(--cpd-space-16x); + width: var(--cpd-space-16x); + margin: 0 auto; + + &.generic { + background-color: var(--cpd-color-bg-subtle-secondary); + border-radius: var(--cpd-radius-pill-effect); + color: var(--cpd-color-icon-primary); + + & svg { + margin: var(--cpd-space-4x); + height: var(--cpd-space-8x); + width: var(--cpd-space-8x); + } + } + + &.image { + height: var(--cpd-space-16x); + width: var(--cpd-space-16x); + border-radius: var(--cpd-space-2x); + overflow: hidden; + } +} + +.consent-scope-list { + --border-radius: var(--cpd-space-4x); + & ul { + display: flex; + flex-direction: column; + gap: var(--cpd-space-1x); + + & > li { + font: var(--cpd-font-body-md-regular); + letter-spacing: var(--cpd-font-letter-spacing-body-md); + color: var(--cpd-color-text-primary); + + background-color: var(--cpd-color-bg-subtle-secondary); + padding: var(--cpd-space-3x) var(--cpd-space-5x); + display: flex; + gap: var(--cpd-space-4x); + line-height: var(--cpd-space-6x); + + &:first-of-type { + border-top-left-radius: var(--border-radius); + border-top-right-radius: var(--border-radius); + } + + &:last-of-type { + border-bottom-left-radius: var(--border-radius); + border-bottom-right-radius: var(--border-radius); + } + + & > p { + flex: 1; + } + + & > svg { + display: block; + height: var(--cpd-space-6x); + width: var(--cpd-space-6x); + color: var(--cpd-color-icon-quaternary); + } + } + } +} \ No newline at end of file diff --git a/templates/app.html b/templates/app.html index cf40187f0..7a7c9ba8a 100644 --- a/templates/app.html +++ b/templates/app.html @@ -38,7 +38,7 @@ limitations under the License. handleChange(query); })(); - {{ include_asset(path='src/main.tsx') | indent(prefix=" ") | safe }} + {{ include_asset(path='src/main.tsx', preload=true) | indent(prefix=" ") | safe }} diff --git a/templates/base.html b/templates/base.html index a8716e638..95cf6b6c6 100644 --- a/templates/base.html +++ b/templates/base.html @@ -20,6 +20,7 @@ limitations under the License. {% import "components/logout.html" as logout %} {% import "components/navbar.html" as navbar %} {% import "components/errors.html" as errors %} +{% import "components/icon.html" as icon %} {% import "components/scope.html" as scope %} @@ -28,7 +29,7 @@ limitations under the License. {% block title %}matrix-authentication-service{% endblock title %} - {{ include_asset(path='src/templates.css') | indent(prefix=" ") | safe }} + {{ include_asset(path='src/templates.css', preload=true) | indent(prefix=" ") | safe }} {% block content %}{% endblock content %} diff --git a/templates/components/back_to_client.html b/templates/components/back_to_client.html index 4c8077351..c273e743e 100644 --- a/templates/components/back_to_client.html +++ b/templates/components/back_to_client.html @@ -14,16 +14,24 @@ See the License for the specific language governing permissions and limitations under the License. #} -{% macro link(text, uri, mode, params, kind="primary") %} +{% macro link(text, uri, mode, params, type="button", kind="primary") %} + {% if type == "button" %} + {% set class = "cpd-button" %} + {% elif type == "link" %} + {% set class = "cpd-link" %} + {% else %} + {{ throw(message="Invalid type") }} + {% endif %} + {% if mode == "form_post" %}
{% for key, value in params %} {% endfor %} - +
{% elif mode == "fragment" or mode == "query" %} - {{ text }} + {{ text }} {% else %} {{ throw(message="Invalid mode") }} {% endif %} diff --git a/templates/components/icon.html b/templates/components/icon.html new file mode 100644 index 000000000..cac02dc27 --- /dev/null +++ b/templates/components/icon.html @@ -0,0 +1,124 @@ +{# +Copyright 2023 The Matrix.org Foundation C.I.C. + +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. +#} + +{# Regenrate with the following shell script: + +for i in frontend/node_modules/@vector-im/compound-design-tokens/assets/web/icons/*.svg; do + NAME=$(basename "$i" | sed 's/\.svg//' | tr '-' '_') + CONTENT=$(cat "$i") + cat < + + +{% endmacro %} + +{% macro check_circle() %} + + + +{% endmacro %} + +{% macro check() %} + + + +{% endmacro %} + +{% macro chevron() %} + + + +{% endmacro %} + +{% macro close() %} + + + +{% endmacro %} + +{% macro computer() %} + + + +{% endmacro %} + +{% macro delete() %} + + + +{% endmacro %} + +{% macro error() %} + + + +{% endmacro %} + +{% macro info() %} + + + +{% endmacro %} + +{% macro lock() %} + + + +{% endmacro %} + +{% macro mobile() %} + + + +{% endmacro %} + +{% macro thread() %} + +{% endmacro %} + +{% macro user() %} + + + +{% endmacro %} + +{% macro visibility_invisible() %} + + + +{% endmacro %} + +{% macro visibility_visible() %} + + + +{% endmacro %} + +{% macro web_browser() %} + + + +{% endmacro %} \ No newline at end of file diff --git a/templates/components/scope.html b/templates/components/scope.html index bc7a36ee9..72d5c2129 100644 --- a/templates/components/scope.html +++ b/templates/components/scope.html @@ -15,24 +15,24 @@ limitations under the License. #} {% macro list(scopes) %} -
    +
      {% for scope in scopes | split(pat=" ") %} {% if scope == "openid" %} -
    • See your profile info and contact details
    • +
    • {{ icon::user() }}

      See your profile info and contact details

    • {% elif scope == "urn:mas:graphql:*" %} -
    • Edit your profile and contact details
    • -
    • Manage your devices and sessions
    • +
    • {{ icon::info() }}

      Edit your profile and contact details

    • +
    • {{ icon::computer() }}

      Manage your devices and sessions

    • {% elif scope == "urn:matrix:org.matrix.msc2967.client:api:*" %} -
    • View your existing messages and data
    • -
    • Send new messages on your behalf
    • +
    • {{ icon::chat() }}

      View your existing messages and data

    • +
    • {{ icon::check_circle() }}

      Send new messages on your behalf

    • {% elif scope == "urn:synapse:admin:*" %} -
    • Administer the Synapse homeserver
    • +
    • {{ icon::error() }}

      Administer the Synapse homeserver

    • {% elif scope == "urn:mas:graphql:admin" %} -
    • Administer any user on the MAS authentication server
    • +
    • {{ icon::error() }}

      Administer any user on the MAS authentication server

    • {% elif scope is matching("^urn:matrix:org.matrix.msc2967.client:device:") %} - {#
    • {{ scope }}
    • #} + {# We hide this scope #} {% else %} -
    • {{ scope }}
    • +
    • {{ icon::info() }}

      {{ scope }}

    • {% endif %} {% endfor %}
    diff --git a/templates/pages/consent.html b/templates/pages/consent.html index 965854721..461722f29 100644 --- a/templates/pages/consent.html +++ b/templates/pages/consent.html @@ -17,61 +17,59 @@ limitations under the License. {% extends "base.html" %} {% block content %} + {% set client_name = client.client_name | default(value=client.client_id) %}
    -
    -
    -
    -
    -
    - {% if client.logo_uri %} - - {% endif %} -
    -

    {{ client.client_name | default(value=client.client_id) }}

    -

    at {{ grant.redirect_uri | simplify_url }}

    -

    wants to access your account

    +
    +
    + {% if client.logo_uri %} + -
    -
    -

    This will allow {{ client.client_name | default(value=client.client_id) }} to:

    - -

    - {{ scope::list(scopes=grant.scope) }} -

    -

    Make sure that you trust {{ client.client_name | default(value=client.client_id) }}.

    -

    - You may be sharing sensitive information with this site or app. - {% if client.policy_uri or client.tos_uri %} - Find out how {{ client.client_name }} will handle your data by reviewing its - {% if client.policy_uri %} - privacy policy{% if not client.tos_uri %}.{% endif %} - {% endif %} - {% if client.policy_uri and client.tos_uri%} - and - {% endif %} - {% if client.tos_uri %} - terms of service. - {% endif %} - {% endif %} -

    -
    + {% else %} + -
    + {% endif %} +

    {{ client_name }}

    +

    at {{ grant.redirect_uri | simplify_url }} wants to access your account. This will allow {{ client_name }} to:

    +
    + + + +
    + Make sure that you trust {{ client_name }}. + You may be sharing sensitive information with this site or app. + {% if client.policy_uri or client.tos_uri %} + Find out how {{ client_name }} will handle your data by reviewing its + {% if client.policy_uri %} + privacy policy{% if not client.tos_uri %}.{% endif %} + {% endif %} + {% if client.policy_uri and client.tos_uri%} + and + {% endif %} + {% if client.tos_uri %} + terms of service. + {% endif %} + {% endif %} +
    + + - -
    - {{ back_to_client::link( - text="Cancel", - kind="destructive", - uri=grant.redirect_uri, - mode=grant.response_mode, - params=dict(error="access_denied", state=grant.state) - ) }} - {{ button::button(text="Allow") }} -
    + {{ button::button(text="Continue") }} -
    + + {{ back_to_client::link( + text="Cancel", + kind="tertiary", + uri=grant.redirect_uri, + mode=grant.response_mode, + params=dict(error="access_denied", state=grant.state) + ) }} + +
    Not {{ current_session.user.username }}? {{ logout::button(text="Sign out", csrf_token=csrf_token, post_logout_action=action, as_link=true) }}
    diff --git a/templates/pages/sso.html b/templates/pages/sso.html index 73f1fd1ea..48079ceca 100644 --- a/templates/pages/sso.html +++ b/templates/pages/sso.html @@ -17,32 +17,38 @@ limitations under the License. {% extends "base.html" %} {% block content %} + {% set client_name = login.redirect_uri | simplify_url %}
    -
    -
    -
    -
    -

    {{ login.redirect_uri | simplify_url }}

    -

    wants to access your account

    +
    +
    + {% if client.logo_uri %} + -
    -
    -

    This will allow it to:

    - -

    - {{ scope::list(scopes="openid urn:matrix:org.matrix.msc2967.client:api:*") }} -

    - -

    Make sure that you trust it.

    -
    + {% else %} + -
    + {% endif %} +

    {{ client_name }} wants to access your account. This will allow {{ client_name }} to:

    +
    + + + +
    + Make sure that you trust {{ client_name }}. + You may be sharing sensitive information with this site or app. +
    + + - - {{ button::button(text="Allow") }} + {{ button::button(text="Continue") }} -
    + +
    Not {{ current_session.user.username }}? {{ logout::button(text="Sign out", csrf_token=csrf_token, post_logout_action=action, as_link=true) }}