mirror of
https://github.com/minetest/contentdb.git
synced 2024-12-22 22:12:24 +01:00
Add email support
This commit is contained in:
parent
acc48c7262
commit
73fa5d1186
@ -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 *
|
||||
|
@ -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)
|
||||
|
@ -41,4 +41,4 @@ def make_celery(app):
|
||||
|
||||
celery = make_celery(app)
|
||||
|
||||
from . import importtasks, forumtasks
|
||||
from . import importtasks, forumtasks, emails
|
||||
|
11
app/tasks/emails.py
Normal file
11
app/tasks/emails.py
Normal file
@ -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)
|
17
app/templates/emails/verify.html
Normal file
17
app/templates/emails/verify.html
Normal file
@ -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>
|
@ -42,24 +42,6 @@
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% if user == current_user %}
|
||||
<tr>
|
||||
<td>Email:</td>
|
||||
<td>
|
||||
{{ user.email }} |
|
||||
<a href="">{% if user.email %}change{% else %}add{% endif %}</a>
|
||||
🔒
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Password:</td>
|
||||
<td>
|
||||
<a href="{{ url_for('user.change_password') }}">
|
||||
{% if user.password %}Change password{% else %}Add password{% endif %}
|
||||
</a> 🔒
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@ -90,10 +72,14 @@
|
||||
<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) }}
|
||||
|
@ -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"))
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user