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 import *
|
||||||
from flask_user import *
|
from flask_user import *
|
||||||
|
import flask_menu as menu
|
||||||
|
from flask.ext import markdown
|
||||||
|
from flask_github import GitHub
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
app.config.from_pyfile('../config.cfg')
|
app.config.from_pyfile('../config.cfg')
|
||||||
|
|
||||||
|
menu.Menu(app=app)
|
||||||
|
markdown.Markdown(app, extensions=['fenced_code'])
|
||||||
|
github = GitHub(app)
|
||||||
|
|
||||||
import models, views
|
import models, views
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
from flask import Flask, url_for
|
from flask import Flask, url_for
|
||||||
from flask.ext.sqlalchemy import SQLAlchemy
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
from app import app
|
from app import app
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from sqlalchemy.orm import validates
|
from sqlalchemy.orm import validates
|
||||||
@ -22,6 +22,10 @@ class User(db.Model, UserMixin):
|
|||||||
password = db.Column(db.String(255), nullable=False, server_default='')
|
password = db.Column(db.String(255), nullable=False, server_default='')
|
||||||
reset_password_token = db.Column(db.String(100), 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
|
# User email information
|
||||||
email = db.Column(db.String(255), nullable=True, unique=True)
|
email = db.Column(db.String(255), nullable=True, unique=True)
|
||||||
confirmed_at = db.Column(db.DateTime())
|
confirmed_at = db.Column(db.DateTime())
|
||||||
@ -38,6 +42,7 @@ class User(db.Model, UserMixin):
|
|||||||
|
|
||||||
self.username = username
|
self.username = username
|
||||||
self.confirmed_at = datetime.datetime.now() - datetime.timedelta(days=6000)
|
self.confirmed_at = datetime.datetime.now() - datetime.timedelta(days=6000)
|
||||||
|
self.display_name = username
|
||||||
|
|
||||||
def isClaimed(self):
|
def isClaimed(self):
|
||||||
return self.password is not None and self.password != ""
|
return self.password is not None and self.password != ""
|
||||||
|
@ -68,9 +68,16 @@ Sign in
|
|||||||
<h2>New here?</h2>
|
<h2>New here?</h2>
|
||||||
|
|
||||||
{% if user_manager.enable_register and not user_manager.require_invitation %}
|
{% 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 %}
|
{% endif %}
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
|
|
||||||
|
<aside class="box box_grey">
|
||||||
|
<h2>OAUTH</h2>
|
||||||
|
|
||||||
|
<a href="{{ url_for('github_signin_page') }}">GitHub</a>
|
||||||
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -3,72 +3,20 @@ from flask import *
|
|||||||
from flask_user import *
|
from flask_user import *
|
||||||
from flask_login import login_user, logout_user
|
from flask_login import login_user, logout_user
|
||||||
from app.models import *
|
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 sqlalchemy import func
|
||||||
from werkzeug.contrib.cache import SimpleCache
|
from werkzeug.contrib.cache import SimpleCache
|
||||||
cache = SimpleCache()
|
cache = SimpleCache()
|
||||||
|
|
||||||
menu.Menu(app=app)
|
|
||||||
markdown.Markdown(app, extensions=['fenced_code'])
|
|
||||||
|
|
||||||
# TODO: remove on production!
|
# TODO: remove on production!
|
||||||
@app.route('/static/<path:path>')
|
@app.route('/static/<path:path>')
|
||||||
def send_static(path):
|
def send_static(path):
|
||||||
return send_from_directory('static', path)
|
return send_from_directory('static', path)
|
||||||
|
|
||||||
|
import users, githublogin
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
@menu.register_menu(app, '.', 'Home')
|
@menu.register_menu(app, '.', 'Home')
|
||||||
def home_page():
|
def home_page():
|
||||||
return render_template('index.html')
|
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=""
|
WTF_CSRF_SECRET_KEY=""
|
||||||
|
|
||||||
SQLALCHEMY_DATABASE_URI = "sqlite:///../db.sqlite"
|
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-User>=0.6.19
|
||||||
Flask-Menu>=0.7.0
|
Flask-Menu>=0.7.0
|
||||||
Flask-Markdown>=0.3
|
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")
|
os.remove("app/data.sqlite")
|
||||||
|
|
||||||
if not os.path.isfile("app/data.sqlite"):
|
if not os.path.isfile("app/data.sqlite"):
|
||||||
from app import models
|
from app.models import *
|
||||||
|
|
||||||
print("Creating database tables...")
|
print("Creating database tables...")
|
||||||
models.db.create_all()
|
db.create_all()
|
||||||
|
|
||||||
print("Filling database...")
|
print("Filling database...")
|
||||||
models.db.session.commit()
|
|
||||||
|
ruben = User("rubenwardy")
|
||||||
|
ruben.github_username = "rubenwardy"
|
||||||
|
db.session.add(ruben)
|
||||||
|
db.session.commit()
|
||||||
else:
|
else:
|
||||||
print("Database already exists")
|
print("Database already exists")
|
||||||
|
Loading…
Reference in New Issue
Block a user