diff options
author | rubenwardy <rw@rubenwardy.com> | 2018-05-13 23:31:42 +0100 |
---|---|---|
committer | rubenwardy <rw@rubenwardy.com> | 2018-05-13 23:33:05 +0100 |
commit | ff8bf992a9048e55b58ece46cf25cc3a43edcef7 (patch) | |
tree | 02a1a7198a9fd20539465a0ccd378f0dd02f8913 | |
parent | 31615da169766087a35c104d6aa8797a6eaa7594 (diff) | |
download | cheatdb-ff8bf992a9048e55b58ece46cf25cc3a43edcef7.tar.xz |
Add user account claiming
-rw-r--r-- | app/tasks/__init__.py | 2 | ||||
-rw-r--r-- | app/tasks/forumtasks.py | 33 | ||||
-rw-r--r-- | app/tasks/phpbbparser.py | 72 | ||||
-rw-r--r-- | app/templates/flask_user/login.html | 17 | ||||
-rw-r--r-- | app/templates/users/claim.html | 98 | ||||
-rw-r--r-- | app/views/githublogin.py | 12 | ||||
-rw-r--r-- | app/views/tasks.py | 2 | ||||
-rw-r--r-- | app/views/users.py | 42 | ||||
-rw-r--r-- | requirements.txt | 2 |
9 files changed, 253 insertions, 27 deletions
diff --git a/app/tasks/__init__.py b/app/tasks/__init__.py index c431fae..9ee293e 100644 --- a/app/tasks/__init__.py +++ b/app/tasks/__init__.py @@ -41,4 +41,4 @@ def make_celery(app): celery = make_celery(app) -from . import importtasks +from . import importtasks, forumtasks diff --git a/app/tasks/forumtasks.py b/app/tasks/forumtasks.py new file mode 100644 index 0000000..e4ddc59 --- /dev/null +++ b/app/tasks/forumtasks.py @@ -0,0 +1,33 @@ +import flask +from flask.ext.sqlalchemy import SQLAlchemy +from app import app +from app.models import * +from app.tasks import celery +from .phpbbparser import getProfile + +@celery.task() +def checkForumAccount(username, token=None): + try: + profile = getProfile("https://forum.minetest.net", username) + except OSError: + return + + user = User.query.filter_by(forums_username=username).first() + + # Create user + needsSaving = False + if user is None: + user = User(username) + user.forums_username = username + db.session.add(user) + + # Get github username + github_username = profile.get("github") + if github_username is not None and github_username.strip() != "": + print("Updated github username") + user.github_username = github_username + needsSaving = True + + # Save + if needsSaving: + db.session.commit() diff --git a/app/tasks/phpbbparser.py b/app/tasks/phpbbparser.py new file mode 100644 index 0000000..3932b94 --- /dev/null +++ b/app/tasks/phpbbparser.py @@ -0,0 +1,72 @@ +import urllib, socket +from bs4 import * +from urllib.parse import urljoin +import urllib.request +import os.path +import time + +class Profile: + def __init__(self, username): + self.username = username + self.signature = "" + self.properties = {} + + def set(self, key, value): + self.properties[key] = value + + def get(self, key): + return self.properties[key] if key in self.properties else None + + def __str__(self): + return self.username + "\n" + str(self.signature) + "\n" + str(self.properties) + +def __extract_properties(profile, soup): + el = soup.find(id="viewprofile") + if el is None: + return None + + res = el.find_all("dl", class_ = "left-box details") + if len(res) != 1: + return None + + catch_next_key = None + + # Look through + for element in res[0].children: + if element.name == "dt": + if catch_next_key is None: + catch_next_key = element.text.lower()[:-1].strip() + else: + print("Unexpected dt!") + + elif element.name == "dd": + if catch_next_key is None: + print("Unexpected dd!") + else: + if catch_next_key != "groups": + profile.set(catch_next_key, element.text) + catch_next_key = None + + elif element and element.name is not None: + print("Unexpected other") + +def __extract_signature(soup): + res = soup.find_all("div", class_="signature") + if (len(res) != 1): + return None + else: + return res[0] + +def getProfile(url, username): + url = url + "/memberlist.php?mode=viewprofile&un=" + username + + contents = urllib.request.urlopen(url).read().decode("utf-8") + soup = BeautifulSoup(contents, "lxml") + if soup is None: + return None + else: + profile = Profile(username) + profile.signature = __extract_signature(soup) + __extract_properties(profile, soup) + + return profile diff --git a/app/templates/flask_user/login.html b/app/templates/flask_user/login.html index c19f1f3..c676aca 100644 --- a/app/templates/flask_user/login.html +++ b/app/templates/flask_user/login.html @@ -61,26 +61,17 @@ Sign in {# Submit button #} {{ render_submit_field(form.submit, tabindex=180) }} </form> + + <a href="{{ url_for('github_signin_page') }}">GitHub</a> </div> <div class="right"> <aside class="box box_grey"> <h2>New here?</h2> - <div class="box box_grey alert alert-error"> - Please use Github login instead! - </div> - - {% if user_manager.enable_register and not user_manager.require_invitation %} - <a href="{{ url_for('github_signin_page') }}">{%trans%}Create an account{%endtrans%}</a> - {% endif %} - </aside> + <p>Create an account using your forum account.</p> - - <aside class="box box_grey"> - <h2>OAUTH</h2> - - <a href="{{ url_for('github_signin_page') }}">GitHub</a> + <a href="{{ url_for('user_claim_page') }}" class="button">{%trans%}Claim your account{%endtrans%}</a> </aside> </div> </div> diff --git a/app/templates/users/claim.html b/app/templates/users/claim.html new file mode 100644 index 0000000..f4333d9 --- /dev/null +++ b/app/templates/users/claim.html @@ -0,0 +1,98 @@ +{% extends "base.html" %} + +{% block title %} +Verify forum account +{% endblock %} + +{% block content %} + <div class="box box_grey"> + <h2>{{ self.title() }}</h2> + + <p> + Create an account by linking it to your forum account and optionally + your github account. + </p> + + {% if current_user.is_authenticated %} + <p> + Please log out to continue. + </p> + <p> + <a href="{{ url_for('user.logout', next=url_for('user_claim_page')) }}" class="button">Logout</a> + </p> + {% else %} + <p> + <b>Don't have a forum account?</b> + Unfortunately, you need a forum account to register. + This is because you also need to create forum topics for any packages + you may upload. + </p> + + <a href="https://forum.minetest.net/ucp.php?mode=register"> + Create a Forum Account + </a> + {% endif %} + </div> + + {% if not current_user.is_authenticated %} + <div class="box box_grey"> + <h2>Option 1 - Use GitHub field in forum profile</h2> + + <form method="post" action="{{ url_for('user_claim_page') }}"> + <input type="hidden" name="claim_type" value="github"> + <input type="hidden" name="csrf_token" value="{{ csrf_token() }}" /> + + <p> + Enter your forum username here: + </p> + + <input type="text" name="username" value="{{ username }}" required placeholder="Forum username"> + + <p> + You'll need to have the GitHub field in your forum profile + filled out. Log into the forum and + <a href="https://forum.minetest.net/ucp.php?i=173"> + do that here</a>. + </p> + + <input type="submit" value="Next: log in with GitHub"> + </form> + </div> + + <!--<div class="box box_grey"> + <h2>Option 2 - Paste verification token into signature</h2> + + <form method="post" action="{{ url_for('user_claim_page') }}"> + <input type="hidden" name="claim_type" value="forum"> + <input type="hidden" name="csrf_token" value="{{ csrf_token() }}" /> + + <p> + Enter your forum username here: + </p> + + <input type="text" name="username" value="{{ username }}" required placeholder="Forum username"> + + <p> + Go to + <a href="https://forum.minetest.net/ucp.php?i=profile&mode=signature"> + User Control Panel > Profile > Edit signature + </a> + </p> + <p> + Paste this into your signature: + </p> + + <input type="text" value="{{ key }}" readonly size=32> + + <p> + Click next so we can check it. + </p> + <p> + Don't worry, you can remove it after this is done. + </p> + + <input type="submit" value="Next"> + </form> + </div>--> + {% endif %} +{% endblock %} diff --git a/app/views/githublogin.py b/app/views/githublogin.py index 875f1b2..114bb2b 100644 --- a/app/views/githublogin.py +++ b/app/views/githublogin.py @@ -43,16 +43,8 @@ def github_authorized(oauth_token): # If not logged in, log in else: if userByGithub is None: - newUser = User(username) - newUser.github_username = username - db.session.add(newUser) - db.session.commit() - - if not loginUser(newUser): - raise Exception("Unable to login as user we just created") - - flash("Created an account", "success") - return redirect(url_for("user_profile_page", username=username)) + flash("Unable to find an account for that Github user", "error") + return redirect(url_for("user_claim_page")) elif loginUser(userByGithub): return redirect(next_url or url_for("home_page")) else: diff --git a/app/views/tasks.py b/app/views/tasks.py index 9b27f61..e6a5dc4 100644 --- a/app/views/tasks.py +++ b/app/views/tasks.py @@ -22,7 +22,6 @@ def new_getmeta_page(): }) @app.route("/tasks/<id>/") -@login_required def check_task(id): result = celery.AsyncResult(id) status = result.status @@ -51,7 +50,6 @@ def check_task(id): abort(422) if status == "SUCCESS": - flash("Task complete!", "success") return redirect(r) else: return render_template("tasks/view.html", info=info) diff --git a/app/views/users.py b/app/views/users.py index 995f09c..d3ed1aa 100644 --- a/app/views/users.py +++ b/app/views/users.py @@ -8,7 +8,8 @@ from flask_wtf import FlaskForm from flask_user.forms import RegisterForm from wtforms import * from wtforms.validators import * -from .utils import rank_required +from .utils import rank_required, randomString +from app.tasks.forumtasks import checkForumAccount class MyRegisterForm(RegisterForm): display_name = StringField("Display name") @@ -59,3 +60,42 @@ def user_profile_page(username): # Process GET or invalid POST return render_template("users/user_profile_page.html", user=user, form=form) + + +@app.route("/users/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")) + + 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": + token = request.form.get("token") + flash("Unimplemented", "error") + else: + flash("Unknown claim type", "error") + + return render_template("users/claim.html", username=username, key=randomString(32)) diff --git a/requirements.txt b/requirements.txt index 903f984..9e79b27 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,3 +8,5 @@ GitHub-Flask>=3.2.0 pyScss==1.3.4 celery==4.0.2 redis==2.10.6 +beautifulsoup4==4.6.0 +lxml==4.2.1 |