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 import *
|
||||||
from flask_user import *
|
from flask_user import *
|
||||||
import flask_menu as menu
|
import flask_menu as menu
|
||||||
|
from flask_mail import Mail
|
||||||
from flask.ext import markdown
|
from flask.ext import markdown
|
||||||
from flask_github import GitHub
|
from flask_github import GitHub
|
||||||
from flask_wtf.csrf import CsrfProtect
|
from flask_wtf.csrf import CsrfProtect
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
app.config.from_pyfile(os.environ["FLASK_CONFIG"])
|
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")
|
markdown.Markdown(app, extensions=["fenced_code"], safe_mode=True, output_format="html5")
|
||||||
github = GitHub(app)
|
github = GitHub(app)
|
||||||
csrf = CsrfProtect(app)
|
csrf = CsrfProtect(app)
|
||||||
|
mail = Mail(app)
|
||||||
|
|
||||||
from . import models, tasks
|
from . import models, tasks
|
||||||
from .views import *
|
from .views import *
|
||||||
|
@ -49,6 +49,7 @@ class Permission(enum.Enum):
|
|||||||
APPROVE_NEW = "APPROVE_NEW"
|
APPROVE_NEW = "APPROVE_NEW"
|
||||||
CHANGE_RELEASE_URL = "CHANGE_RELEASE_URL"
|
CHANGE_RELEASE_URL = "CHANGE_RELEASE_URL"
|
||||||
CHANGE_RANK = "CHANGE_RANK"
|
CHANGE_RANK = "CHANGE_RANK"
|
||||||
|
CHANGE_EMAIL = "CHANGE_EMAIL"
|
||||||
EDIT_EDITREQUEST = "EDIT_EDITREQUEST"
|
EDIT_EDITREQUEST = "EDIT_EDITREQUEST"
|
||||||
|
|
||||||
# Only return true if the permission is valid for *all* contexts
|
# 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)
|
return user.rank.atLeast(UserRank.EDITOR)
|
||||||
elif perm == Permission.CHANGE_RANK:
|
elif perm == Permission.CHANGE_RANK:
|
||||||
return user.rank.atLeast(UserRank.MODERATOR)
|
return user.rank.atLeast(UserRank.MODERATOR)
|
||||||
|
elif perm == Permission.CHANGE_EMAIL:
|
||||||
|
return user == self or user.rank.atLeast(UserRank.MODERATOR)
|
||||||
else:
|
else:
|
||||||
raise Exception("Permission {} is not related to users".format(perm.name))
|
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):
|
class Notification(db.Model):
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
@ -41,4 +41,4 @@ def make_celery(app):
|
|||||||
|
|
||||||
celery = 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 %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</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>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -90,10 +72,14 @@
|
|||||||
<div class="col-sm-6 col-md-5 col-lg-4">
|
<div class="col-sm-6 col-md-5 col-lg-4">
|
||||||
{{ form.hidden_tag() }}
|
{{ 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") %}
|
{% if user.checkPerm(current_user, "CHANGE_RANK") %}
|
||||||
{{ render_field(form.rank, tabindex=240) }}
|
{{ render_field(form.rank, tabindex=250) }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{{ render_submit_field(form.submit, tabindex=280) }}
|
{{ render_submit_field(form.submit, tabindex=280) }}
|
||||||
|
@ -10,10 +10,12 @@ from wtforms import *
|
|||||||
from wtforms.validators import *
|
from wtforms.validators import *
|
||||||
from .utils import rank_required, randomString
|
from .utils import rank_required, randomString
|
||||||
from app.tasks.forumtasks import checkForumAccount
|
from app.tasks.forumtasks import checkForumAccount
|
||||||
|
from app.tasks.emails import sendVerifyEmail
|
||||||
|
|
||||||
# Define the User profile form
|
# Define the User profile form
|
||||||
class UserProfileForm(FlaskForm):
|
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)
|
rank = SelectField("Rank", [InputRequired()], choices=UserRank.choices(), coerce=UserRank.coerce, default=UserRank.NEW_MEMBER)
|
||||||
submit = SubmitField("Save")
|
submit = SubmitField("Save")
|
||||||
|
|
||||||
@ -48,6 +50,21 @@ def user_profile_page(username):
|
|||||||
else:
|
else:
|
||||||
flash("Can't promote a user to a rank higher than yourself!", "error")
|
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
|
# Save user_profile
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
@ -96,3 +113,19 @@ def user_claim_page():
|
|||||||
flash("Unknown claim type", "error")
|
flash("Unknown claim type", "error")
|
||||||
|
|
||||||
return render_template("users/claim.html", username=username, key=randomString(32))
|
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"
|
USER_APP_NAME="Content DB"
|
||||||
|
SERVER_NAME="content.minetest.net"
|
||||||
|
BASE_URL="http://" + SERVER_NAME
|
||||||
|
|
||||||
SECRET_KEY=""
|
SECRET_KEY=""
|
||||||
WTF_CSRF_SECRET_KEY=""
|
WTF_CSRF_SECRET_KEY=""
|
||||||
@ -8,9 +10,17 @@ SQLALCHEMY_DATABASE_URI = "sqlite:///../db.sqlite"
|
|||||||
GITHUB_CLIENT_ID = ""
|
GITHUB_CLIENT_ID = ""
|
||||||
GITHUB_CLIENT_SECRET = ""
|
GITHUB_CLIENT_SECRET = ""
|
||||||
|
|
||||||
BASE_URL="http://localhost:5000/"
|
CELERY_BROKER_URL='redis://localhost:6379'
|
||||||
|
CELERY_RESULT_BACKEND='redis://localhost:6379'
|
||||||
|
|
||||||
UPLOAD_FOLDER="tmp"
|
UPLOAD_FOLDER="tmp"
|
||||||
|
|
||||||
USER_ENABLE_REGISTER = False
|
USER_ENABLE_REGISTER = False
|
||||||
USER_ENABLE_CHANGE_USERNAME = 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