Created
November 30, 2018 00:11
-
-
Save alanhamlett/2942ff58b0263e11dcb8d376b149de43 to your computer and use it in GitHub Desktop.
Flask-Admin Example (replace dash with forward slash in file names)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
""" | |
wakatime.admin | |
~~~~~~~~~~~~~~ | |
Flask-Admin. | |
""" | |
from .views import admin |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
""" | |
wakatime.admin.utils | |
~~~~~~~~~~~~~~~~~~~~ | |
Flask-Admin utilities. | |
""" | |
from flask import abort, redirect, request, url_for | |
from flask_admin import AdminIndexView, expose | |
from flask_admin.babel import lazy_gettext | |
from flask_admin.base import MenuLink | |
from flask_admin.contrib import sqla | |
from functools import wraps | |
from wakatime import app, utils | |
class FilterUUIDEqual(sqla.filters.BaseSQLAFilter): | |
def apply(self, query, value, *args): | |
if not utils.is_uuid4(value): | |
return query | |
return query.filter(self.column == value) | |
def operation(self): | |
return lazy_gettext('equals') | |
def admin_required(f): | |
@wraps(f) | |
def decorated(*args, **kwargs): | |
if not app.current_user.is_authenticated: | |
return redirect(url_for('views.login', next=request.url)) | |
if not app.current_user.is_admin: | |
app.logger.debug('Not an admin') | |
abort(404) | |
return f(*args, **kwargs) | |
return decorated | |
def permission_required(permissions): | |
if not isinstance(permissions, (list, set, tuple)): | |
permissions = [permissions] | |
permissions = [x.upper() for x in permissions] | |
def decorator(method): | |
@wraps(method) | |
def f(*args, **kwargs): | |
if not app.current_user.is_authenticated: | |
return redirect(url_for('views.login', next=request.url)) | |
users_permissions = app.current_user.permissions | |
if 'ALL' not in users_permissions: | |
for permission in permissions: | |
if permission not in users_permissions: | |
app.logger.debug('Missing permission: {0}'.format(permission)) | |
abort(404) | |
return method(*args, **kwargs) | |
return f | |
return decorator | |
class AuthenticatedMenuLink(MenuLink): | |
def is_accessible(self): | |
return app.current_user.is_authenticated | |
class CustomAdminIndexView(AdminIndexView): | |
@expose('/') | |
@permission_required('admin') | |
def index(self): | |
if not app.current_user.is_authenticated: | |
return redirect(url_for('views.login', next=request.url)) | |
return super(CustomAdminIndexView, self).index() | |
@expose('/login/') | |
def login_view(self): | |
return redirect(url_for('views.login', next=request.url)) | |
@expose('/logout/') | |
def logout_view(self): | |
return redirect('/logout') | |
class CustomModelView(sqla.ModelView): | |
edit_template = 'admin/model/edit.html' | |
create_template = 'admin/model/create.html' | |
list_template = 'admin/model/custom_list.html' | |
page_size = 50 | |
_include = None | |
class_attributes = [ | |
'page_size', | |
'can_create', | |
'can_edit', | |
'can_delete', | |
'column_searchable_list', | |
'column_filters', | |
'column_exclude_list', | |
'column_default_sort', | |
] | |
def __init__(self, *args, **kwargs): | |
if 'exclude' in kwargs: | |
self.form_excluded_columns = kwargs['exclude'] | |
del kwargs['exclude'] | |
if 'include' in kwargs: | |
self._include = kwargs['include'] | |
del kwargs['include'] | |
for item in self.class_attributes: | |
if item in kwargs: | |
setattr(self, item, kwargs[item]) | |
del kwargs[item] | |
super(CustomModelView, self).__init__(*args, **kwargs) | |
def get_list_columns(self): | |
if self._include: | |
return self.get_column_names( | |
only_columns=self.scaffold_list_columns() + self._include, | |
excluded_columns=self.column_exclude_list, | |
) | |
return super(CustomModelView, self).get_list_columns() | |
def is_accessible(self): | |
return app.current_user.is_authenticated and app.current_user.is_admin | |
def inaccessible_callback(self, name, **kwargs): | |
return abort(404) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
""" | |
wakatime.admin.views | |
~~~~~~~~~~~~~~~~~~~~ | |
Flask-Admin views. | |
""" | |
from flask_admin import Admin, BaseView, expose | |
from wakatime import app | |
from wakatime.admin.utils import (AuthenticatedMenuLink, CustomAdminIndexView, | |
CustomModelView, FilterUUIDEqual, | |
admin_required) | |
from wakatime.models import db, User | |
admin = Admin(app, index_view=CustomAdminIndexView(), template_mode='bootstrap3', base_template='admin/custom_base.html') | |
admin.add_link(AuthenticatedMenuLink(name='Logout', endpoint='admin.logout_view')) | |
class UsersView(BaseView): | |
@expose('/') | |
@admin_required | |
def index(self): | |
return self.render('admin/index.html') | |
admin.add_view(UsersView(name='Search', endpoint='users', category='Users')) | |
admin.add_view(CustomModelView(User, db.session, category='Users', | |
can_create=False, can_delete=False, | |
column_default_sort=('created_at', True), | |
exclude=['password', 'auth_clients', 'leaderboards', 'created_at', 'modified_at'], | |
column_exclude_list=['api_key', 'password', 'session_id', 'modified_at'], | |
column_filters=['email', 'username', FilterUUIDEqual(User.id, 'user_id')], | |
column_searchable_list=['email', 'username', 'timezone'], | |
)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment