]> git.lizzy.rs Git - cheatdb.git/blobdiff - app/views/users.py
Add topics todo list based on forum parser
[cheatdb.git] / app / views / users.py
index 1dc5e296ab5515e475393a7a207d49b75e78d134..86219f9964a7870108a1edeb98914482191d8633 100644 (file)
+# Content DB
+# Copyright (C) 2018  rubenwardy
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+
 from flask import *
 from flask_user import *
 from flask_login import login_user, logout_user
 from flask.ext import menu
 from app import app
 from app.models import *
-
-
-
-# Define the User registration form
-# It augments the Flask-User RegisterForm with additional fields
-from flask_user.forms import RegisterForm
 from flask_wtf import FlaskForm
-from wtforms import StringField, SubmitField, validators
-class MyRegisterForm(RegisterForm):
-       display_name = StringField("Diplay name")
+from flask_user.forms import RegisterForm
+from wtforms import *
+from wtforms.validators import *
+from app.utils import rank_required, randomString, loginUser
+from app.tasks.forumtasks import checkForumAccount
+from app.tasks.emails import sendVerifyEmail
+from app.tasks.phpbbparser import getProfile
 
 # Define the User profile form
 class UserProfileForm(FlaskForm):
-       display_name = StringField("Diplay name")
-       submit = SubmitField('Save')
+       display_name = StringField("Display name", [Optional(), Length(2, 20)])
+       email = StringField("Email", [Optional(), Email()])
+       rank = SelectField("Rank", [Optional()], choices=UserRank.choices(), coerce=UserRank.coerce, default=UserRank.NEW_MEMBER)
+       submit = SubmitField("Save")
 
-@app.route('/user/', methods=['GET', 'POST'])
-@app.route('/user/<username>/', methods=['GET'])
-def user_profile_page(username=None):
-       user = None
-       form = None
-       if username is None:
-               if not current_user.is_authenticated:
-                       return current_app.login_manager.unauthorized()
-               user = current_user
-       else:
-               user = User.query.filter_by(username=username).first()
-               if not user:
-                       abort(404)
+@app.route("/users/", methods=["GET"])
+@login_required
+def user_list_page():
+       users = User.query.order_by(db.desc(User.rank), db.asc(User.display_name)).all()
+       return render_template("users/list.html", users=users)
+
+
+@app.route("/users/<username>/", methods=["GET", "POST"])
+def user_profile_page(username):
+       user = User.query.filter_by(username=username).first()
+       if not user:
+               abort(404)
 
-       if user == current_user:
+       form = None
+       if user.checkPerm(current_user, Permission.CHANGE_DNAME) or \
+                       user.checkPerm(current_user, Permission.CHANGE_EMAIL) or \
+                       user.checkPerm(current_user, Permission.CHANGE_RANK):
                # Initialize form
-               form = UserProfileForm(formdata=request.form, obj=current_user)
+               form = UserProfileForm(formdata=request.form, obj=user)
 
                # Process valid POST
-               if request.method=='POST' and form.validate():
+               if request.method=="POST" and form.validate():
                        # Copy form fields to user_profile fields
-                       form.populate_obj(current_user)
+                       if user.checkPerm(current_user, Permission.CHANGE_DNAME):
+                               user.display_name = form["display_name"].data
+
+                       if user.checkPerm(current_user, Permission.CHANGE_RANK):
+                               newRank = form["rank"].data
+                               if current_user.rank.atLeast(newRank):
+                                       user.rank = form["rank"].data
+                               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 and newEmail.strip() != "":
+                                       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()
 
                        # Redirect to home page
-                       return redirect(url_for('home_page'))
+                       return redirect(url_for("user_profile_page", username=username))
+
+       packages = user.packages.filter_by(soft_deleted=False)
+       if not current_user.is_authenticated or (user != current_user and not current_user.canAccessTodoList()):
+               packages = packages.filter_by(approved=True)
+       packages = packages.order_by(db.asc(Package.title))
+
+       topics_to_add = None
+       if current_user == user or user.checkPerm(current_user, Permission.CHANGE_AUTHOR):
+               topics_to_add = KrockForumTopic.query \
+                                       .filter_by(author_id=user.id) \
+                                       .filter(~ db.exists().where(Package.forums==KrockForumTopic.topic_id)) \
+                                       .all()
 
        # Process GET or invalid POST
-       return render_template('users/user_profile_page.html',
-                       user=user, form=form)
+       return render_template("users/user_profile_page.html",
+                       user=user, form=form, packages=packages, topics_to_add=topics_to_add)
+
+class SetPasswordForm(FlaskForm):
+       email = StringField("Email (Optional)", [Optional(), Email()])
+       password = PasswordField("New password", [InputRequired(), Length(2, 20)])
+       password2 = PasswordField("Verify password", [InputRequired(), Length(2, 20)])
+       submit = SubmitField("Save")
+
+@app.route("/user/set-password/", methods=["GET", "POST"])
+@login_required
+def set_password_page():
+       if current_user.password is not None:
+               return redirect(url_for("user.change_password"))
+
+       form = SetPasswordForm(request.form)
+       if request.method == "POST" and form.validate():
+               one = form.password.data
+               two = form.password2.data
+               if one == two:
+                       # Hash password
+                       hashed_password = user_manager.hash_password(form.password.data)
+
+                       # Change password
+                       user_manager.update_password(current_user, hashed_password)
+
+                       # Send 'password_changed' email
+                       if user_manager.enable_email and user_manager.send_password_changed_email and current_user.email:
+                               emails.send_password_changed_email(current_user)
+
+                       # Send password_changed signal
+                       signals.user_changed_password.send(current_app._get_current_object(), user=current_user)
+
+                       # Prepare one-time system message
+                       flash('Your password has been changed successfully.', 'success')
+
+                       newEmail = form["email"].data
+                       if newEmail != current_user.email and newEmail.strip() != "":
+                               token = randomString(32)
+
+                               ver = UserEmailVerification()
+                               ver.user = current_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=current_user.username)))
+                       else:
+                               return redirect(url_for("user_profile_page", username=current_user.username))
+               else:
+                       flash("Passwords do not match", "error")
+
+       return render_template("users/set_password.html", form=form)
+
+
+@app.route("/user/claim/", methods=["GET", "POST"])
+def user_claim_page():
+       username = request.args.get("username")
+       if username is None:
+               username = ""
+       else:
+               method = request.args.get("method")
+               user = User.query.filter_by(forums_username=username).first()
+               if user and user.rank.atLeast(UserRank.NEW_MEMBER):
+                       flash("User has already been claimed", "error")
+                       return redirect(url_for("user_claim_page"))
+               elif user is None and method == "github":
+                       flash("Unable to get Github username for user", "error")
+                       return redirect(url_for("user_claim_page"))
+               elif user is None:
+                       flash("Unable to find that user", "error")
+                       return redirect(url_for("user_claim_page"))
+
+               if user is not None and method == "github":
+                       return redirect(url_for("github_signin_page"))
+
+       token = None
+       if "forum_token" in session:
+               token = session["forum_token"]
+       else:
+               token = randomString(32)
+               session["forum_token"] = token
+
+       if request.method == "POST":
+               ctype   = request.form.get("claim_type")
+               username = request.form.get("username")
+
+               if username is None or len(username.strip()) < 2:
+                       flash("Invalid username", "error")
+               elif ctype == "github":
+                       task = checkForumAccount.delay(username)
+                       return redirect(url_for("check_task", id=task.id, r=url_for("user_claim_page", username=username, method="github")))
+               elif ctype == "forum":
+                       user = User.query.filter_by(forums_username=username).first()
+                       if user is not None and user.rank.atLeast(UserRank.NEW_MEMBER):
+                               flash("That user has already been claimed!", "error")
+                               return redirect(url_for("user_claim_page"))
+
+                       # Get signature
+                       sig = None
+                       try:
+                               profile = getProfile("https://forum.minetest.net", username)
+                               sig = profile.signature
+                       except IOError:
+                               flash("Unable to get forum signature - does the user exist?", "error")
+                               return redirect(url_for("user_claim_page", username=username))
+
+                       # Look for key
+                       if token in sig:
+                               if user is None:
+                                       user = User(username)
+                                       user.forums_username = username
+                                       db.session.add(user)
+                                       db.session.commit()
+
+                               if loginUser(user):
+                                       return redirect(url_for("set_password_page"))
+                               else:
+                                       flash("Unable to login as user", "error")
+                                       return redirect(url_for("user_claim_page", username=username))
+
+                       else:
+                               flash("Could not find the key in your signature!", "error")
+                               return redirect(url_for("user_claim_page", username=username))
+               else:
+                       flash("Unknown claim type", "error")
+
+       return render_template("users/claim.html", username=username, key=token)
+
+@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"))