mirror of
https://github.com/minetest/contentdb.git
synced 2024-12-22 22:12:24 +01:00
Add Github login
This commit is contained in:
parent
7f4faf21fa
commit
7d20c49ebb
@ -1,7 +1,14 @@
|
||||
from flask import *
|
||||
from flask_user import *
|
||||
import flask_menu as menu
|
||||
from flask.ext import markdown
|
||||
from flask_github import GitHub
|
||||
|
||||
app = Flask(__name__)
|
||||
app.config.from_pyfile('../config.cfg')
|
||||
|
||||
menu.Menu(app=app)
|
||||
markdown.Markdown(app, extensions=['fenced_code'])
|
||||
github = GitHub(app)
|
||||
|
||||
import models, views
|
||||
|
@ -1,5 +1,5 @@
|
||||
from flask import Flask, url_for
|
||||
from flask.ext.sqlalchemy import SQLAlchemy
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
from app import app
|
||||
from datetime import datetime
|
||||
from sqlalchemy.orm import validates
|
||||
@ -22,6 +22,10 @@ class User(db.Model, UserMixin):
|
||||
password = db.Column(db.String(255), nullable=False, server_default='')
|
||||
reset_password_token = db.Column(db.String(100), nullable=False, server_default='')
|
||||
|
||||
# Account linking
|
||||
github_username = db.Column(db.String(50), nullable=True, unique=True)
|
||||
forums_username = db.Column(db.String(50), nullable=True, unique=True)
|
||||
|
||||
# User email information
|
||||
email = db.Column(db.String(255), nullable=True, unique=True)
|
||||
confirmed_at = db.Column(db.DateTime())
|
||||
@ -38,6 +42,7 @@ class User(db.Model, UserMixin):
|
||||
|
||||
self.username = username
|
||||
self.confirmed_at = datetime.datetime.now() - datetime.timedelta(days=6000)
|
||||
self.display_name = username
|
||||
|
||||
def isClaimed(self):
|
||||
return self.password is not None and self.password != ""
|
||||
|
@ -68,9 +68,16 @@ Sign in
|
||||
<h2>New here?</h2>
|
||||
|
||||
{% if user_manager.enable_register and not user_manager.require_invitation %}
|
||||
<a href="">{%trans%}Create an account{%endtrans%}</a>
|
||||
<a href="{{ url_for('github_signin_page') }}">{%trans%}Create an account{%endtrans%}</a>
|
||||
{% endif %}
|
||||
</aside>
|
||||
|
||||
|
||||
<aside class="box box_grey">
|
||||
<h2>OAUTH</h2>
|
||||
|
||||
<a href="{{ url_for('github_signin_page') }}">GitHub</a>
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
@ -3,72 +3,20 @@ from flask import *
|
||||
from flask_user import *
|
||||
from flask_login import login_user, logout_user
|
||||
from app.models import *
|
||||
from flask.ext import menu, markdown
|
||||
import flask_menu as menu
|
||||
from flask.ext import markdown
|
||||
from sqlalchemy import func
|
||||
from werkzeug.contrib.cache import SimpleCache
|
||||
cache = SimpleCache()
|
||||
|
||||
menu.Menu(app=app)
|
||||
markdown.Markdown(app, extensions=['fenced_code'])
|
||||
|
||||
# TODO: remove on production!
|
||||
@app.route('/static/<path:path>')
|
||||
def send_static(path):
|
||||
return send_from_directory('static', path)
|
||||
|
||||
import users, githublogin
|
||||
|
||||
@app.route('/')
|
||||
@menu.register_menu(app, '.', 'Home')
|
||||
def home_page():
|
||||
return render_template('index.html')
|
||||
|
||||
# Define the User registration form
|
||||
# It augments the Flask-User RegisterForm with additional fields
|
||||
from flask_user.forms import RegisterForm
|
||||
from flask_wtf import FlaskForm
|
||||
from wtforms import StringField, SubmitField, validators
|
||||
class MyRegisterForm(RegisterForm):
|
||||
first_name = StringField('First name', validators=[
|
||||
validators.DataRequired('First name is required')])
|
||||
last_name = StringField('Last name', validators=[
|
||||
validators.DataRequired('Last name is required')])
|
||||
|
||||
# Define the User profile form
|
||||
class UserProfileForm(FlaskForm):
|
||||
first_name = StringField('First name', validators=[
|
||||
validators.DataRequired('First name is required')])
|
||||
last_name = StringField('Last name', validators=[
|
||||
validators.DataRequired('Last name is required')])
|
||||
submit = SubmitField('Save')
|
||||
|
||||
@app.route('/user/', methods=['GET', 'POST'])
|
||||
@app.route('/user/<username>/', methods=['GET'])
|
||||
def user_profile_page(username=None):
|
||||
user = None
|
||||
form = None
|
||||
if username is None:
|
||||
if not current_user.is_authenticated:
|
||||
return current_app.login_manager.unauthorized()
|
||||
user = current_user
|
||||
else:
|
||||
user = User.query.filter_by(username=username).first()
|
||||
if not user:
|
||||
abort(404)
|
||||
|
||||
if user == current_user:
|
||||
# Initialize form
|
||||
form = UserProfileForm(request.form, current_user)
|
||||
|
||||
# Process valid POST
|
||||
if request.method=='POST' and form.validate():
|
||||
# Copy form fields to user_profile fields
|
||||
form.populate_obj(current_user)
|
||||
|
||||
# Save user_profile
|
||||
db.session.commit()
|
||||
|
||||
# Redirect to home page
|
||||
return redirect(url_for('home_page'))
|
||||
|
||||
# Process GET or invalid POST
|
||||
return render_template('users/user_profile_page.html',
|
||||
user=user, form=form)
|
||||
|
100
app/views/githublogin.py
Normal file
100
app/views/githublogin.py
Normal file
@ -0,0 +1,100 @@
|
||||
from flask import *
|
||||
from flask_user import *
|
||||
from flask_login import login_user, logout_user
|
||||
import flask_menu as menu
|
||||
from flask_github import GitHub
|
||||
from app import app, github
|
||||
from app.models import *
|
||||
|
||||
|
||||
@app.route('/user/github/start/')
|
||||
def github_signin_page():
|
||||
return github.authorize("public_repo,repo")
|
||||
|
||||
|
||||
def _do_login_user(user, remember_me=False):
|
||||
def _call_or_get(v):
|
||||
if callable(v):
|
||||
return v()
|
||||
else:
|
||||
return v
|
||||
|
||||
# User must have been authenticated
|
||||
if not user:
|
||||
return False
|
||||
|
||||
user.active = True
|
||||
db.session.commit()
|
||||
|
||||
# Check if user account has been disabled
|
||||
if not _call_or_get(user.is_active):
|
||||
flash('Your account has not been enabled.', 'error')
|
||||
return False
|
||||
|
||||
# Check if user has a confirmed email address
|
||||
user_manager = current_app.user_manager
|
||||
if user_manager.enable_email and user_manager.enable_confirm_email \
|
||||
and not current_app.user_manager.enable_login_without_confirm_email \
|
||||
and not user.has_confirmed_email():
|
||||
url = url_for('user.resend_confirm_email')
|
||||
flash("Your email address has not yet been confirmed", 'error')
|
||||
return False
|
||||
|
||||
# Use Flask-Login to sign in user
|
||||
login_user(user, remember=remember_me)
|
||||
signals.user_logged_in.send(current_app._get_current_object(), user=user)
|
||||
|
||||
flash('You have signed in successfully.', 'success')
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
||||
def _login_user(user):
|
||||
user_mixin = None
|
||||
if user_manager.enable_username:
|
||||
user_mixin = user_manager.find_user_by_username(user.username)
|
||||
|
||||
return _do_login_user(user_mixin, False)
|
||||
|
||||
|
||||
|
||||
@app.route('/user/github/callback/')
|
||||
@github.authorized_handler
|
||||
def github_authorized(oauth_token):
|
||||
next_url = request.args.get('next')
|
||||
if oauth_token is None:
|
||||
flash("Authorization failed [err=gh-oauth-login-failed]", "danger")
|
||||
return redirect(url_for("user.login"))
|
||||
|
||||
import requests
|
||||
|
||||
# Get Github username
|
||||
url = "https://api.github.com/user"
|
||||
r = requests.get(url, headers={"Authorization": "token " + oauth_token})
|
||||
username = r.json()["login"]
|
||||
|
||||
# Get user by github username
|
||||
userByGithub = User.query.filter_by(github_username=username).first()
|
||||
|
||||
# If logged in, connect
|
||||
if current_user and current_user.is_authenticated:
|
||||
if userByGithub is None:
|
||||
current_user.github_username = username
|
||||
db.session.add(auth)
|
||||
db.session.commit()
|
||||
return redirect(url_for("gitAccount", id=auth.id))
|
||||
else:
|
||||
flash("Github account is already associated with another user", "danger")
|
||||
return redirect(url_for("home_page"))
|
||||
|
||||
# If not logged in, log in
|
||||
else:
|
||||
if userByGithub is None:
|
||||
flash("Authorization failed [err=gh-no-such-account]", "danger")
|
||||
return redirect(url_for("user.login"))
|
||||
elif _login_user(userByGithub):
|
||||
return redirect(next_url or url_for("home_page"))
|
||||
else:
|
||||
flash("Authorization failed [err=gh-login-failed]", "danger")
|
||||
return redirect(url_for("user.login"))
|
60
app/views/users.py
Normal file
60
app/views/users.py
Normal file
@ -0,0 +1,60 @@
|
||||
from flask import *
|
||||
from flask_user import *
|
||||
from flask_login import login_user, logout_user
|
||||
from flask.ext import menu
|
||||
from app import app
|
||||
from app.models import *
|
||||
|
||||
|
||||
|
||||
# Define the User registration form
|
||||
# It augments the Flask-User RegisterForm with additional fields
|
||||
from flask_user.forms import RegisterForm
|
||||
from flask_wtf import FlaskForm
|
||||
from wtforms import StringField, SubmitField, validators
|
||||
class MyRegisterForm(RegisterForm):
|
||||
first_name = StringField('First name', validators=[
|
||||
validators.DataRequired('First name is required')])
|
||||
last_name = StringField('Last name', validators=[
|
||||
validators.DataRequired('Last name is required')])
|
||||
|
||||
# Define the User profile form
|
||||
class UserProfileForm(FlaskForm):
|
||||
first_name = StringField('First name', validators=[
|
||||
validators.DataRequired('First name is required')])
|
||||
last_name = StringField('Last name', validators=[
|
||||
validators.DataRequired('Last name is required')])
|
||||
submit = SubmitField('Save')
|
||||
|
||||
@app.route('/user/', methods=['GET', 'POST'])
|
||||
@app.route('/user/<username>/', methods=['GET'])
|
||||
def user_profile_page(username=None):
|
||||
user = None
|
||||
form = None
|
||||
if username is None:
|
||||
if not current_user.is_authenticated:
|
||||
return current_app.login_manager.unauthorized()
|
||||
user = current_user
|
||||
else:
|
||||
user = User.query.filter_by(username=username).first()
|
||||
if not user:
|
||||
abort(404)
|
||||
|
||||
if user == current_user:
|
||||
# Initialize form
|
||||
form = UserProfileForm(request.form, current_user)
|
||||
|
||||
# Process valid POST
|
||||
if request.method=='POST' and form.validate():
|
||||
# Copy form fields to user_profile fields
|
||||
form.populate_obj(current_user)
|
||||
|
||||
# Save user_profile
|
||||
db.session.commit()
|
||||
|
||||
# Redirect to home page
|
||||
return redirect(url_for('home_page'))
|
||||
|
||||
# Process GET or invalid POST
|
||||
return render_template('users/user_profile_page.html',
|
||||
user=user, form=form)
|
@ -4,3 +4,6 @@ SECRET_KEY=""
|
||||
WTF_CSRF_SECRET_KEY=""
|
||||
|
||||
SQLALCHEMY_DATABASE_URI = "sqlite:///../db.sqlite"
|
||||
|
||||
GITHUB_CLIENT_ID = ""
|
||||
GITHUB_CLIENT_SECRET = ""
|
||||
|
@ -3,3 +3,4 @@ Flask-SQLAlchemy>=2.3
|
||||
Flask-User>=0.6.19
|
||||
Flask-Menu>=0.7.0
|
||||
Flask-Markdown>=0.3
|
||||
GitHub-Flask>=3.2.0
|
||||
|
11
setup.py
11
setup.py
@ -6,12 +6,15 @@ if delete_db and os.path.isfile("app/data.sqlite"):
|
||||
os.remove("app/data.sqlite")
|
||||
|
||||
if not os.path.isfile("app/data.sqlite"):
|
||||
from app import models
|
||||
from app.models import *
|
||||
|
||||
print("Creating database tables...")
|
||||
models.db.create_all()
|
||||
|
||||
db.create_all()
|
||||
print("Filling database...")
|
||||
models.db.session.commit()
|
||||
|
||||
ruben = User("rubenwardy")
|
||||
ruben.github_username = "rubenwardy"
|
||||
db.session.add(ruben)
|
||||
db.session.commit()
|
||||
else:
|
||||
print("Database already exists")
|
||||
|
Loading…
Reference in New Issue
Block a user