wargaming openid auth

This commit is contained in:
vanzhiganov 2017-08-27 04:09:23 +03:00
parent e49dd74a21
commit af8eb4fa7b
15 changed files with 247 additions and 1 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
.env/
*.pyc

View file

@ -7,6 +7,7 @@ script_location = alembic
# template used to generate migration files # template used to generate migration files
# file_template = %%(rev)s_%%(slug)s # file_template = %%(rev)s_%%(slug)s
file_template = %%(rev)s file_template = %%(rev)s
file_template = %%(year)d_%%(month).2d_%%(day).2d_%%(hour).2d_%%(minute).2d
# timezone to use when rendering the date # timezone to use when rendering the date
# within the migration file as well as the filename. # within the migration file as well as the filename.

View file

@ -24,6 +24,7 @@ def upgrade():
sa.Column('email', sa.String(length=256), nullable=False, unique=True), sa.Column('email', sa.String(length=256), nullable=False, unique=True),
sa.Column('password', sa.String(32), nullable=False), sa.Column('password', sa.String(32), nullable=False),
sa.Column('openid', sa.String(256), nullable=True, unique=True), sa.Column('openid', sa.String(256), nullable=True, unique=True),
sa.Column('name', sa.String(256), nullable=False, unique=True),
sa.PrimaryKeyConstraint('id') sa.PrimaryKeyConstraint('id')
) )
pass pass

View 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
View file

6
wotstats/database.py Normal file
View 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
View 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

View file

@ -7,10 +7,11 @@ class User(db.Model):
status = db.Column(db.Integer, default=0, nullable=False) status = db.Column(db.Integer, default=0, nullable=False)
email = db.Column(db.String(256), unique=True, nullable=False) email = db.Column(db.String(256), unique=True, nullable=False)
password = db.Column(db.String(32), 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) openid = db.Column(db.String(256), unique=True, nullable=True)
def __init__(self, email): def __init__(self, email):
self.password = email self.email = email
def __repr__(self): def __repr__(self):
return '<User id={} email={}>'.format(self.id, self.email) return '<User id={} email={}>'.format(self.id, self.email)

3
wotstats/openid.py Normal file
View file

@ -0,0 +1,3 @@
from flask.ext.openid import OpenID
oid = OpenID()

View file

@ -0,0 +1,9 @@
<html>
<head>
<title>{% block title %}{% endblock %}</title>
</head>
<body>
<h1>wotstats</h1>
{% block content %}{% endblock %}
</body>
</html>

View 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 %}

View 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 %}

View 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 %}

View 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
View 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))