diff --git a/app/tasks/__init__.py b/app/tasks/__init__.py
index c431fae7..9ee293ea 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 00000000..e4ddc594
--- /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 00000000..3932b943
--- /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 c19f1f3a..c676aca7 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) }}
+
+ GitHub
New here?
-
- Please use Github login instead!
-
+ Create an account using your forum account.
- {% if user_manager.enable_register and not user_manager.require_invitation %}
- {%trans%}Create an account{%endtrans%}
- {% endif %}
-
-
-
-
diff --git a/app/templates/users/claim.html b/app/templates/users/claim.html
new file mode 100644
index 00000000..f4333d9a
--- /dev/null
+++ b/app/templates/users/claim.html
@@ -0,0 +1,98 @@
+{% extends "base.html" %}
+
+{% block title %}
+Verify forum account
+{% endblock %}
+
+{% block content %}
+
+
{{ self.title() }}
+
+
+ Create an account by linking it to your forum account and optionally
+ your github account.
+
+
+ {% if current_user.is_authenticated %}
+
+ Please log out to continue.
+
+
+ Logout
+
+ {% else %}
+
+ Don't have a forum account?
+ Unfortunately, you need a forum account to register.
+ This is because you also need to create forum topics for any packages
+ you may upload.
+
+
+
+ Create a Forum Account
+
+ {% endif %}
+
+
+ {% if not current_user.is_authenticated %}
+
+
Option 1 - Use GitHub field in forum profile
+
+
+
+
+
+ {% endif %}
+{% endblock %}
diff --git a/app/views/githublogin.py b/app/views/githublogin.py
index 875f1b27..114bb2b5 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 9b27f61a..e6a5dc4e 100644
--- a/app/views/tasks.py
+++ b/app/views/tasks.py
@@ -22,7 +22,6 @@ def new_getmeta_page():
})
@app.route("/tasks//")
-@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 995f09c1..d3ed1aa6 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 903f984f..9e79b270 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