]> git.lizzy.rs Git - cheatdb.git/commitdiff
Add user account claiming
authorrubenwardy <rw@rubenwardy.com>
Sun, 13 May 2018 22:31:42 +0000 (23:31 +0100)
committerrubenwardy <rw@rubenwardy.com>
Sun, 13 May 2018 22:33:05 +0000 (23:33 +0100)
app/tasks/__init__.py
app/tasks/forumtasks.py [new file with mode: 0644]
app/tasks/phpbbparser.py [new file with mode: 0644]
app/templates/flask_user/login.html
app/templates/users/claim.html [new file with mode: 0644]
app/views/githublogin.py
app/views/tasks.py
app/views/users.py
requirements.txt

index c431fae718a716e5ef62f3486811b4ec60dc6564..9ee293eae2de99618771854f6c34064fb153cdd2 100644 (file)
@@ -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 (file)
index 0000000..e4ddc59
--- /dev/null
@@ -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 (file)
index 0000000..3932b94
--- /dev/null
@@ -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
index c19f1f3acb7e06c0a76515cce7c0e9df631f4719..c676aca70517d36b3de26823e0e78f1626ef774d 100644 (file)
@@ -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 (file)
index 0000000..f4333d9
--- /dev/null
@@ -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 %}
index 875f1b271c9655a4869ca83c3f3cf3051a3f3746..114bb2b5f3ebd1e346919ec29ca51cd259f0e758 100644 (file)
@@ -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:
index 9b27f61a386158cd51db7df9affae12d5c6359c9..e6a5dc4e76a8e548831afe6c14d571aa63adaa8f 100644 (file)
@@ -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)
index 995f09c173d673b9d375edfa0d1196780f6c039d..d3ed1aa69676c0b6547a5a329490df34116abd42 100644 (file)
@@ -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))
index 903f984f1a55875ccb1c80bd22c71b976cb5815e..9e79b2709d3d19808fe7d8fb84e3ffc4a2bc2bd7 100644 (file)
@@ -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