commit
c4b147c3e5
31 changed files with 704 additions and 154 deletions
|
@ -2,6 +2,7 @@ from realms import login_manager
|
|||
from flask import request, flash, redirect
|
||||
from flask.ext.login import login_url
|
||||
|
||||
modules = set()
|
||||
|
||||
@login_manager.unauthorized_handler
|
||||
def unauthorized():
|
||||
|
|
3
realms/modules/auth/ldap/__init__.py
Normal file
3
realms/modules/auth/ldap/__init__.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
from ..models import Auth
|
||||
|
||||
Auth.register('ldap')
|
7
realms/modules/auth/ldap/forms.py
Normal file
7
realms/modules/auth/ldap/forms.py
Normal file
|
@ -0,0 +1,7 @@
|
|||
from flask_wtf import Form
|
||||
from wtforms import StringField, PasswordField, validators
|
||||
|
||||
|
||||
class LoginForm(Form):
|
||||
login = StringField('Username', [validators.DataRequired()])
|
||||
password = PasswordField('Password', [validators.DataRequired()])
|
53
realms/modules/auth/ldap/models.py
Normal file
53
realms/modules/auth/ldap/models.py
Normal file
|
@ -0,0 +1,53 @@
|
|||
from flask import render_template
|
||||
from flask.ext.login import login_user
|
||||
from realms import ldap
|
||||
from flask_ldap_login import LDAPLoginForm
|
||||
from ..models import BaseUser
|
||||
|
||||
|
||||
users = {}
|
||||
|
||||
|
||||
@ldap.save_user
|
||||
def save_user(username, userdata):
|
||||
user = User(userdata.get('username'), userdata.get('email'))
|
||||
users[user.id] = user
|
||||
return user
|
||||
|
||||
|
||||
class User(BaseUser):
|
||||
type = 'ldap'
|
||||
|
||||
def __init__(self, username, email='null@localhost.local', password=None):
|
||||
self.id = username
|
||||
self.username = username
|
||||
self.email = email
|
||||
self.password = password
|
||||
|
||||
@property
|
||||
def auth_token_id(self):
|
||||
return self.password
|
||||
|
||||
@staticmethod
|
||||
def load_user(*args, **kwargs):
|
||||
return User.get_by_id(args[0])
|
||||
|
||||
@staticmethod
|
||||
def get_by_id(user_id):
|
||||
return users.get(user_id)
|
||||
|
||||
@staticmethod
|
||||
def login_form():
|
||||
return render_template('auth/ldap/login.html', form=LDAPLoginForm())
|
||||
|
||||
@staticmethod
|
||||
def auth(user, password):
|
||||
password = User.hash_password(password)
|
||||
user.password = password
|
||||
users[user.id] = user
|
||||
if user:
|
||||
login_user(user, remember=True)
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
19
realms/modules/auth/ldap/views.py
Normal file
19
realms/modules/auth/ldap/views.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
from flask import current_app, request, redirect, Blueprint, flash, url_for
|
||||
from ..ldap.models import User
|
||||
from flask_ldap_login import LDAPLoginForm
|
||||
|
||||
blueprint = Blueprint('auth.ldap', __name__)
|
||||
|
||||
|
||||
@blueprint.route("/login/ldap", methods=['POST'])
|
||||
def login():
|
||||
form = LDAPLoginForm()
|
||||
|
||||
if not form.validate():
|
||||
flash('Form invalid', 'warning')
|
||||
return redirect(url_for('auth.login'))
|
||||
|
||||
if User.auth(form.user, request.form['password']):
|
||||
return redirect(request.args.get("next") or url_for(current_app.config['ROOT_ENDPOINT']))
|
||||
else:
|
||||
return redirect(url_for('auth.login'))
|
3
realms/modules/auth/local/__init__.py
Normal file
3
realms/modules/auth/local/__init__.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
from ..models import Auth
|
||||
|
||||
Auth.register('local')
|
|
@ -1,9 +1,10 @@
|
|||
import click
|
||||
from realms.lib.util import random_string
|
||||
from realms.modules.auth.models import User
|
||||
from realms.modules.auth.local.models import User
|
||||
from realms.lib.util import green, red, yellow
|
||||
from realms import flask_cli
|
||||
|
||||
|
||||
@flask_cli.group(short_help="Auth Module")
|
||||
def cli():
|
||||
pass
|
98
realms/modules/auth/local/models.py
Normal file
98
realms/modules/auth/local/models.py
Normal file
|
@ -0,0 +1,98 @@
|
|||
from flask import current_app, render_template
|
||||
from flask.ext.login import logout_user, login_user
|
||||
from realms import login_manager, db
|
||||
from realms.lib.model import Model
|
||||
from ..models import BaseUser
|
||||
from .forms import LoginForm
|
||||
from itsdangerous import URLSafeSerializer, BadSignature
|
||||
from hashlib import sha256
|
||||
|
||||
|
||||
@login_manager.token_loader
|
||||
def load_token(token):
|
||||
# Load unsafe because payload is needed for sig
|
||||
sig_okay, payload = URLSafeSerializer(current_app.config['SECRET_KEY']).loads_unsafe(token)
|
||||
|
||||
if not payload:
|
||||
return None
|
||||
|
||||
# User key *could* be stored in payload to avoid user lookup in db
|
||||
user = User.get_by_id(payload.get('id'))
|
||||
|
||||
if not user:
|
||||
return None
|
||||
|
||||
try:
|
||||
if BaseUser.signer(sha256(user.password).hexdigest()).loads(token):
|
||||
return user
|
||||
else:
|
||||
return None
|
||||
except BadSignature:
|
||||
return None
|
||||
|
||||
|
||||
class User(Model, BaseUser):
|
||||
__tablename__ = 'users'
|
||||
type = 'local'
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
username = db.Column(db.String(128), unique=True)
|
||||
email = db.Column(db.String(128), unique=True)
|
||||
password = db.Column(db.String(60))
|
||||
admin = False
|
||||
|
||||
hidden_fields = ['password']
|
||||
readonly_fields = ['email', 'password']
|
||||
|
||||
@property
|
||||
def auth_token_id(self):
|
||||
return self.password
|
||||
|
||||
@staticmethod
|
||||
def load_user(*args, **kwargs):
|
||||
return User.get_by_id(args[0])
|
||||
|
||||
@staticmethod
|
||||
def create(username, email, password):
|
||||
u = User()
|
||||
u.username = username
|
||||
u.email = email
|
||||
u.password = User.hash_password(password)
|
||||
u.save()
|
||||
|
||||
@staticmethod
|
||||
def get_by_username(username):
|
||||
return User.query().filter_by(username=username).first()
|
||||
|
||||
@staticmethod
|
||||
def get_by_email(email):
|
||||
return User.query().filter_by(email=email).first()
|
||||
|
||||
@staticmethod
|
||||
def signer(salt):
|
||||
return URLSafeSerializer(current_app.config['SECRET_KEY'] + salt)
|
||||
|
||||
@staticmethod
|
||||
def auth(email, password):
|
||||
user = User.get_by_email(email)
|
||||
|
||||
if not user:
|
||||
# User doesn't exist
|
||||
return False
|
||||
|
||||
if User.check_password(password, user.password):
|
||||
# Password is good, log in user
|
||||
login_user(user, remember=True)
|
||||
return user
|
||||
else:
|
||||
# Password check failed
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def logout(cls):
|
||||
logout_user()
|
||||
|
||||
@staticmethod
|
||||
def login_form():
|
||||
form = LoginForm()
|
||||
return render_template('auth/local/login.html', form=form)
|
||||
|
51
realms/modules/auth/local/views.py
Normal file
51
realms/modules/auth/local/views.py
Normal file
|
@ -0,0 +1,51 @@
|
|||
from flask import current_app, render_template, request, redirect, Blueprint, flash, url_for
|
||||
from realms.modules.auth.local.models import User
|
||||
from realms.modules.auth.local.forms import LoginForm, RegistrationForm
|
||||
|
||||
blueprint = Blueprint('auth.local', __name__)
|
||||
|
||||
|
||||
@blueprint.route("/login/local", methods=['POST'])
|
||||
def login():
|
||||
form = LoginForm()
|
||||
|
||||
if not form.validate():
|
||||
flash('Form invalid', 'warning')
|
||||
return redirect(url_for('auth.login'))
|
||||
|
||||
if User.auth(request.form['email'], request.form['password']):
|
||||
return redirect(request.args.get("next") or url_for(current_app.config['ROOT_ENDPOINT']))
|
||||
else:
|
||||
flash('Email or Password Incorrect', 'warning')
|
||||
return redirect(url_for('auth.login'))
|
||||
|
||||
|
||||
@blueprint.route("/register", methods=['GET', 'POST'])
|
||||
def register():
|
||||
|
||||
if not current_app.config['REGISTRATION_ENABLED']:
|
||||
flash("Registration is disabled")
|
||||
return redirect(url_for(current_app.config['ROOT_ENDPOINT']))
|
||||
|
||||
form = RegistrationForm()
|
||||
|
||||
if request.method == "POST":
|
||||
|
||||
if not form.validate():
|
||||
flash('Form invalid', 'warning')
|
||||
return redirect(url_for('auth.local.register'))
|
||||
|
||||
if User.get_by_username(request.form['username']):
|
||||
flash('Username is taken', 'warning')
|
||||
return redirect(url_for('auth.local.register'))
|
||||
|
||||
if User.get_by_email(request.form['email']):
|
||||
flash('Email is taken', 'warning')
|
||||
return redirect(url_for('auth.local.register'))
|
||||
|
||||
User.create(request.form['username'], request.form['email'], request.form['password'])
|
||||
User.auth(request.form['email'], request.form['password'])
|
||||
|
||||
return redirect(request.args.get("next") or url_for(current_app.config['ROOT_ENDPOINT']))
|
||||
|
||||
return render_template("auth/register.html", form=form)
|
|
@ -1,39 +1,43 @@
|
|||
from flask import current_app
|
||||
from flask.ext.login import UserMixin, logout_user, login_user, AnonymousUserMixin
|
||||
from realms import login_manager, db
|
||||
from realms.lib.model import Model
|
||||
from flask.ext.login import UserMixin, logout_user, AnonymousUserMixin
|
||||
from realms import login_manager
|
||||
from realms.lib.util import gravatar_url
|
||||
from itsdangerous import URLSafeSerializer, BadSignature
|
||||
from hashlib import sha256
|
||||
from . import modules
|
||||
import bcrypt
|
||||
import importlib
|
||||
|
||||
|
||||
@login_manager.user_loader
|
||||
def load_user(user_id):
|
||||
return User.get_by_id(user_id)
|
||||
def load_user(auth_id):
|
||||
return Auth.load_user(auth_id)
|
||||
|
||||
auth_users = {}
|
||||
|
||||
|
||||
@login_manager.token_loader
|
||||
def load_token(token):
|
||||
# Load unsafe because payload is needed for sig
|
||||
sig_okay, payload = URLSafeSerializer(current_app.config['SECRET_KEY']).loads_unsafe(token)
|
||||
class Auth(object):
|
||||
|
||||
if not payload:
|
||||
return None
|
||||
@staticmethod
|
||||
def register(module):
|
||||
modules.add(module)
|
||||
|
||||
# User key *could* be stored in payload to avoid user lookup in db
|
||||
user = User.get_by_id(payload.get('id'))
|
||||
@staticmethod
|
||||
def get_auth_user(auth_type):
|
||||
mod = importlib.import_module('realms.modules.auth.%s.models' % auth_type)
|
||||
return mod.User
|
||||
|
||||
if not user:
|
||||
return None
|
||||
@staticmethod
|
||||
def load_user(auth_id):
|
||||
auth_type, user_id = auth_id.split("/")
|
||||
return Auth.get_auth_user(auth_type).load_user(user_id)
|
||||
|
||||
try:
|
||||
if User.signer(sha256(user.password).hexdigest()).loads(token):
|
||||
return user
|
||||
else:
|
||||
return None
|
||||
except BadSignature:
|
||||
return None
|
||||
@staticmethod
|
||||
def login_forms():
|
||||
forms = []
|
||||
for t in modules:
|
||||
forms.append(Auth.get_auth_user(t).login_form())
|
||||
return "<hr />".join(forms)
|
||||
|
||||
|
||||
class AnonUser(AnonymousUserMixin):
|
||||
|
@ -42,61 +46,35 @@ class AnonUser(AnonymousUserMixin):
|
|||
admin = False
|
||||
|
||||
|
||||
class User(Model, UserMixin):
|
||||
__tablename__ = 'users'
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
username = db.Column(db.String(128), unique=True)
|
||||
email = db.Column(db.String(128), unique=True)
|
||||
password = db.Column(db.String(60))
|
||||
admin = False
|
||||
class BaseUser(UserMixin):
|
||||
id = None
|
||||
email = None
|
||||
username = None
|
||||
type = 'base'
|
||||
|
||||
hidden_fields = ['password']
|
||||
readonly_fields = ['email', 'password']
|
||||
def get_id(self):
|
||||
return unicode("%s/%s" % (self.type, self.id))
|
||||
|
||||
def get_auth_token(self):
|
||||
key = sha256(self.password).hexdigest()
|
||||
return User.signer(key).dumps(dict(id=self.id))
|
||||
key = sha256(self.auth_token_id).hexdigest()
|
||||
return BaseUser.signer(key).dumps(dict(id=self.id))
|
||||
|
||||
@property
|
||||
def auth_token_id(self):
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
def avatar(self):
|
||||
return gravatar_url(self.email)
|
||||
|
||||
@staticmethod
|
||||
def create(username, email, password):
|
||||
u = User()
|
||||
u.username = username
|
||||
u.email = email
|
||||
u.password = User.hash_password(password)
|
||||
u.save()
|
||||
|
||||
@staticmethod
|
||||
def get_by_username(username):
|
||||
return User.query().filter_by(username=username).first()
|
||||
|
||||
@staticmethod
|
||||
def get_by_email(email):
|
||||
return User.query().filter_by(email=email).first()
|
||||
def load_user(*args, **kwargs):
|
||||
raise NotImplementedError
|
||||
|
||||
@staticmethod
|
||||
def signer(salt):
|
||||
return URLSafeSerializer(current_app.config['SECRET_KEY'] + salt)
|
||||
|
||||
@staticmethod
|
||||
def auth(email, password):
|
||||
user = User.get_by_email(email)
|
||||
|
||||
if not user:
|
||||
# User doesn't exist
|
||||
return False
|
||||
|
||||
if User.check_password(password, user.password):
|
||||
# Password is good, log in user
|
||||
login_user(user, remember=True)
|
||||
return user
|
||||
else:
|
||||
# Password check failed
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def hash_password(password):
|
||||
return bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt(12))
|
||||
|
@ -109,4 +87,8 @@ class User(Model, UserMixin):
|
|||
def logout(cls):
|
||||
logout_user()
|
||||
|
||||
@staticmethod
|
||||
def login_form():
|
||||
pass
|
||||
|
||||
login_manager.anonymous_user = AnonUser
|
||||
|
|
3
realms/modules/auth/oauth/__init__.py
Normal file
3
realms/modules/auth/oauth/__init__.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
from ..models import Auth
|
||||
|
||||
Auth.register('oauth')
|
173
realms/modules/auth/oauth/models.py
Normal file
173
realms/modules/auth/oauth/models.py
Normal file
|
@ -0,0 +1,173 @@
|
|||
from flask import session
|
||||
from flask_login import login_user
|
||||
from flask_oauthlib.client import OAuth
|
||||
|
||||
from realms import config
|
||||
from ..models import BaseUser
|
||||
|
||||
oauth = OAuth()
|
||||
|
||||
users = {}
|
||||
|
||||
providers = {
|
||||
'twitter': {
|
||||
'oauth': dict(
|
||||
base_url='https://api.twitter.com/1.1/',
|
||||
request_token_url='https://api.twitter.com/oauth/request_token',
|
||||
access_token_url='https://api.twitter.com/oauth/access_token',
|
||||
authorize_url='https://api.twitter.com/oauth/authenticate',
|
||||
access_token_method='GET'),
|
||||
'button': '<a href="/login/oauth/twitter" class="btn btn-twitter"><i class="fa fa-twitter"></i></a>',
|
||||
'profile': None,
|
||||
'field_map': {
|
||||
'id': 'user_id',
|
||||
'username': 'screen_name'
|
||||
},
|
||||
'token_name': 'oauth_token'
|
||||
},
|
||||
'github': {
|
||||
'oauth': dict(
|
||||
request_token_params={'scope': 'user:email'},
|
||||
base_url='https://api.github.com/',
|
||||
request_token_url=None,
|
||||
access_token_method='POST',
|
||||
access_token_url='https://github.com/login/oauth/access_token',
|
||||
authorize_url='https://github.com/login/oauth/authorize'),
|
||||
'button': '<a href="/login/oauth/github" class="btn btn-github"><i class="fa fa-github"></i></a>',
|
||||
'profile': 'user',
|
||||
'field_map': {
|
||||
'id': 'id',
|
||||
'username': 'login',
|
||||
'email': 'email'
|
||||
},
|
||||
'token_name': 'access_token'
|
||||
},
|
||||
'facebook': {
|
||||
'oauth': dict(
|
||||
request_token_params={'scope': 'email'},
|
||||
base_url='https://graph.facebook.com',
|
||||
request_token_url=None,
|
||||
access_token_url='/oauth/access_token',
|
||||
access_token_method='GET',
|
||||
authorize_url='https://www.facebook.com/dialog/oauth'
|
||||
),
|
||||
'button': '<a href="/login/oauth/facebook" class="btn btn-facebook"><i class="fa fa-facebook"></i></a>',
|
||||
'profile': '/me',
|
||||
'field_map': {
|
||||
'id': 'id',
|
||||
'username': 'name',
|
||||
'email': 'email'
|
||||
},
|
||||
'token_name': 'access_token'
|
||||
},
|
||||
'google': {
|
||||
'oauth': dict(
|
||||
request_token_params={
|
||||
'scope': 'https://www.googleapis.com/auth/userinfo.email'
|
||||
},
|
||||
base_url='https://www.googleapis.com/oauth2/v1/',
|
||||
request_token_url=None,
|
||||
access_token_method='POST',
|
||||
access_token_url='https://accounts.google.com/o/oauth2/token',
|
||||
authorize_url='https://accounts.google.com/o/oauth2/auth',
|
||||
),
|
||||
'button': '<a href="/login/oauth/google" class="btn btn-google"><i class="fa fa-google"></i></a>',
|
||||
'profile': 'userinfo',
|
||||
'field_map': {
|
||||
'id': 'id',
|
||||
'username': 'name',
|
||||
'email': 'email'
|
||||
},
|
||||
'token_name': 'access_token'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class User(BaseUser):
|
||||
type = 'oauth'
|
||||
provider = None
|
||||
|
||||
def __init__(self, provider, user_id, username=None, token=None, email=None):
|
||||
self.provider = provider
|
||||
self.username = username
|
||||
self.email = email
|
||||
self.id = user_id
|
||||
self.token = token
|
||||
self.auth_id = "%s-%s" % (provider, username)
|
||||
|
||||
@property
|
||||
def auth_token_id(self):
|
||||
return self.token
|
||||
|
||||
@staticmethod
|
||||
def load_user(*args, **kwargs):
|
||||
return User.get_by_id(args[0])
|
||||
|
||||
@staticmethod
|
||||
def get_by_id(user_id):
|
||||
return users.get(user_id)
|
||||
|
||||
@staticmethod
|
||||
def auth(provider, data, oauth_token):
|
||||
field_map = providers.get(provider).get('field_map')
|
||||
if not field_map:
|
||||
raise NotImplementedError
|
||||
|
||||
def get_value(d, key):
|
||||
if isinstance(key, basestring):
|
||||
return d.get(key)
|
||||
# key should be list here
|
||||
val = d.get(key.pop(0))
|
||||
if len(key) == 0:
|
||||
# if empty we have our value
|
||||
return val
|
||||
# keep digging
|
||||
return get_value(val, key)
|
||||
|
||||
fields = {}
|
||||
for k, v in field_map.items():
|
||||
fields[k] = get_value(data, v)
|
||||
|
||||
user = User(provider, fields['id'], username=fields.get('username'), email=fields.get('email'),
|
||||
token=User.hash_password(oauth_token))
|
||||
users[user.auth_id] = user
|
||||
|
||||
if user:
|
||||
login_user(user, remember=True)
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def get_app(cls, provider):
|
||||
if oauth.remote_apps.get(provider):
|
||||
return oauth.remote_apps.get(provider)
|
||||
app = oauth.remote_app(
|
||||
provider,
|
||||
consumer_key=config.OAUTH.get(provider, {}).get('key'),
|
||||
consumer_secret=config.OAUTH.get(provider, {}).get(
|
||||
'secret'),
|
||||
**providers[provider]['oauth'])
|
||||
app.tokengetter(lambda: session.get(provider + "_token"))
|
||||
return app
|
||||
|
||||
@classmethod
|
||||
def get_provider_value(cls, provider, key):
|
||||
return providers.get(provider, {}).get(key)
|
||||
|
||||
@classmethod
|
||||
def get_token(cls, provider, resp):
|
||||
return resp.get(cls.get_provider_value(provider, 'token_name'))
|
||||
|
||||
def get_id(self):
|
||||
return unicode("%s/%s" % (self.type, self.auth_id))
|
||||
|
||||
@staticmethod
|
||||
def login_form():
|
||||
buttons = []
|
||||
for name, val in providers.items():
|
||||
if not config.OAUTH.get(name, {}).get('key') or not config.OAUTH.get(name, {}).get('secret'):
|
||||
continue
|
||||
buttons.append(val.get('button'))
|
||||
|
||||
return "<h3>Social Login</h3>" + " ".join(buttons)
|
39
realms/modules/auth/oauth/views.py
Normal file
39
realms/modules/auth/oauth/views.py
Normal file
|
@ -0,0 +1,39 @@
|
|||
from flask import Blueprint, url_for, request, flash, redirect, session, current_app
|
||||
from .models import User
|
||||
|
||||
blueprint = Blueprint('auth.oauth', __name__)
|
||||
|
||||
|
||||
def oauth_failed(next_url):
|
||||
flash('You denied the request to sign in.')
|
||||
return redirect(next_url)
|
||||
|
||||
|
||||
@blueprint.route("/login/oauth/<provider>")
|
||||
def login(provider):
|
||||
return User.get_app(provider).authorize(callback=url_for('auth.oauth.callback', provider=provider, _external=True))
|
||||
|
||||
|
||||
@blueprint.route('/login/oauth/<provider>/callback')
|
||||
def callback(provider):
|
||||
next_url = request.args.get('next') or url_for(current_app.config['ROOT_ENDPOINT'])
|
||||
try:
|
||||
remote_app = User.get_app(provider)
|
||||
resp = remote_app.authorized_response()
|
||||
if resp is None:
|
||||
flash('You denied the request to sign in.', 'error')
|
||||
flash('Reason: ' + request.args['error_reason'] +
|
||||
' ' + request.args['error_description'], 'error')
|
||||
return redirect(next_url)
|
||||
except Exception as e:
|
||||
flash('Access denied: %s' % e.message)
|
||||
return redirect(next_url)
|
||||
|
||||
oauth_token = resp.get(User.get_provider_value(provider, 'token_name'))
|
||||
session[provider + "_token"] = (oauth_token, '')
|
||||
profile = User.get_provider_value(provider, 'profile')
|
||||
data = remote_app.get(profile).data if profile else resp
|
||||
|
||||
User.auth(provider, data, oauth_token)
|
||||
|
||||
return redirect(next_url)
|
|
@ -1,72 +1,22 @@
|
|||
from flask import current_app, render_template, request, redirect, Blueprint, flash, url_for
|
||||
from realms.modules.auth.models import User
|
||||
from realms.modules.auth.forms import LoginForm, RegistrationForm
|
||||
from flask.ext.login import logout_user
|
||||
from realms.modules.auth.models import Auth
|
||||
|
||||
blueprint = Blueprint('auth', __name__)
|
||||
|
||||
|
||||
@blueprint.route("/logout")
|
||||
def logout_page():
|
||||
User.logout()
|
||||
flash("You are now logged out")
|
||||
return redirect(url_for(current_app.config['ROOT_ENDPOINT']))
|
||||
|
||||
|
||||
@blueprint.route("/login", methods=['GET', 'POST'])
|
||||
def login():
|
||||
form = LoginForm()
|
||||
|
||||
if request.method == "POST":
|
||||
if not form.validate():
|
||||
flash('Form invalid', 'warning')
|
||||
return redirect(url_for('auth.login'))
|
||||
|
||||
if User.auth(request.form['email'], request.form['password']):
|
||||
return redirect(request.args.get("next") or url_for(current_app.config['ROOT_ENDPOINT']))
|
||||
else:
|
||||
flash('Email or Password Incorrect', 'warning')
|
||||
return redirect(url_for('auth.login'))
|
||||
|
||||
return render_template("auth/login.html", form=form)
|
||||
return render_template("auth/login.html", forms=Auth.login_forms())
|
||||
|
||||
|
||||
@blueprint.route("/register", methods=['GET', 'POST'])
|
||||
def register():
|
||||
|
||||
if not current_app.config['REGISTRATION_ENABLED']:
|
||||
flash("Registration is disabled")
|
||||
return redirect(url_for(current_app.config['ROOT_ENDPOINT']))
|
||||
|
||||
form = RegistrationForm()
|
||||
|
||||
if request.method == "POST":
|
||||
|
||||
if not form.validate():
|
||||
flash('Form invalid', 'warning')
|
||||
return redirect(url_for('auth.register'))
|
||||
|
||||
if User.get_by_username(request.form['username']):
|
||||
flash('Username is taken', 'warning')
|
||||
return redirect(url_for('auth.register'))
|
||||
|
||||
if User.get_by_email(request.form['email']):
|
||||
flash('Email is taken', 'warning')
|
||||
return redirect(url_for('auth.register'))
|
||||
|
||||
User.create(request.form['username'], request.form['email'], request.form['password'])
|
||||
User.auth(request.form['email'], request.form['password'])
|
||||
|
||||
return redirect(request.args.get("next") or url_for(current_app.config['ROOT_ENDPOINT']))
|
||||
|
||||
return render_template("auth/register.html", form=form)
|
||||
@blueprint.route("/logout")
|
||||
def logout():
|
||||
logout_user()
|
||||
flash("You are now logged out")
|
||||
return redirect(url_for(current_app.config['ROOT_ENDPOINT']))
|
||||
|
||||
|
||||
@blueprint.route("/settings", methods=['GET', 'POST'])
|
||||
def settings():
|
||||
return render_template("auth/settings.html")
|
||||
|
||||
|
||||
@blueprint.route("/logout")
|
||||
def logout():
|
||||
User.logout()
|
||||
return redirect(url_for(current_app.config['ROOT_ENDPOINT']))
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from flask import abort, g, render_template, request, redirect, Blueprint, flash, url_for, current_app
|
||||
from flask import render_template, request, Blueprint
|
||||
from realms import search as search_engine
|
||||
|
||||
blueprint = Blueprint('search', __name__)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue