diff --git a/app/models.py b/app/models.py index 3a41c83..d3cba53 100644 --- a/app/models.py +++ b/app/models.py @@ -19,7 +19,7 @@ from flask import Flask, url_for from flask_sqlalchemy import SQLAlchemy from flask_migrate import Migrate from urllib.parse import urlparse -from app import app +from app import app, gravatar from datetime import datetime from sqlalchemy.orm import validates from flask_user import login_required, UserManager, UserMixin, SQLAlchemyAdapter @@ -97,26 +97,27 @@ class Permission(enum.Enum): raise Exception("Non-global permission checked globally. Use Package.checkPerm or User.checkPerm instead.") class User(db.Model, UserMixin): - id = db.Column(db.Integer, primary_key=True) + id = db.Column(db.Integer, primary_key=True) # User authentication information - username = db.Column(db.String(50, collation="NOCASE"), nullable=False, unique=True, index=True) - password = db.Column(db.String(255), nullable=True) + username = db.Column(db.String(50, collation="NOCASE"), nullable=False, unique=True, index=True) + password = db.Column(db.String(255), nullable=True) reset_password_token = db.Column(db.String(100), nullable=False, server_default="") - rank = db.Column(db.Enum(UserRank)) + rank = db.Column(db.Enum(UserRank)) # Account linking github_username = db.Column(db.String(50, collation="NOCASE"), nullable=True, unique=True) forums_username = db.Column(db.String(50, collation="NOCASE"), nullable=True, unique=True) # User email information - email = db.Column(db.String(255), nullable=True, unique=True) - confirmed_at = db.Column(db.DateTime()) + email = db.Column(db.String(255), nullable=True, unique=True) + confirmed_at = db.Column(db.DateTime()) # User information - active = db.Column("is_active", db.Boolean, nullable=False, server_default="0") - display_name = db.Column(db.String(100), nullable=False, server_default="") + profile_pic = db.Column(db.String(255), nullable=True, server_default=None) + active = db.Column("is_active", db.Boolean, nullable=False, server_default="0") + display_name = db.Column(db.String(100), nullable=False, server_default="") # Content notifications = db.relationship("Notification", primaryjoin="User.id==Notification.user_id") @@ -146,6 +147,12 @@ class User(db.Model, UserMixin): def isClaimed(self): return self.rank.atLeast(UserRank.NEW_MEMBER) + def getProfilePicURL(self): + if self.profile_pic: + return self.profile_pic + else: + return gravatar(self.email or "") + def checkPerm(self, user, perm): if not user.is_authenticated: return False diff --git a/app/tasks/forumtasks.py b/app/tasks/forumtasks.py index 1df6d2b..0a5f028 100644 --- a/app/tasks/forumtasks.py +++ b/app/tasks/forumtasks.py @@ -25,7 +25,7 @@ import urllib.request from urllib.parse import urlparse, quote_plus @celery.task() -def checkForumAccount(username, token=None): +def checkForumAccount(username): try: profile = getProfile("https://forum.minetest.net", username) except OSError: @@ -47,6 +47,10 @@ def checkForumAccount(username, token=None): user.github_username = github_username needsSaving = True + pic = profile.avatar + needsSaving = needsSaving or pic != user.profile_pic + user.profile_pic = pic + # Save if needsSaving: db.session.commit() diff --git a/app/tasks/phpbbparser.py b/app/tasks/phpbbparser.py index 9984ad0..d3e1231 100644 --- a/app/tasks/phpbbparser.py +++ b/app/tasks/phpbbparser.py @@ -15,8 +15,9 @@ def urlEncodeNonAscii(b): class Profile: def __init__(self, username): - self.username = username - self.signature = "" + self.username = username + self.signature = "" + self.avatar = None self.properties = {} def set(self, key, value): @@ -33,6 +34,11 @@ def __extract_properties(profile, soup): if el is None: return None + res1 = el.find_all("dl") + imgs = res1[0].find_all("img") + if len(imgs) == 1: + profile.avatar = imgs[0]["src"] + res = el.find_all("dl", class_ = "left-box details") if len(res) != 1: return None diff --git a/app/templates/users/user_profile_page.html b/app/templates/users/user_profile_page.html index 46881fd..26988ba 100644 --- a/app/templates/users/user_profile_page.html +++ b/app/templates/users/user_profile_page.html @@ -21,11 +21,13 @@

{{ user.display_name }}

- {% if user.email %} + {% if user.forums_username %} + + {% elif user.email %} {% endif %} - - {% if user.email %} + + {% if user.forums_username or user.email %} {% endif %}
@@ -67,14 +69,23 @@ Profile Picture: + {% if user.forums_username %} +
+ + +
+ {% endif %} {% if user.email %} Gravatar {% else %} -

- Please add an email to your profile. -

+ + Gravatar + {% endif %} diff --git a/app/views/users.py b/app/views/users.py index 7c8cfdd..d81c832 100644 --- a/app/views/users.py +++ b/app/views/users.py @@ -106,6 +106,26 @@ def user_profile_page(username): return render_template("users/user_profile_page.html", user=user, form=form, packages=packages, topics_to_add=topics_to_add) + +@app.route("/users//check/", methods=["POST"]) +@login_required +def user_check(username): + user = User.query.filter_by(username=username).first() + if user is None: + abort(404) + + if current_user != user and not current_user.rank.atLeast(UserRank.MODERATOR): + abort(403) + + if user.forums_username is None: + abort(404) + + task = checkForumAccount.delay(user.forums_username) + next_url = url_for("user_profile_page", username=username) + + return redirect(url_for("check_task", id=task.id, r=next_url)) + + class SetPasswordForm(FlaskForm): email = StringField("Email", [Optional(), Email()]) password = PasswordField("New password", [InputRequired(), Length(2, 20)]) diff --git a/migrations/versions/dce69ad1e4eb_.py b/migrations/versions/dce69ad1e4eb_.py new file mode 100644 index 0000000..9276d9d --- /dev/null +++ b/migrations/versions/dce69ad1e4eb_.py @@ -0,0 +1,28 @@ +"""empty message + +Revision ID: dce69ad1e4eb +Revises: a791b9b74a4c +Create Date: 2018-12-25 18:57:44.575501 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'dce69ad1e4eb' +down_revision = 'a791b9b74a4c' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column("user", sa.Column('profile_pic', sa.String(length=255), nullable=True)) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column("user", "profile_pic") + # ### end Alembic commands ###