From 6f653db5fe5ce3002d59755ff482e801f9e491d3 Mon Sep 17 00:00:00 2001
From: kaiyou <pierre@jaury.eu>
Date: Sat, 14 Sep 2019 21:20:43 +0200
Subject: [PATCH] Allow users to create profiles

---
 trurt/account/forms.py                      |  6 +++
 trurt/account/login.py                      |  2 +-
 trurt/account/profiles.py                   | 44 +++++++++++++++++++--
 trurt/account/templates/account_pick.html   | 18 ++++++++-
 trurt/account/templates/account_signup.html | 11 ++++++
 trurt/account/templates/profile_create.html | 11 ++++++
 trurt/models.py                             |  2 +-
 7 files changed, 87 insertions(+), 7 deletions(-)
 create mode 100644 trurt/account/templates/account_signup.html
 create mode 100644 trurt/account/templates/profile_create.html

diff --git a/trurt/account/forms.py b/trurt/account/forms.py
index b6e560af..998e8977 100644
--- a/trurt/account/forms.py
+++ b/trurt/account/forms.py
@@ -28,3 +28,9 @@ class PasswordForm(flask_wtf.FlaskForm):
     password2 = fields.PasswordField(_('Confirm new password'),
         [validators.DataRequired(), validators.EqualTo('password')])
     submit = fields.SubmitField(_('Change password'))
+
+
+class ProfileForm(flask_wtf.FlaskForm):
+    username = fields.StringField(_('Username'), [validators.DataRequired()])
+    comment = fields.StringField(_('Comment'))
+    submit = fields.SubmitField(_('Create profile'))
diff --git a/trurt/account/login.py b/trurt/account/login.py
index 29254a8b..fc9e8406 100644
--- a/trurt/account/login.py
+++ b/trurt/account/login.py
@@ -46,5 +46,5 @@ def signup():
             models.db.session.commit()
             flask.flash("User created successfully", "success")
             return flask.redirect(utils.url_or_intent("account.home"))
-    return flask.render_template("form.html", form=form,
+    return flask.render_template("account_signup.html", form=form,
         title="Signup up", subtitle="for a new account")
diff --git a/trurt/account/profiles.py b/trurt/account/profiles.py
index 2bfbbe34..6ac27d8b 100644
--- a/trurt/account/profiles.py
+++ b/trurt/account/profiles.py
@@ -1,4 +1,4 @@
-from trurt.account import blueprint
+from trurt.account import blueprint, forms
 from trurt.sso import forms as sso_forms
 from trurt import models, utils
 
@@ -15,12 +15,48 @@ def profiles():
 @flask_login.login_required
 def pick():
     service_uuid = flask.request.args.get("service_uuid") or flask.abort(404)
-    service = models.Service.query.get(service_uuid) or flask.arort(404)
+    service = models.Service.query.get(service_uuid) or flask.abort(404)
     profiles = models.Profile.query.filter_by(
         service_uuid=service.uuid,
         user_uuid=flask_login.current_user.uuid
-    )
+    ).all()
     form = sso_forms.SSOValidateForm()
     return flask.render_template("account_pick.html",
         service=service, profiles=profiles, form=form,
-        action=utils.url_or_intent("account.status"))
+        action_create=utils.url_for("account.create_profile", intent="account.pick"),
+        action_pick=utils.url_or_intent("account.status"))
+
+
+@blueprint.route("/profile/create", methods=["GET", "POST"])
+@flask_login.login_required
+def create_profile():
+    service_uuid = flask.request.args.get("service_uuid") or flask.abort(404)
+    service = models.Service.query.get(service_uuid) or flask.abort(404)
+    profiles = models.Profile.query.filter_by(
+        service_uuid=service.uuid,
+        user_uuid=flask_login.current_user.uuid
+    ).all()
+    if len(profiles) >= service.max_profiles:
+        flask.flash("You have reached the maximum number of profiles for that\
+            account", "error")
+        return flask.redirect(utils.url_or_intent("account.home"))
+    form = forms.ProfileForm()
+    if form.validate_on_submit():
+        conflict = models.Profile.query.filter_by(
+            service_uuid=service_uuid, username=form.username.data
+        ).first()
+        print(conflict)
+        if conflict:
+            flask.flash("A profile with that username exists already", "danger")
+        else:
+            profile = models.Profile()
+            profile.username = form.username.data
+            profile.user = flask_login.current_user
+            profile.service = service
+            profile.comment = form.comment.data
+            models.db.session.add(profile)
+            models.db.session.commit()
+            return flask.redirect(utils.url_or_intent("account.home"))
+    return flask.render_template("profile_create.html",
+        title="Create a profile", subtitle="for {}".format(service.name),
+        form=form, service=service)
diff --git a/trurt/account/templates/account_pick.html b/trurt/account/templates/account_pick.html
index 1af8a1da..5acfaa66 100644
--- a/trurt/account/templates/account_pick.html
+++ b/trurt/account/templates/account_pick.html
@@ -6,12 +6,28 @@
 {% block subtitle %}for the service {{ service.name }}{% endblock %}
 
 {% block content %}
