celery = make_celery(app)
-from . import importtasks
+from . import importtasks, forumtasks
--- /dev/null
+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()
--- /dev/null
+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
{# 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>
--- /dev/null
+{% 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 %}
# 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:
})
@app.route("/tasks/<id>/")
-@login_required
def check_task(id):
result = celery.AsyncResult(id)
status = result.status
abort(422)
if status == "SUCCESS":
- flash("Task complete!", "success")
return redirect(r)
else:
return render_template("tasks/view.html", info=info)
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")
# 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))
pyScss==1.3.4
celery==4.0.2
redis==2.10.6
+beautifulsoup4==4.6.0
+lxml==4.2.1