]> git.lizzy.rs Git - cheatdb.git/commitdiff
Add email support
authorrubenwardy <rw@rubenwardy.com>
Sun, 13 May 2018 23:40:34 +0000 (00:40 +0100)
committerrubenwardy <rw@rubenwardy.com>
Sun, 13 May 2018 23:40:34 +0000 (00:40 +0100)
app/__init__.py
app/models.py
app/tasks/__init__.py
app/tasks/emails.py [new file with mode: 0644]
app/templates/emails/verify.html [new file with mode: 0644]
app/templates/users/user_profile_page.html
app/views/users.py
config.example.cfg

index 11d7cca7f1ecb059975869a6599810acc92c2fc5..506ed27d8789ee8f3b10d90a40345cfd403bc1f5 100644 (file)
@@ -1,13 +1,12 @@
 from flask import *
 from flask_user import *
 import flask_menu as menu
+from flask_mail import Mail
 from flask.ext import markdown
 from flask_github import GitHub
 from flask_wtf.csrf import CsrfProtect
 import os
 
-
-
 app = Flask(__name__)
 app.config.from_pyfile(os.environ["FLASK_CONFIG"])
 
@@ -15,6 +14,7 @@ menu.Menu(app=app)
 markdown.Markdown(app, extensions=["fenced_code"], safe_mode=True, output_format="html5")
 github = GitHub(app)
 csrf = CsrfProtect(app)
+mail = Mail(app)
 
 from . import models, tasks
 from .views import *
index e0bcb2e669f233a1009b1ceddb1adeda26d021dd..eaa44e80ff4bd0b71df7d68125028d618e66403f 100644 (file)
@@ -49,6 +49,7 @@ class Permission(enum.Enum):
        APPROVE_NEW        = "APPROVE_NEW"
        CHANGE_RELEASE_URL = "CHANGE_RELEASE_URL"
        CHANGE_RANK        = "CHANGE_RANK"
+       CHANGE_EMAIL       = "CHANGE_EMAIL"
        EDIT_EDITREQUEST   = "EDIT_EDITREQUEST"
 
        # Only return true if the permission is valid for *all* contexts
@@ -119,9 +120,17 @@ class User(db.Model, UserMixin):
                        return user.rank.atLeast(UserRank.EDITOR)
                elif perm == Permission.CHANGE_RANK:
                        return user.rank.atLeast(UserRank.MODERATOR)
+               elif perm == Permission.CHANGE_EMAIL:
+                       return user == self or user.rank.atLeast(UserRank.MODERATOR)
                else:
                        raise Exception("Permission {} is not related to users".format(perm.name))
 
+class UserEmailVerification(db.Model):
+       id      = db.Column(db.Integer, primary_key=True)
+       user_id = db.Column(db.Integer, db.ForeignKey("user.id"))
+       email   = db.Column(db.String(100))
+       token   = db.Column(db.String(32))
+       user    = db.relationship("User", foreign_keys=[user_id])
 
 class Notification(db.Model):
        id        = db.Column(db.Integer, primary_key=True)
index 9ee293eae2de99618771854f6c34064fb153cdd2..40a824c47fbf0cf88f698c094d1d57c73441e3bb 100644 (file)
@@ -41,4 +41,4 @@ def make_celery(app):
 
 celery = make_celery(app)
 
-from . import importtasks, forumtasks
+from . import importtasks, forumtasks, emails
diff --git a/app/tasks/emails.py b/app/tasks/emails.py
new file mode 100644 (file)
index 0000000..7040d38
--- /dev/null
@@ -0,0 +1,11 @@
+from flask import *
+from flask_mail import Message
+from app import mail
+from app.tasks import celery
+
+@celery.task()
+def sendVerifyEmail(newEmail, token):
+    msg = Message("Verify email address", recipients=[newEmail])
+    msg.body = "This is a verification email!"
+    msg.html = render_template("emails/verify.html", token=token)
+    mail.send(msg)
diff --git a/app/templates/emails/verify.html b/app/templates/emails/verify.html
new file mode 100644 (file)
index 0000000..a08b174
--- /dev/null
@@ -0,0 +1,17 @@
+<h1>Hello!</h1>
+
+<p>
+       This email has been sent to you because someone (hopefully you)
+       has entered your email address as a user's email.
+</p>
+
+<p>
+       If this was you, then please click this link to verify the address:
+       <a href="{{ url_for('verify_email_page', token=token, _external=True) }}">
+               {{ url_for('verify_email_page', token=token, _external=True) }}
+       </a>
+</p>
+
+<p>
+       If it wasn't you, then just delete this email.
+</p>
index 7e280e1a8f653a6db6374df568f40a378612fc5d..2d429f1539c30baba5035f8f63a06b816badfa78 100644 (file)
                                {% endif %}
                        </td>
                </tr>
-               {% if user == current_user %}
-                       <tr>
-                               <td>Email:</td>
-                               <td>
-                                       {{ user.email }} |
-                                       <a href="">{% if user.email %}change{% else %}add{% endif %}</a>
-                                       &#x1f512;
-                               </td>
-                       </tr>
-                       <tr>
-                               <td>Password:</td>
-                               <td>
-                                       <a href="{{ url_for('user.change_password') }}">
-                                               {% if user.password %}Change password{% else %}Add password{% endif %}
-                                       </a> &#x1f512;
-                               </td>
-                       </tr>
-               {% endif %}
        </table>
 </div>
 
                        <div class="col-sm-6 col-md-5 col-lg-4">
                                {{ form.hidden_tag() }}
 
-                               {{ render_field(form.display_name, tabindex=240) }}
+                               {{ render_field(form.display_name, tabindex=230) }}
+
+                               {% if user.checkPerm(current_user, "CHANGE_EMAIL") %}
+                                       {{ render_field(form.email, tabindex=240) }}
+                               {% endif %}
 
                                {% if user.checkPerm(current_user, "CHANGE_RANK") %}
-                                       {{ render_field(form.rank, tabindex=240) }}
+                                       {{ render_field(form.rank, tabindex=250) }}
                                {% endif %}
 
                                {{ render_submit_field(form.submit, tabindex=280) }}
index e7306c1875d30e17615bc8d9027e18920e531910..a4fb90b9c8ddd8c80b6bc976ce76066baa2f30be 100644 (file)
@@ -10,10 +10,12 @@ from wtforms import *
 from wtforms.validators import *
 from .utils import rank_required, randomString
 from app.tasks.forumtasks import checkForumAccount
+from app.tasks.emails import sendVerifyEmail
 
 # Define the User profile form
 class UserProfileForm(FlaskForm):
-       display_name = StringField("Display name")
+       display_name = StringField("Display name", [InputRequired(), Length(2, 20)])
+       email = StringField("Email")
        rank = SelectField("Rank", [InputRequired()], choices=UserRank.choices(), coerce=UserRank.coerce, default=UserRank.NEW_MEMBER)
        submit = SubmitField("Save")
 
@@ -48,6 +50,21 @@ def user_profile_page(username):
                                else:
                                        flash("Can't promote a user to a rank higher than yourself!", "error")
 
+                       if user.checkPerm(current_user, Permission.CHANGE_EMAIL):
+                               newEmail = form["email"].data
+                               if newEmail != user.email:
+                                       token = randomString(32)
+
+                                       ver = UserEmailVerification()
+                                       ver.user = user
+                                       ver.token = token
+                                       ver.email = newEmail
+                                       db.session.add(ver)
+                                       db.session.commit()
+
+                                       task = sendVerifyEmail.delay(newEmail, token)
+                                       return redirect(url_for("check_task", id=task.id, r=url_for("user_profile_page", username=username)))
+
                        # Save user_profile
                        db.session.commit()
 
@@ -96,3 +113,19 @@ def user_claim_page():
                        flash("Unknown claim type", "error")
 
        return render_template("users/claim.html", username=username, key=randomString(32))
+
+@app.route("/users/verify/")
+def verify_email_page():
+       token = request.args.get("token")
+       ver = UserEmailVerification.query.filter_by(token=token).first()
+       if ver is None:
+               flash("Unknown verification token!", "error")
+       else:
+               ver.user.email = ver.email
+               db.session.delete(ver)
+               db.session.commit()
+
+       if current_user.is_authenticated:
+               return redirect(url_for("user_profile_page", username=current_user.username))
+       else:
+               return redirect(url_for("home_page"))
index 925da5c32947d495655ba99459903ae72890ef6f..53313c6d7919b9ba3ad46cb9fddf76d8b20b16a4 100644 (file)
@@ -1,4 +1,6 @@
 USER_APP_NAME="Content DB"
+SERVER_NAME="content.minetest.net"
+BASE_URL="http://" + SERVER_NAME
 
 SECRET_KEY=""
 WTF_CSRF_SECRET_KEY=""
@@ -8,9 +10,17 @@ SQLALCHEMY_DATABASE_URI = "sqlite:///../db.sqlite"
 GITHUB_CLIENT_ID = ""
 GITHUB_CLIENT_SECRET = ""
 
-BASE_URL="http://localhost:5000/"
+CELERY_BROKER_URL='redis://localhost:6379'
+CELERY_RESULT_BACKEND='redis://localhost:6379'
 
 UPLOAD_FOLDER="tmp"
 
 USER_ENABLE_REGISTER = False
 USER_ENABLE_CHANGE_USERNAME = False
+s
+MAIL_USERNAME=""
+MAIL_PASSWORD=""
+MAIL_DEFAULT_SENDER=""
+MAIL_SERVER=""
+MAIL_PORT=587
+MAIL_USE_TLS=True