]> git.lizzy.rs Git - cheatdb.git/blob - app/views/users.py
Add list of similar packages in details page
[cheatdb.git] / app / views / users.py
1 # Content DB
2 # Copyright (C) 2018  rubenwardy
3 #
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program.  If not, see <https://www.gnu.org/licenses/>.
16
17
18 from flask import *
19 from flask_user import *
20 from flask_login import login_user, logout_user
21 from flask.ext import menu
22 from app import app
23 from app.models import *
24 from flask_wtf import FlaskForm
25 from flask_user.forms import RegisterForm
26 from wtforms import *
27 from wtforms.validators import *
28 from app.utils import rank_required, randomString, loginUser
29 from app.tasks.forumtasks import checkForumAccount
30 from app.tasks.emails import sendVerifyEmail
31 from app.tasks.phpbbparser import getProfile
32
33 # Define the User profile form
34 class UserProfileForm(FlaskForm):
35         display_name = StringField("Display name", [Optional(), Length(2, 20)])
36         email = StringField("Email", [Optional(), Email()])
37         rank = SelectField("Rank", [Optional()], choices=UserRank.choices(), coerce=UserRank.coerce, default=UserRank.NEW_MEMBER)
38         submit = SubmitField("Save")
39
40 @app.route("/users/", methods=["GET"])
41 @login_required
42 def user_list_page():
43         users = User.query.order_by(db.desc(User.rank), db.asc(User.display_name)).all()
44         return render_template("users/list.html", users=users)
45
46
47 @app.route("/users/<username>/", methods=["GET", "POST"])
48 def user_profile_page(username):
49         user = User.query.filter_by(username=username).first()
50         if not user:
51                 abort(404)
52
53         form = None
54         if user.checkPerm(current_user, Permission.CHANGE_DNAME) or \
55                         user.checkPerm(current_user, Permission.CHANGE_EMAIL) or \
56                         user.checkPerm(current_user, Permission.CHANGE_RANK):
57                 # Initialize form
58                 form = UserProfileForm(formdata=request.form, obj=user)
59
60                 # Process valid POST
61                 if request.method=="POST" and form.validate():
62                         # Copy form fields to user_profile fields
63                         if user.checkPerm(current_user, Permission.CHANGE_DNAME):
64                                 user.display_name = form["display_name"].data
65
66                         if user.checkPerm(current_user, Permission.CHANGE_RANK):
67                                 newRank = form["rank"].data
68                                 if current_user.rank.atLeast(newRank):
69                                         user.rank = form["rank"].data
70                                 else:
71                                         flash("Can't promote a user to a rank higher than yourself!", "error")
72
73                         if user.checkPerm(current_user, Permission.CHANGE_EMAIL):
74                                 newEmail = form["email"].data
75                                 if newEmail != user.email and newEmail.strip() != "":
76                                         token = randomString(32)
77
78                                         ver = UserEmailVerification()
79                                         ver.user = user
80                                         ver.token = token
81                                         ver.email = newEmail
82                                         db.session.add(ver)
83                                         db.session.commit()
84
85                                         task = sendVerifyEmail.delay(newEmail, token)
86                                         return redirect(url_for("check_task", id=task.id, r=url_for("user_profile_page", username=username)))
87
88                         # Save user_profile
89                         db.session.commit()
90
91                         # Redirect to home page
92                         return redirect(url_for("user_profile_page", username=username))
93
94         packages = user.packages.filter_by(soft_deleted=False)
95         if not current_user.is_authenticated or (user != current_user and not current_user.canAccessTodoList()):
96                 packages = packages.filter_by(approved=True)
97         packages = packages.order_by(db.asc(Package.title))
98
99         topics_to_add = None
100         if current_user == user or user.checkPerm(current_user, Permission.CHANGE_AUTHOR):
101                 topics_to_add = KrockForumTopic.query \
102                                         .filter_by(author_id=user.id) \
103                                         .filter(~ db.exists().where(Package.forums==KrockForumTopic.topic_id)) \
104                                         .order_by(db.asc(KrockForumTopic.name), db.asc(KrockForumTopic.title)) \
105                                         .all()
106
107         # Process GET or invalid POST
108         return render_template("users/user_profile_page.html",
109                         user=user, form=form, packages=packages, topics_to_add=topics_to_add)
110
111 class SetPasswordForm(FlaskForm):
112         email = StringField("Email (Optional)", [Optional(), Email()])
113         password = PasswordField("New password", [InputRequired(), Length(2, 20)])
114         password2 = PasswordField("Verify password", [InputRequired(), Length(2, 20)])
115         submit = SubmitField("Save")
116
117 @app.route("/user/set-password/", methods=["GET", "POST"])
118 @login_required
119 def set_password_page():
120         if current_user.password is not None:
121                 return redirect(url_for("user.change_password"))
122
123         form = SetPasswordForm(request.form)
124         if request.method == "POST" and form.validate():
125                 one = form.password.data
126                 two = form.password2.data
127                 if one == two:
128                         # Hash password
129                         hashed_password = user_manager.hash_password(form.password.data)
130
131                         # Change password
132                         user_manager.update_password(current_user, hashed_password)
133
134                         # Send 'password_changed' email
135                         if user_manager.enable_email and user_manager.send_password_changed_email and current_user.email:
136                                 emails.send_password_changed_email(current_user)
137
138                         # Send password_changed signal
139                         signals.user_changed_password.send(current_app._get_current_object(), user=current_user)
140
141                         # Prepare one-time system message
142                         flash('Your password has been changed successfully.', 'success')
143
144                         newEmail = form["email"].data
145                         if newEmail != current_user.email and newEmail.strip() != "":
146                                 token = randomString(32)
147
148                                 ver = UserEmailVerification()
149                                 ver.user = current_user
150                                 ver.token = token
151                                 ver.email = newEmail
152                                 db.session.add(ver)
153                                 db.session.commit()
154
155                                 task = sendVerifyEmail.delay(newEmail, token)
156                                 return redirect(url_for("check_task", id=task.id, r=url_for("user_profile_page", username=current_user.username)))
157                         else:
158                                 return redirect(url_for("user_profile_page", username=current_user.username))
159                 else:
160                         flash("Passwords do not match", "error")
161
162         return render_template("users/set_password.html", form=form)
163
164
165 @app.route("/user/claim/", methods=["GET", "POST"])
166 def user_claim_page():
167         username = request.args.get("username")
168         if username is None:
169                 username = ""
170         else:
171                 method = request.args.get("method")
172                 user = User.query.filter_by(forums_username=username).first()
173                 if user and user.rank.atLeast(UserRank.NEW_MEMBER):
174                         flash("User has already been claimed", "error")
175                         return redirect(url_for("user_claim_page"))
176                 elif user is None and method == "github":
177                         flash("Unable to get Github username for user", "error")
178                         return redirect(url_for("user_claim_page"))
179                 elif user is None:
180                         flash("Unable to find that user", "error")
181                         return redirect(url_for("user_claim_page"))
182
183                 if user is not None and method == "github":
184                         return redirect(url_for("github_signin_page"))
185
186         token = None
187         if "forum_token" in session:
188                 token = session["forum_token"]
189         else:
190                 token = randomString(32)
191                 session["forum_token"] = token
192
193         if request.method == "POST":
194                 ctype   = request.form.get("claim_type")
195                 username = request.form.get("username")
196
197                 if username is None or len(username.strip()) < 2:
198                         flash("Invalid username", "error")
199                 elif ctype == "github":
200                         task = checkForumAccount.delay(username)
201                         return redirect(url_for("check_task", id=task.id, r=url_for("user_claim_page", username=username, method="github")))
202                 elif ctype == "forum":
203                         user = User.query.filter_by(forums_username=username).first()
204                         if user is not None and user.rank.atLeast(UserRank.NEW_MEMBER):
205                                 flash("That user has already been claimed!", "error")
206                                 return redirect(url_for("user_claim_page"))
207
208                         # Get signature
209                         sig = None
210                         try:
211                                 profile = getProfile("https://forum.minetest.net", username)
212                                 sig = profile.signature
213                         except IOError:
214                                 flash("Unable to get forum signature - does the user exist?", "error")
215                                 return redirect(url_for("user_claim_page", username=username))
216
217                         # Look for key
218                         if token in sig:
219                                 if user is None:
220                                         user = User(username)
221                                         user.forums_username = username
222                                         db.session.add(user)
223                                         db.session.commit()
224
225                                 if loginUser(user):
226                                         return redirect(url_for("set_password_page"))
227                                 else:
228                                         flash("Unable to login as user", "error")
229                                         return redirect(url_for("user_claim_page", username=username))
230
231                         else:
232                                 flash("Could not find the key in your signature!", "error")
233                                 return redirect(url_for("user_claim_page", username=username))
234                 else:
235                         flash("Unknown claim type", "error")
236
237         return render_template("users/claim.html", username=username, key=token)
238
239 @app.route("/users/verify/")
240 def verify_email_page():
241         token = request.args.get("token")
242         ver = UserEmailVerification.query.filter_by(token=token).first()
243         if ver is None:
244                 flash("Unknown verification token!", "error")
245         else:
246                 ver.user.email = ver.email
247                 db.session.delete(ver)
248                 db.session.commit()
249
250         if current_user.is_authenticated:
251                 return redirect(url_for("user_profile_page", username=current_user.username))
252         else:
253                 return redirect(url_for("home_page"))