wargaming openid auth
This commit is contained in:
parent
e49dd74a21
commit
af8eb4fa7b
15 changed files with 247 additions and 1 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
.env/
|
||||
*.pyc
|
|
@ -7,6 +7,7 @@ script_location = alembic
|
|||
# template used to generate migration files
|
||||
# file_template = %%(rev)s_%%(slug)s
|
||||
file_template = %%(rev)s
|
||||
file_template = %%(year)d_%%(month).2d_%%(day).2d_%%(hour).2d_%%(minute).2d
|
||||
|
||||
# timezone to use when rendering the date
|
||||
# within the migration file as well as the filename.
|
||||
|
|
|
@ -24,6 +24,7 @@ def upgrade():
|
|||
sa.Column('email', sa.String(length=256), nullable=False, unique=True),
|
||||
sa.Column('password', sa.String(32), nullable=False),
|
||||
sa.Column('openid', sa.String(256), nullable=True, unique=True),
|
||||
sa.Column('name', sa.String(256), nullable=False, unique=True),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
pass
|
24
alembic/versions/2017_08_27_03_02.py
Normal file
24
alembic/versions/2017_08_27_03_02.py
Normal file
|
@ -0,0 +1,24 @@
|
|||
"""empty message
|
||||
|
||||
Revision ID: b3222bf2cedb
|
||||
Revises: 5766fed0b2ef
|
||||
Create Date: 2017-08-27 03:02:09.126373
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'b3222bf2cedb'
|
||||
down_revision = 'f5e44761054e'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
pass
|
||||
|
||||
|
||||
def downgrade():
|
||||
pass
|
0
tmp/.ignore
Normal file
0
tmp/.ignore
Normal file
6
wotstats/database.py
Normal file
6
wotstats/database.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
from flask_migrate import Migrate
|
||||
|
||||
db = SQLAlchemy()
|
||||
migrate = Migrate()
|
34
wotstats/init.py
Normal file
34
wotstats/init.py
Normal file
|
@ -0,0 +1,34 @@
|
|||
|
||||
from flask import Flask, render_template, g, session
|
||||
from wotstats.database import db, migrate
|
||||
from wotstats.openid import oid
|
||||
from wotstats.views import pages_home
|
||||
|
||||
def init_app():
|
||||
app = Flask(__name__)
|
||||
app.debug = True
|
||||
app.config['SECRET_KEY'] = 'super-secret'
|
||||
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgres://wot:wot@192.168.1.47/wot'
|
||||
app.config['OPENID_FS_STORE_PATH'] = 'tmp'
|
||||
#
|
||||
app.config['WG_ID'] = '502910c1c785c3c7ca2e83c9e89bde02'
|
||||
app.config['WG_OPENID_URL'] = 'https://eu.wargaming.net/id/openid/'
|
||||
|
||||
# , safe_roots=[]
|
||||
oid.init_app(app)
|
||||
db.init_app(app)
|
||||
migrate.init_app(app, db)
|
||||
# jwt = JWT(app, authenticate, identity)
|
||||
|
||||
app.register_blueprint(pages_home)
|
||||
|
||||
@app.before_request
|
||||
def lookup_current_user():
|
||||
from wotstats.models import User
|
||||
|
||||
g.user = None
|
||||
if 'openid' in session:
|
||||
openid = session['openid']
|
||||
g.user = User.query.filter_by(openid=openid).first()
|
||||
|
||||
return app
|
|
@ -7,10 +7,11 @@ class User(db.Model):
|
|||
status = db.Column(db.Integer, default=0, nullable=False)
|
||||
email = db.Column(db.String(256), unique=True, nullable=False)
|
||||
password = db.Column(db.String(32), nullable=False)
|
||||
name = db.Column(db.String(256), unique=True, nullable=False)
|
||||
openid = db.Column(db.String(256), unique=True, nullable=True)
|
||||
|
||||
def __init__(self, email):
|
||||
self.password = email
|
||||
self.email = email
|
||||
|
||||
def __repr__(self):
|
||||
return '<User id={} email={}>'.format(self.id, self.email)
|
||||
|
|
3
wotstats/openid.py
Normal file
3
wotstats/openid.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
from flask.ext.openid import OpenID
|
||||
|
||||
oid = OpenID()
|
9
wotstats/templates/layouts/main.html
Normal file
9
wotstats/templates/layouts/main.html
Normal file
|
@ -0,0 +1,9 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>{% block title %}{% endblock %}</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>wotstats</h1>
|
||||
{% block content %}{% endblock %}
|
||||
</body>
|
||||
</html>
|
7
wotstats/templates/pages/auth_step1.html
Normal file
7
wotstats/templates/pages/auth_step1.html
Normal file
|
@ -0,0 +1,7 @@
|
|||
{% extends 'layouts/main.html' %}
|
||||
|
||||
{% block content %}
|
||||
<ul>
|
||||
<li><a href="{{ url_for('page_auth_step1') }}">auth</a></li>
|
||||
</ul>
|
||||
{% endblock %}
|
22
wotstats/templates/pages/create_profile.html
Normal file
22
wotstats/templates/pages/create_profile.html
Normal file
|
@ -0,0 +1,22 @@
|
|||
{% extends "layouts/main.html" %}
|
||||
{% block title %}Create Profile{% endblock %}
|
||||
{% block content %}
|
||||
<h2>Create Profile</h2>
|
||||
<p>
|
||||
Hey! This is the first time you signed in on this website. In
|
||||
order to proceed we need a couple of more information from you:
|
||||
<form action="" method=post>
|
||||
<dl>
|
||||
<dt>Name:
|
||||
<dd><input type=text name=name size=30 value="{{ request.values.name }}">
|
||||
<dt>E-Mail:
|
||||
<dd><input type=text name=email size=30 value="{{ request.values.email }}">
|
||||
</dl>
|
||||
<p>
|
||||
<input type=submit value="Create profile">
|
||||
<input type=hidden name=next value="{{ next }}">
|
||||
</form>
|
||||
<p>
|
||||
If you don't want to proceed, you can <a href="{{ url_for('pages_home.logout')
|
||||
}}">sign out</a> again.
|
||||
{% endblock %}
|
19
wotstats/templates/pages/index.html
Normal file
19
wotstats/templates/pages/index.html
Normal file
|
@ -0,0 +1,19 @@
|
|||
{% extends 'layouts/main.html' %}
|
||||
|
||||
{% block content %}
|
||||
{% if session['openid'] %}
|
||||
<ul>
|
||||
{% if 'openid' in session %}
|
||||
<li>{{ session['openid'] }}</li>
|
||||
{% else %}
|
||||
<li>{{ session['email'] }}</li>
|
||||
{% endif %}
|
||||
<li><a href="{{ url_for('pages_home.logout') }}">statistics</a></li>
|
||||
<li><a href="{{ url_for('pages_home.logout') }}">logout</a></li>
|
||||
</ul>
|
||||
{% else %}
|
||||
<ul>
|
||||
<li><a href="{{ url_for('pages_home.login') }}">login</a></li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
{% endblock %}
|
13
wotstats/templates/pages/login.html
Normal file
13
wotstats/templates/pages/login.html
Normal file
|
@ -0,0 +1,13 @@
|
|||
{% extends "layouts/main.html" %}
|
||||
{% block title %}Create Profile{% endblock %}
|
||||
{% block content %}
|
||||
<h2>Sign in</h2>
|
||||
<form action="" method=post>
|
||||
{% if error %}<p class=error><strong>Error:</strong> {{ error }}</p>{% endif %}
|
||||
<p>
|
||||
OpenID:
|
||||
<input type=text name=openid size=30>
|
||||
<input type=submit value="Sign in">
|
||||
<input type=hidden name=next value="{{ next }}">
|
||||
</form>
|
||||
{% endblock %}
|
104
wotstats/views/__init__.py
Normal file
104
wotstats/views/__init__.py
Normal file
|
@ -0,0 +1,104 @@
|
|||
import re
|
||||
from flask import (
|
||||
g, Blueprint, render_template, abort, current_app, redirect,
|
||||
redirect, request, url_for, session, flash
|
||||
)
|
||||
from jinja2 import TemplateNotFound
|
||||
from wotstats.openid import oid
|
||||
|
||||
from wotstats.database import db
|
||||
from wotstats.models import User
|
||||
|
||||
pages_home = Blueprint('pages_home', __name__, template_folder='templates')
|
||||
|
||||
# def show(page):
|
||||
# try:
|
||||
# return render_template('pages/%s.html' % page)
|
||||
# except TemplateNotFound:
|
||||
# abort(404)
|
||||
|
||||
def parse_wargaming_openid_url(url):
|
||||
"""
|
||||
>>> parse_wargaming_openid_url('https://ru.wargaming.net/id/69552613-CrazyPants1999/')
|
||||
('69552613', 'CrazyPants1999')
|
||||
|
||||
"""
|
||||
pattern = '^https?.*id\/([0-9]+)-(\w+)\/$'
|
||||
return re.findall(pattern, url)[0]
|
||||
|
||||
|
||||
@pages_home.route('/', defaults={'page': 'index'})
|
||||
@pages_home.route('/<page>')
|
||||
def index(page):
|
||||
z = session['openid']
|
||||
return render_template('pages/index.html')
|
||||
|
||||
|
||||
@pages_home.route('/auth.html')
|
||||
def auth_step1():
|
||||
return render_template('pages/auth_step1.html')
|
||||
|
||||
|
||||
@pages_home.route('/login', methods=['GET', 'POST'])
|
||||
@oid.loginhandler
|
||||
def login():
|
||||
if g.user is not None:
|
||||
return redirect(oid.get_next_url())
|
||||
if request.method == 'POST':
|
||||
openid = request.form.get('openid')
|
||||
if openid:
|
||||
return oid.try_login(
|
||||
openid,
|
||||
ask_for=['email', 'nickname'],
|
||||
ask_for_optional=['fullname'])
|
||||
return render_template(
|
||||
'pages/login.html',
|
||||
next=oid.get_next_url(),
|
||||
error=oid.fetch_error())
|
||||
|
||||
|
||||
@pages_home.route('/create-profile', methods=['GET', 'POST'])
|
||||
def create_profile():
|
||||
if g.user is not None or 'openid' not in session:
|
||||
return redirect(url_for('pages_home.index'))
|
||||
if request.method == 'POST':
|
||||
name = request.form['name']
|
||||
email = request.form['email']
|
||||
if not name:
|
||||
flash(u'Error: you have to provide a name')
|
||||
elif '@' not in email:
|
||||
flash(u'Error: you have to enter a valid email address')
|
||||
else:
|
||||
flash(u'Profile successfully created')
|
||||
u = User(email)
|
||||
u.name = name
|
||||
u.openid = session['openid']
|
||||
u.password = ''
|
||||
|
||||
db.session.add(u)
|
||||
db.session.commit()
|
||||
return redirect(oid.get_next_url())
|
||||
return render_template(
|
||||
'pages/create_profile.html',
|
||||
next=oid.get_next_url())
|
||||
|
||||
|
||||
@pages_home.route('/logout')
|
||||
def logout():
|
||||
session.pop('openid', None)
|
||||
flash(u'You were signed out')
|
||||
return redirect(oid.get_next_url())
|
||||
|
||||
@oid.after_login
|
||||
def create_or_login(resp):
|
||||
session['openid'] = resp.identity_url
|
||||
user = User.query.filter_by(openid=resp.identity_url).first()
|
||||
if user is not None:
|
||||
flash(u'Successfully signed in')
|
||||
g.user = user
|
||||
return redirect(oid.get_next_url())
|
||||
return redirect(url_for(
|
||||
'pages_home.create_profile',
|
||||
next=oid.get_next_url(),
|
||||
name=resp.fullname or resp.nickname,
|
||||
email=resp.email))
|
Reference in a new issue