+{% if not profiles %}
+<div class="box">
+  <div class="box-body">
+  You currently have no profile for this service. You can create a new profile by clicking the follwing button.
+  <a href="{{ action_create }}" class="btn btn-flat">New profile</a>
+  </div>
+</div>
+{% elif profiles.__len__() < service.max_profiles %}
+<div class="box">
+  <div class="box-body">
+  You are allowed to create up to {{ service.max_profiles }} profiles for this service. You can create a new profile
+  by clicking the following button.
+  <a href="{{ action_create }}" class="btn btn-flat">New profile</a>
+  </div>
+</div>
+{% endif %}
 <div class="row">
 {% for profile in profiles %}
   <div class="col-md-4 col-s-6 col-xs-12">
     <div class="box box-widget widget-user-2">
       <div class="widget-user-header bg-{{ colors[loop.index0 % 7] }}">
-        <form method="POST" action="{{ action }}" class="form">
+        <form method="POST" action="{{ action_pick }}" class="form">
             {{ form.hidden_tag() }}
             <input type="hidden" name="profile_uuid" value="{{ profile.uuid }}">
             <input type="submit" value="Use this" class="btn btn-lg btn-bg-gray text-black pull-right">
diff --git a/trurt/account/templates/account_signup.html b/trurt/account/templates/account_signup.html
new file mode 100644
index 00000000..778e5f5d
--- /dev/null
+++ b/trurt/account/templates/account_signup.html
@@ -0,0 +1,11 @@
+{% extends "base.html" %}
+
+{% block content %}
+<div class="box">
+  <div class="box-body">
+    <p>This account is only meant to access the authentication service. You will then be able to create per-service
+    profiles with different usernames and settings.</p>
+  </div>
+</div>
+{{ macros.form(form) }}
+{% endblock %}
diff --git a/trurt/account/templates/profile_create.html b/trurt/account/templates/profile_create.html
new file mode 100644
index 00000000..a2d63c0f
--- /dev/null
+++ b/trurt/account/templates/profile_create.html
@@ -0,0 +1,11 @@
+{% extends "base.html" %}
+
+{% block content %}
+<div class="box">
+  <div class="box-body">
+    <p>Your profile username does not need to be identical to your account name. Every user is free to pick what profile name they
+    wish for each service.</p>
+  </div>
+</div>
+{{ macros.form(form) }}
+{% endblock %}
diff --git a/trurt/models.py b/trurt/models.py
index 3fafe9f0..719f62ca 100644
--- a/trurt/models.py
+++ b/trurt/models.py
@@ -136,7 +136,7 @@ class Service(db.Model):
     protocol = db.Column(db.String(25))
     name = db.Column(db.String(255))
     description = db.Column(db.String())
-    max_profiles = db.Column(db.Integer())
+    max_profiles = db.Column(db.Integer(), nullable=False, default=1)
     config = db.Column(JSONEncoded)
 
 
-- 
GitLab