From f3f98e4a7534de9ec53ce5f9048c3d96123a6256 Mon Sep 17 00:00:00 2001 From: Son NK Date: Wed, 29 Jan 2020 23:50:50 +0700 Subject: [PATCH 1/3] Improve authorize page UI for non-authenticated user --- .../oauth/authorize_nonlogin_user.html | 93 +++++++++++-------- 1 file changed, 55 insertions(+), 38 deletions(-) diff --git a/app/oauth/templates/oauth/authorize_nonlogin_user.html b/app/oauth/templates/oauth/authorize_nonlogin_user.html index 9a1d8426..07a36601 100644 --- a/app/oauth/templates/oauth/authorize_nonlogin_user.html +++ b/app/oauth/templates/oauth/authorize_nonlogin_user.html @@ -1,47 +1,64 @@ -{% extends "single.html" %} +{% extends "base.html" %} -{% block single_content %} -
- {{ client.name }}   would like to have access to your following data: - - - - -
- -
-
- - - Login - - - - Sign Up +{% block content %} + -
+
+ {{ client.name }} would like to have access to your following data: +
+ +
+
    + {% for scope in client.get_scopes() %} +
  • + {% if scope == Scope.AVATAR_URL %} + avatar + {% else %} + {{ scope.value }} + {% endif %} +
  • + {% endfor %} +
+
+ +
+ In order to accept the request, you need to sign in. +
+ + + +
+ +
+

Cancel and go back to {{ client.name }}

+ + Cancel + +
+ +
+ SimpleLogin is an open source social login provider that protects your privacy. +
-
-

Cancel and go back to {{ client.name }}

- - Cancel -
{% endblock %} + + From 6cad537931a44247e54c07f8acd02b360b4c88ab Mon Sep 17 00:00:00 2001 From: Son NK Date: Wed, 29 Jan 2020 23:56:44 +0700 Subject: [PATCH 2/3] user can choose to create alias with custom domain on the authorize page --- app/oauth/templates/oauth/authorize.html | 38 ++++++-- app/oauth/views/authorize.py | 116 ++++++++++++++--------- 2 files changed, 101 insertions(+), 53 deletions(-) diff --git a/app/oauth/templates/oauth/authorize.html b/app/oauth/templates/oauth/authorize.html index a9977c7a..b2080423 100644 --- a/app/oauth/templates/oauth/authorize.html +++ b/app/oauth/templates/oauth/authorize.html @@ -84,24 +84,42 @@
{% if current_user.can_create_new_alias() %} -
OR
-
- - -
- .{{ email_suffix }}@{{ EMAIL_DOMAIN }} +
OR
+ +
+
+ +
+ + +
+
+ Alias can use letter, number, dash and cannot be empty diff --git a/app/oauth/views/authorize.py b/app/oauth/views/authorize.py index 7ba3a49a..734e50d5 100644 --- a/app/oauth/views/authorize.py +++ b/app/oauth/views/authorize.py @@ -4,7 +4,8 @@ from urllib.parse import urlparse from flask import request, render_template, redirect, flash from flask_login import current_user -from app.config import EMAIL_DOMAIN +from app.config import EMAIL_DOMAIN, ALIAS_DOMAINS, DISABLE_ALIAS_SUFFIX +from app.email_utils import get_email_domain_part from app.extensions import db from app.jose_utils import make_id_token from app.log import LOG @@ -16,6 +17,7 @@ from app.models import ( RedirectUri, OauthToken, DeletedAlias, + CustomDomain, ) from app.oauth.base import oauth_bp from app.oauth_models import ( @@ -103,21 +105,33 @@ def authorize(): client.name ) suggested_name, other_names = current_user.suggested_names() - email_suffix = random_word() + + user_custom_domains = [ + cd.domain for cd in current_user.verified_custom_domains() + ] + # List of (is_custom_domain, alias-suffix) + suffixes = [] + + # put custom domain first + for alias_domain in user_custom_domains: + suffixes.append((True, "@" + alias_domain)) + + # then default domain + for domain in ALIAS_DOMAINS: + suffixes.append( + ( + False, + ("" if DISABLE_ALIAS_SUFFIX else "." + random_word()) + + "@" + + domain, + ) + ) return render_template( "oauth/authorize.html", - client=client, - user_info=user_info, - client_user=client_user, Scope=Scope, - suggested_email=suggested_email, - personal_email=current_user.email, - suggested_name=suggested_name, - other_names=other_names, - other_emails=other_emails, - email_suffix=email_suffix, EMAIL_DOMAIN=EMAIL_DOMAIN, + **locals(), ) else: # after user logs in, redirect user back to this page @@ -127,7 +141,7 @@ def authorize(): next=request.url, Scope=Scope, ) - else: # user allows or denies + else: # POST - user allows or denies if request.form.get("button") == "deny": LOG.debug("User %s denies Client %s", current_user, client) final_redirect_uri = f"{redirect_uri}?error=deny&state={state}" @@ -140,32 +154,55 @@ def authorize(): if client_user: LOG.d("user %s has already allowed client %s", current_user, client) else: - email_suffix = request.form.get("email-suffix") - custom_email_prefix = request.form.get("custom-email-prefix") - chosen_email = request.form.get("suggested-email") - - suggested_name = request.form.get("suggested-name") - custom_name = request.form.get("custom-name") - - use_default_avatar = request.form.get("avatar-choice") == "default" + alias_prefix = request.form.get("prefix") + alias_suffix = request.form.get("suffix") gen_email = None - if custom_email_prefix: - # check if user can generate custom email + + # user creates a new alias, not using suggested alias + if alias_prefix: + # should never happen as this is checked on the front-end if not current_user.can_create_new_alias(): raise Exception(f"User {current_user} cannot create custom email") - email = f"{convert_to_id(custom_email_prefix)}.{email_suffix}@{EMAIL_DOMAIN}" - LOG.d("create custom email alias %s for user %s", email, current_user) + user_custom_domains = [ + cd.domain for cd in current_user.verified_custom_domains() + ] - if GenEmail.get_by(email=email) or DeletedAlias.get_by(email=email): - LOG.error("email %s already used, very rare!", email) - flash(f"alias {email} already used", "error") + from app.dashboard.views.custom_alias import verify_prefix_suffix + + if verify_prefix_suffix( + current_user, alias_prefix, alias_suffix, user_custom_domains + ): + full_alias = alias_prefix + alias_suffix + + if GenEmail.get_by(email=full_alias) or DeletedAlias.get_by( + email=full_alias + ): + LOG.error("alias %s already used, very rare!", full_alias) + flash(f"Alias {full_alias} already used", "error") + return redirect(request.url) + else: + gen_email = GenEmail.create( + user_id=current_user.id, email=full_alias + ) + + # get the custom_domain_id if alias is created with a custom domain + alias_domain = get_email_domain_part(full_alias) + custom_domain = CustomDomain.get_by(domain=alias_domain) + if custom_domain: + gen_email.custom_domain_id = custom_domain.id + + db.session.flush() + flash(f"Alias {full_alias} has been created", "success") + # only happen if the request has been "hacked" + else: + flash("something went wrong", "warning") return redirect(request.url) - - gen_email = GenEmail.create(email=email, user_id=current_user.id) - db.session.flush() - else: # user picks an email from suggestion + # User chooses one of the suggestions + else: + chosen_email = request.form.get("suggested-email") + # todo: add some checks on chosen_email if chosen_email != current_user.email: gen_email = GenEmail.get_by(email=chosen_email) if not gen_email: @@ -174,6 +211,11 @@ def authorize(): ) db.session.flush() + suggested_name = request.form.get("suggested-name") + custom_name = request.form.get("custom-name") + + use_default_avatar = request.form.get("avatar-choice") == "default" + client_user = ClientUser.create( client_id=client.id, user_id=current_user.id ) @@ -181,20 +223,8 @@ def authorize(): client_user.gen_email_id = gen_email.id if custom_name: - LOG.d( - "use custom name %s for user %s client %s", - custom_name, - current_user, - client, - ) client_user.name = custom_name elif suggested_name != current_user.name: - LOG.d( - "use another name %s for user %s client %s", - custom_name, - current_user, - client, - ) client_user.name = suggested_name if use_default_avatar: From cce330a44214148d3ce14adbf5f98079e376de6d Mon Sep 17 00:00:00 2001 From: Son NK Date: Wed, 29 Jan 2020 23:57:11 +0700 Subject: [PATCH 3/3] check if alias is not deleted before in custom-alias page --- app/dashboard/views/custom_alias.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/dashboard/views/custom_alias.py b/app/dashboard/views/custom_alias.py index bf4d56f4..250cae09 100644 --- a/app/dashboard/views/custom_alias.py +++ b/app/dashboard/views/custom_alias.py @@ -1,4 +1,4 @@ -from flask import render_template, redirect, url_for, flash, request, session +from flask import render_template, redirect, url_for, flash, request from flask_login import login_required, current_user from app.config import ( @@ -9,7 +9,7 @@ from app.dashboard.base import dashboard_bp from app.email_utils import email_belongs_to_alias_domains, get_email_domain_part from app.extensions import db from app.log import LOG -from app.models import GenEmail, CustomDomain +from app.models import GenEmail, CustomDomain, DeletedAlias from app.utils import convert_to_id, random_word, word_exist @@ -49,7 +49,9 @@ def custom_alias(): ): full_alias = alias_prefix + alias_suffix - if GenEmail.get_by(email=full_alias): + if GenEmail.get_by(email=full_alias) or DeletedAlias.get_by( + email=full_alias + ): LOG.d("full alias already used %s", full_alias) flash( f"Alias {full_alias} already exists, please choose another one",