]> git.lizzy.rs Git - cheatdb.git/blob - app/utils.py
Add package soft deletion
[cheatdb.git] / app / utils.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 request, flash, abort, redirect
19 from flask_user import *
20 from flask_login import login_user, logout_user
21 from app.models import *
22 from app import app
23 import random, string, os
24
25 def getExtension(filename):
26         return filename.rsplit(".", 1)[1].lower() if "." in filename else None
27
28 def isFilenameAllowed(filename, exts):
29         return getExtension(filename) in exts
30
31 def shouldReturnJson():
32         return "application/json" in request.accept_mimetypes and \
33                         not "text/html" in request.accept_mimetypes
34
35 def randomString(n):
36         return ''.join(random.choice(string.ascii_lowercase + \
37                         string.ascii_uppercase + string.digits) for _ in range(n))
38
39 def doFileUpload(file, allowedExtensions, fileTypeName):
40         if not file or file is None or file.filename == "":
41                 flash("No selected file", "error")
42                 return None
43
44         ext = getExtension(file.filename)
45         if ext is None or not ext in allowedExtensions:
46                 flash("Please upload load " + fileTypeName, "error")
47                 return None
48
49         filename = randomString(10) + "." + ext
50         file.save(os.path.join("app/public/uploads", filename))
51         return "/uploads/" + filename
52
53
54 def _do_login_user(user, remember_me=False):
55         def _call_or_get(v):
56                 if callable(v):
57                         return v()
58                 else:
59                         return v
60
61         # User must have been authenticated
62         if not user:
63                 return False
64
65         user.active = True
66         if not user.rank.atLeast(UserRank.NEW_MEMBER):
67                 user.rank = UserRank.NEW_MEMBER
68
69         db.session.commit()
70
71         # Check if user account has been disabled
72         if not _call_or_get(user.is_active):
73                 flash("Your account has not been enabled.", "error")
74                 return False
75
76         # Check if user has a confirmed email address
77         user_manager = current_app.user_manager
78         if user_manager.enable_email and user_manager.enable_confirm_email \
79                         and not current_app.user_manager.enable_login_without_confirm_email \
80                         and not user.has_confirmed_email():
81                 url = url_for("user.resend_confirm_email")
82                 flash("Your email address has not yet been confirmed", "error")
83                 return False
84
85         # Use Flask-Login to sign in user
86         login_user(user, remember=remember_me)
87         signals.user_logged_in.send(current_app._get_current_object(), user=user)
88
89         flash("You have signed in successfully.", "success")
90
91         return True
92
93 def loginUser(user):
94         user_mixin = None
95         if user_manager.enable_username:
96                 user_mixin = user_manager.find_user_by_username(user.username)
97
98         return _do_login_user(user_mixin, False)
99
100 def rank_required(rank):
101         def decorator(f):
102                 @wraps(f)
103                 def decorated_function(*args, **kwargs):
104                         if not current_user.is_authenticated:
105                                 return redirect(url_for("user.login"))
106                         if not current_user.rank.atLeast(rank):
107                                 abort(403)
108
109                         return f(*args, **kwargs)
110
111                 return decorated_function
112         return decorator
113
114 def getPackageByInfo(author, name):
115         user = User.query.filter_by(username=author).first()
116         if user is None:
117                 abort(404)
118
119         package = Package.query.filter_by(name=name, author_id=user.id, soft_deleted=False).first()
120         if package is None:
121                 abort(404)
122
123         return package
124
125 def is_package_page(f):
126         @wraps(f)
127         def decorated_function(*args, **kwargs):
128                 if not ("author" in kwargs and "name" in kwargs):
129                         abort(400)
130
131                 package = getPackageByInfo(kwargs["author"], kwargs["name"])
132
133                 del kwargs["author"]
134                 del kwargs["name"]
135
136                 return f(package=package, *args, **kwargs)
137
138         return decorated_function
139
140 def triggerNotif(owner, causer, title, url):
141         if owner.rank.atLeast(UserRank.NEW_MEMBER) and owner != causer:
142                 Notification.query.filter_by(user=owner, url=url).delete()
143                 notif = Notification(owner, causer, title, url)
144                 db.session.add(notif)
145
146 def clearNotifications(url):
147         if current_user.is_authenticated:
148                 Notification.query.filter_by(user=current_user, url=url).delete()
149                 db.session.commit()