Updated roles, db migrate, @require_role v1

This commit is contained in:
Xevion
2019-07-03 13:46:12 -05:00
parent 4bbc17ec52
commit 0c8437edd8
4 changed files with 54 additions and 7 deletions

View File

@@ -11,6 +11,7 @@ class User(UserMixin, db.Model):
password_hash = db.Column(db.String(64)) password_hash = db.Column(db.String(64))
posts = db.relationship('Post', backref='author', lazy='dynamic') posts = db.relationship('Post', backref='author', lazy='dynamic')
search_history = db.relationship('Search', backref='user', lazy='dynamic') search_history = db.relationship('Search', backref='user', lazy='dynamic')
uroles = db.Column(db.String(80), default='')
def set_password(self, password): def set_password(self, password):
self.password_hash = generate_password_hash(password) self.password_hash = generate_password_hash(password)
@@ -19,6 +20,33 @@ class User(UserMixin, db.Model):
if self.password_hash is None: if self.password_hash is None:
raise "{} has no password_hash set!".format(self.__repr__()) raise "{} has no password_hash set!".format(self.__repr__())
return check_password_hash(self.password_hash, password) return check_password_hash(self.password_hash, password)
def get_roles(self):
return self.uroles.split(' ')
def add_roles(self, roles):
user_roles = self.uroles.split(' ')
if type(roles) == str:
user_roles.append(roles)
elif type(roles) == list:
user_roles.extend(roles)
user_roles = ' '.join(user_roles)
self.uroles = user_roles
# Input: ['Insane', ['Fortunate', 'Blessed']]
# Meaning: Must have 'Insane' role, as well as 'Fortunate' or 'Blessed' roles.
def has_roles(self, roles):
user_roles = self.uroles.split(' ')
for reqrole in roles:
# If we have this role
if type(reqrole) == str:
if reqrole not in user_roles:
return False
# If we have any of these roles
elif type(reqrole) == list:
if not any([subreqrole in user_roles for subreqrole in reqrole]):
return False
return True
def __repr__(self): def __repr__(self):
return '<User {}>'.format(self.username) return '<User {}>'.format(self.username)

View File

@@ -1,8 +1,8 @@
from app import app, db from app import app, db, login
from app.models import User, Search from app.models import User, Search
from app.forms import LoginForm, RegistrationForm from app.forms import LoginForm, RegistrationForm
from werkzeug.urls import url_parse from werkzeug.urls import url_parse
from flask import render_template, redirect, url_for, flash, request, jsonify from flask import render_template, redirect, url_for, flash, request, jsonify, abort
from flask_login import current_user, login_user, logout_user, login_required from flask_login import current_user, login_user, logout_user, login_required
import requests import requests
import xmltodict import xmltodict
@@ -16,16 +16,29 @@ fake = faker.Faker()
def strgen(length): return ''.join(random.choices(list(string.ascii_letters), k=length)) def strgen(length): return ''.join(random.choices(list(string.ascii_letters), k=length))
def require_role(func, roles=[]):
def auth(*args, **kwargs):
if current_user.is_authenticated:
if current_user.has_roles(roles):
return func(*args, **kwargs)
return abort(401)
return auth
@app.route('/api') @app.route('/api')
@login_required
@require_role
def api(): def api():
return 'fuckoff' return 'fuckoff'
@app.errorhandler(401)
def unauthorized(e):
return redirect(url_for('login'))
@app.route('/dashboard') @app.route('/dashboard')
def dashboard(): def dashboard():
return '' return ''
@app.route('/userinfo') @app.route('/userinfo')
@login_required
def user_info(): def user_info():
prepare = { prepare = {
'id' : current_user.get_id(), 'id' : current_user.get_id(),
@@ -35,7 +48,8 @@ def user_info():
'is_active' : current_user.is_active, 'is_active' : current_user.is_active,
'is_anonymous' : current_user.is_anonymous, 'is_anonymous' : current_user.is_anonymous,
'is_authenticated' : current_user.is_authenticated, 'is_authenticated' : current_user.is_authenticated,
'metadata' : current_user.metadata.info 'metadata' : current_user.metadata.info,
'uroles' : current_user.get_roles()
} }
return jsonify(prepare) return jsonify(prepare)

View File

@@ -20,7 +20,7 @@
<th><abbr title="Search ID">ID</abbr></th> <th><abbr title="Search ID">ID</abbr></th>
<th>Exact URL</th> <th>Exact URL</th>
<th>Query Arguments</th> <th>Query Arguments</th>
<th><abbr title="in UTC time">Timestamp</abbr></th> <th>Timestamp</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@@ -29,7 +29,7 @@
<td>{{ post.id }}</td> <td>{{ post.id }}</td>
<td>{{ post.exact_url }}</td> <td>{{ post.exact_url }}</td>
<td>{{ post.query_args }}</td> <td>{{ post.query_args }}</td>
<td>{{ post.timestamp }} </td> <td>{{ post.timestamp }} UTC</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>

View File

@@ -13,4 +13,9 @@ class Config(object):
TEMPLATES_AUTO_RELOAD=True TEMPLATES_AUTO_RELOAD=True
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or \ SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or \
'sqlite:///' + os.path.join(basedir, 'app.db') 'sqlite:///' + os.path.join(basedir, 'app.db')
SQLALCHEMY_TRACK_MODIFICATIONS = False SQLALCHEMY_TRACK_MODIFICATIONS = False
# Flask-User settings
USER_APP_NAME = "Flask-User QuickStart App" # Shown in and email templates and page footers
USER_ENABLE_EMAIL = False # Disable email authentication
USER_ENABLE_USERNAME = True # Enable username authentication
USER_REQUIRE_RETYPE_PASSWORD = True