def toggle_favourite(key): """ 'Like' a dataset Marks the dataset as being liked by the currently active user, which can be used for organisation in the front-end. :param str key: Key of the dataset to mark as favourite. :return: A JSON object with the status of the request :return-schema: {type=object,properties={success={type=boolean},favourite_status={type=boolean}}} :return-error 404: If the dataset key was not found """ try: dataset = DataSet(key=key, db=db) except TypeError: return error(404, error="Dataset does not exist.") current_status = db.fetchone("SELECT * FROM users_favourites WHERE name = %s AND key = %s", (current_user.get_id(), dataset.key)) if not current_status: db.insert("users_favourites", data={"name": current_user.get_id(), "key": dataset.key}) return jsonify({"success": True, "favourite_status": True}) else: db.delete("users_favourites", where={"name": current_user.get_id(), "key": dataset.key}) return jsonify({"success": True, "favourite_status": False})
def request_token(): """ Request an access token Requires that the user is currently logged in to 4CAT. :return: An object with one item `token` :return-schema={type=object,properties={token={type=string}}} :return-error 403: If the user is logged in with an anonymous account. """ if current_user.get_id() == "autologin": # access tokens are only for 'real' users so we can keep track of who # (ab)uses them return error(403, error="Anonymous users may not request access tokens.") token = db.fetchone( "SELECT * FROM access_tokens WHERE name = %s AND (expires = 0 OR expires > %s)", (current_user.get_id(), int(time.time()))) if token: token = token["token"] else: token = current_user.get_id() + str(time.time()) token = hashlib.sha256(token.encode("utf8")).hexdigest() token = { "name": current_user.get_id(), "token": token, "expires": int(time.time()) + (365 * 86400) } # delete any expired tokens db.delete("access_tokens", where={"name": current_user.get_id()}) # save new token db.insert("access_tokens", token) if request.args.get("forward"): # show HTML page return redirect(url_for("show_access_tokens")) else: # show JSON response (by default) return jsonify(token)
def add_user(): if not current_user.is_admin(): return error(403, message="This page is off-limits to you.") response = {"success": False} email = request.form.get("email", request.args.get("email", "")).strip() if not email or not re.match(r"[^@]+\@.*?\.[a-zA-Z]+", email): response = {**response, **{"message": "Please provide a valid e-mail address."}} else: username = email try: db.insert("users", data={"name": username, "timestamp_token": int(time.time())}) user = User.get_by_name(username) if user is None: response = {**response, **{"message": "User was created but could not be instantiated properly."}} else: try: user.email_token(new=True) response["success"] = True response = {**response, **{ "message": "An e-mail containing a link through which the registration can be completed has been sent to %s." % username}} except RuntimeError as e: response = {**response, **{ "message": "User was created but the registration e-mail could not be sent to them (%s)." % e}} except psycopg2.IntegrityError: db.rollback() response = {**response, **{"message": "Error: User %s already exists." % username}} if request.args.get("format", None) == "html": return render_template("error.html", message=response["message"], title=("New account created" if response["success"] else "Error")) else: return jsonify(response)
def add_user(): """ Create a new user Sends the user an e-mail with a link through which they can set their password. :return: Either an html page with a message, or a JSON response, depending on whether ?format == html """ if not current_user.is_authenticated or not current_user.is_admin(): return error(403, message="This page is off-limits to you.") response = {"success": False} email = request.form.get("email", request.args.get("email", "")).strip() fmt = request.form.get("format", request.args.get("format", "")).strip() force = request.form.get("force", request.args.get("force", None)) if not email or not re.match(r"[^@]+\@.*?\.[a-zA-Z]+", email): response = { **response, **{ "message": "Please provide a valid e-mail address." } } else: username = email try: db.insert("users", data={ "name": username, "timestamp_token": int(time.time()) }) user = User.get_by_name(username) if user is None: response = { **response, **{ "message": "User was created but could not be instantiated properly." } } else: try: user.email_token(new=True) response["success"] = True response = { **response, **{ "message": "An e-mail containing a link through which the registration can be completed has been sent to %s." % username } } except RuntimeError as e: response = { **response, **{ "message": "User was created but the registration e-mail could not be sent to them (%s)." % e } } except psycopg2.IntegrityError: db.rollback() if not force: response = { **response, **{ "message": 'Error: User %s already exists. If you want to re-create the user and re-send the registration e-mail, use [this link](/admin/add-user?email=%s&force=1&format=%s).' % (username, username, fmt) } } else: # if a user does not use their token in time, maybe you want to # be a benevolent admin and give them another change, without # having them go through the whole signup again user = User.get_by_name(username) db.update("users", data={"timestamp_token": int(time.time())}, where={"name": username}) try: user.email_token(new=True) response["success"] = True response = { **response, **{ "message": "A new registration e-mail has been sent to %s." % username } } except RuntimeError as e: response = { **response, **{ "message": "Token was reset registration e-mail could not be sent to them (%s)." % e } } if fmt == "html": return render_template( "error.html", message=response["message"], title=("New account created" if response["success"] else "Error")) else: return jsonify(response)