diff --git a/docs/usage/index.rst b/docs/usage/index.rst index 16b719a..f7a8ccc 100644 --- a/docs/usage/index.rst +++ b/docs/usage/index.rst @@ -7,3 +7,4 @@ Usage start commands web + privileges diff --git a/docs/usage/privileges.rst b/docs/usage/privileges.rst new file mode 100644 index 0000000..3adcc37 --- /dev/null +++ b/docs/usage/privileges.rst @@ -0,0 +1,3 @@ +Privileges and Roles +==================== + diff --git a/migrations/versions/13a18cc60ee5_privileges_for_role.py b/migrations/versions/13a18cc60ee5_privileges_for_role.py new file mode 100644 index 0000000..e8966c2 --- /dev/null +++ b/migrations/versions/13a18cc60ee5_privileges_for_role.py @@ -0,0 +1,28 @@ +"""Privileges for role + +Revision ID: 13a18cc60ee5 +Revises: 891cf9712a20 +Create Date: 2018-07-21 09:54:25.502179 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '13a18cc60ee5' +down_revision = '891cf9712a20' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('Role', sa.Column('privileges', sa.Text(), nullable=True)) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('Role', 'privileges') + # ### end Alembic commands ### diff --git a/repocribro/commands/assign_role.py b/repocribro/commands/assign_role.py index b9da273..b01f02a 100644 --- a/repocribro/commands/assign_role.py +++ b/repocribro/commands/assign_role.py @@ -17,7 +17,8 @@ def _assign_role(login, role_name): role = db.session.query(Role).filter_by(name=role_name).first() if role is None: print('Role {} not in DB... adding'.format(role_name)) - role = Role(role_name, '') + print('WARNING - created role has all privileges by default!') + role = Role(role_name, '*', '') db.session.add(role) user.user_account.roles.append(role) db.session.commit() diff --git a/repocribro/controllers/admin.py b/repocribro/controllers/admin.py index c069b41..7ba9849 100644 --- a/repocribro/controllers/admin.py +++ b/repocribro/controllers/admin.py @@ -1,15 +1,15 @@ import flask import sqlalchemy -from ..models import User, Role, Repository -from ..security import permissions +from ..models import User, Role, Repository, Anonymous +from ..security import permissions, reload_anonymous_role #: Admin controller blueprint admin = flask.Blueprint('admin', __name__, url_prefix='/admin') @admin.route('') -@permissions.admin_role.require(404) +@permissions.roles.admin.require(404) def index(): """Administration zone dashboard (GET handler)""" ext_master = flask.current_app.container.get('ext_master') @@ -26,7 +26,7 @@ def index(): @admin.route('/account/') -@permissions.admin_role.require(404) +@permissions.roles.admin.require(404) def account_detail(login): """Account administration (GET handler)""" db = flask.current_app.container.get('db') @@ -38,7 +38,7 @@ def account_detail(login): @admin.route('/account//ban', methods=['POST']) -@permissions.admin_role.require(404) +@permissions.roles.admin.require(404) def account_ban(login): """Ban (make inactive) account (POST handler)""" db = flask.current_app.container.get('db') @@ -66,7 +66,7 @@ def account_ban(login): @admin.route('/account//delete', methods=['POST']) -@permissions.admin_role.require(404) +@permissions.roles.admin.require(404) def account_delete(login): """Delete account (POST handler)""" db = flask.current_app.container.get('db') @@ -84,7 +84,7 @@ def account_delete(login): @admin.route('/repository//') -@permissions.admin_role.require(404) +@permissions.roles.admin.require(404) def repo_detail(login, reponame): """Repository administration (GET handler)""" db = flask.current_app.container.get('db') @@ -101,7 +101,7 @@ def repo_detail(login, reponame): @admin.route('/repository///visibility', methods=['POST']) -@permissions.admin_role.require(404) +@permissions.roles.admin.require(404) def repo_visibility(login, reponame): """Change repository visibility (POST handler)""" db = flask.current_app.container.get('db') @@ -134,7 +134,7 @@ def repo_visibility(login, reponame): @admin.route('/repository///delete', methods=['POST']) -@permissions.admin_role.require(404) +@permissions.roles.admin.require(404) def repo_delete(login, reponame): """Delete repository (POST handler)""" db = flask.current_app.container.get('db') @@ -152,7 +152,7 @@ def repo_delete(login, reponame): @admin.route('/role/') -@permissions.admin_role.require(404) +@permissions.roles.admin.require(404) def role_detail(name): """Role administration (GET handler)""" db = flask.current_app.container.get('db') @@ -164,7 +164,7 @@ def role_detail(name): @admin.route('/role//edit', methods=['POST']) -@permissions.admin_role.require(404) +@permissions.roles.admin.require(404) def role_edit(name): """Edit role (POST handler)""" db = flask.current_app.container.get('db') @@ -173,14 +173,24 @@ def role_edit(name): if role is None: flask.abort(404) name = flask.request.form.get('name', '') + priv = flask.request.form.get('privileges', '') desc = flask.request.form.get('description', None) if name == '': flask.flash('Couldn\'t make that role...', 'warning') return flask.redirect(flask.url_for('admin.index', tab='roles')) + + role.name = name + role.privileges = priv.lower() + role.description = desc + if not role.valid_privileges(): + flask.flash('Unsaved - incorrect characters in privileges ' + 'for role {}'.format(name), 'warning') + return flask.redirect(flask.url_for('admin.role_detail', + name=role.name)) try: - role.name = name - role.description = desc db.session.commit() + if name == Anonymous.rolename: + reload_anonymous_role(flask.current_app, db) except sqlalchemy.exc.IntegrityError as e: flask.flash('Couldn\'t make that role... {}'.format(str(e)), 'warning') @@ -191,7 +201,7 @@ def role_edit(name): @admin.route('/role//delete', methods=['POST']) -@permissions.admin_role.require(404) +@permissions.roles.admin.require(404) def role_delete(name): """Delete role (POST handler)""" db = flask.current_app.container.get('db') @@ -207,30 +217,39 @@ def role_delete(name): @admin.route('/roles/create', methods=['POST']) -@permissions.admin_role.require(404) +@permissions.roles.admin.require(404) def role_create(): """Create new role (POST handler)""" db = flask.current_app.container.get('db') name = flask.request.form.get('name', '') + priv = flask.request.form.get('privileges', '') desc = flask.request.form.get('description', None) if name == '': flask.flash('Couldn\'t make that role...', 'warning') return flask.redirect(flask.url_for('admin.index', tab='roles')) + role = Role(name, priv, desc) + if not role.valid_privileges(): + flask.flash('Unsaved - incorrect characters in privileges ' + 'for role {}'.format(name), 'warning') + return flask.redirect(flask.url_for('admin.role_detail', + name=role.name)) try: - role = Role(name, desc) db.session.add(role) db.session.commit() + if name == Anonymous.rolename: + reload_anonymous_role(flask.current_app, db) except sqlalchemy.exc.IntegrityError as e: flask.flash('Couldn\'t make that role... {}'.format(str(e)), 'warning') db.session.rollback() return flask.redirect(flask.url_for('admin.index', tab='roles')) - return flask.redirect(flask.url_for('admin.role_detail', name=role.name)) + return flask.redirect(flask.url_for('admin.role_detail', + name=role.name)) @admin.route('/role//add', methods=['POST']) -@permissions.admin_role.require(404) +@permissions.roles.admin.require(404) def role_assignment_add(name): """Assign role to user (POST handler)""" db = flask.current_app.container.get('db') @@ -253,7 +272,7 @@ def role_assignment_add(name): @admin.route('/role//remove', methods=['POST']) -@permissions.admin_role.require(404) +@permissions.roles.admin.require(404) def role_assignment_remove(name): """Remove assignment of role to user (POST handler)""" db = flask.current_app.container.get('db') diff --git a/repocribro/controllers/auth.py b/repocribro/controllers/auth.py index 5983f92..edaaf51 100644 --- a/repocribro/controllers/auth.py +++ b/repocribro/controllers/auth.py @@ -2,7 +2,9 @@ import flask_sqlalchemy from ..models import User, UserAccount -from ..security import login as security_login, logout as security_logout +from ..security import login as security_login, \ + logout as security_logout, \ + get_default_user_role #: Auth controller blueprint auth = flask.Blueprint('auth', __name__, url_prefix='/auth') @@ -33,6 +35,9 @@ def github_callback_get_account(db, gh_api): is_new = False if gh_user is None: user_account = UserAccount() + default_role = get_default_user_role(flask.current_app, db) + if default_role is not None: + user_account.roles.append(default_role) db.session.add(user_account) gh_user = User.create_from_dict(user_data, user_account) db.session.add(gh_user) diff --git a/repocribro/controllers/core.py b/repocribro/controllers/core.py index 4e8cd0d..1d046a3 100644 --- a/repocribro/controllers/core.py +++ b/repocribro/controllers/core.py @@ -2,6 +2,7 @@ import flask_login from ..models import User, Organization, Repository +from ..security import permissions #: Core controller blueprint core = flask.Blueprint('core', __name__, url_prefix='') diff --git a/repocribro/ext_core.py b/repocribro/ext_core.py index f535e43..011d133 100644 --- a/repocribro/ext_core.py +++ b/repocribro/ext_core.py @@ -4,7 +4,7 @@ from .extending import Extension from .extending.helpers import ViewTab, Badge -from .models import Push, Release, Repository +from .models import Push, Release, Repository, Role, Anonymous, UserAccount from .github import GitHubAPI @@ -164,6 +164,20 @@ def provide_filters(): from .filters import all_filters return all_filters + @staticmethod + def provide_roles(): + return { + 'admin': Role('admin', '*', 'Service administrators'), + 'user': Role(UserAccount.default_rolename, 'search*', + 'Regular users'), + 'anonymous': Role(Anonymous.rolename, 'search*:login', + 'Not-logged users') + } + + @staticmethod + def provide_actions(): + return ['login', 'search'] + @staticmethod def get_gh_webhook_processors(): """Get all GitHub webhooks processory""" @@ -191,7 +205,9 @@ def setup_config(self): def init_business(self): """Init business layer (other extensions, what is needed)""" - from .security import init_login_manager + from .security import init_login_manager, reload_anonymous_role + + reload_anonymous_role(self.app, self.db) login_manager, principals = init_login_manager(self.db) login_manager.init_app(self.app) principals.init_app(self.app) diff --git a/repocribro/extending/extension.py b/repocribro/extending/extension.py index 233f63b..f4fc22f 100644 --- a/repocribro/extending/extension.py +++ b/repocribro/extending/extension.py @@ -108,6 +108,24 @@ def provide_filters(): """ return {} + @staticmethod + def provide_roles(): + """Extension can define roles for user accounts + + :return: Dictionary with name + Role entity + :rtype: dict of str: ``repocribro.models.Role`` + """ + return {} + + @staticmethod + def provide_actions(): + """Extension can define actions for privileges + + :return: List of action names + :rtype: list of str + """ + return [] + def init_models(self): """Hook operation for initiating the models and registering them within db @@ -126,6 +144,16 @@ def init_filters(self): """ self.register_filters_from_dict(self.provide_filters()) + def init_security(self): + """Hook operation to setup privileges (roles and actions)""" + from ..security import create_default_role + permissions = self.app.container.get('permissions') + for role_name, role in self.provide_roles().items(): + permissions.register_role(role_name) + create_default_role(self.app, self.db, role) + for action_name in self.provide_actions(): + permissions.register_action(action_name) + def introduce(self): """Hook operation for getting short introduction of extension (mostly for debug/log purpose) diff --git a/repocribro/models.py b/repocribro/models.py index 3d89f7f..d822931 100644 --- a/repocribro/models.py +++ b/repocribro/models.py @@ -2,6 +2,8 @@ import sqlalchemy import flask_login import datetime +import fnmatch +import re from .database import db @@ -50,6 +52,8 @@ def fulltext_query(cls, query_str, db_query): class RoleMixin: """Mixin for models representing roles""" + priv_regex = re.compile('[a-z_\?\*]+') + def __eq__(self, other): """Equality of roles is based on names @@ -79,52 +83,66 @@ def __hash__(self): """ return hash(self.name) + def permits(self, privilege): + privileges = self.privileges.split(':') + if privilege in privileges: + return True + for priv in privileges: + if fnmatch.fnmatch(privilege, priv): + return True + return False + + def valid_privileges(self): + privileges = self.privileges.split(':') + for priv in privileges: + if not self.priv_regex.search(priv): + return False + return True -class Anonymous(flask_login.AnonymousUserMixin): - """Anonymous (not logged) user representation""" +class UserMixin(flask_login.UserMixin): @property def is_active(self): """Check whether is user active - :return: False, anonymous is not active + :return: If user is active (can login) :rtype: bool """ - return False + return self.active def has_role(self, role): """Check whether has the role :param role: Role to be checked - :type role: ``repocribro.models.RoleMixin`` - :return: False, anonymous has no roles + :type role: str + :return: If user has a role :rtype: bool """ - return False + return role in (role.name for role in self.roles) @property def rolenames(self): """Get names of all roles of that user - :return: Empty list, anonymous has no roles + :return: List of names of roles of user :rtype: list of str """ - return [] + return [role.name for role in self.roles] def owns_repo(self, repo): """Check if user owns the repository :param repo: Repository which shoudl be tested :type repo: ``repocribro.models.Repository`` - :return: False, anonymous can not own repository + :return: If user owns repo :rtype: bool """ - return False + return repo.owner.github_id == self.github_user.github_id def sees_repo(self, repo, has_secret=False): """Check if user is allowed to see the repo - Anonymous can see only public repos + Must be admin or owner to see not public repo :param repo: Repository which user want to see :type repo: ``repocribro.models.Repository`` @@ -134,52 +152,66 @@ def sees_repo(self, repo, has_secret=False): :rtype: bool """ visible = repo.is_public or (has_secret and repo.is_hidden) - return visible + return visible or self.has_role('admin') or self.owns_repo(repo) + def privileges(self, all_privileges=frozenset()): + privileges = set() + for priv in all_privileges: + for role in self.roles: + if role.permits(priv): + privileges.add(priv) + break + return privileges + + +class Anonymous(flask_login.AnonymousUserMixin, UserMixin): + """Anonymous (not logged) user representation""" + + rolename = 'anonymous' + roles = [] -class UserMixin(flask_login.UserMixin): @property def is_active(self): """Check whether is user active - :return: If user is active (can login) + :return: False, anonymous is not active :rtype: bool """ - return self.active + return False def has_role(self, role): """Check whether has the role :param role: Role to be checked - :type role: str - :return: If user has a role + :type role: ``repocribro.models.RoleMixin`` + :return: False, anonymous has no roles :rtype: bool """ - return role in (role.name for role in self.roles) + return role == self.rolename @property def rolenames(self): """Get names of all roles of that user - :return: List of names of roles of user + :return: Empty list, anonymous has no roles :rtype: list of str """ - return [role.name for role in self.roles] + return [self.rolename] def owns_repo(self, repo): """Check if user owns the repository :param repo: Repository which shoudl be tested :type repo: ``repocribro.models.Repository`` - :return: If user owns repo + :return: False, anonymous can not own repository :rtype: bool """ - return repo.owner.github_id == self.github_user.github_id + return False def sees_repo(self, repo, has_secret=False): """Check if user is allowed to see the repo - Must be admin or owner to see not public repo + Anonymous can see only public repos :param repo: Repository which user want to see :type repo: ``repocribro.models.Repository`` @@ -189,7 +221,7 @@ def sees_repo(self, repo, has_secret=False): :rtype: bool """ visible = repo.is_public or (has_secret and repo.is_hidden) - return visible or self.has_role('admin') or self.owns_repo(repo) + return visible #: Many-to-many relationship between user accounts and roles @@ -208,6 +240,8 @@ class UserAccount(db.Model, UserMixin, SearchableMixin): """UserAccount in the repocribro app""" __tablename__ = 'UserAccount' + default_rolename = 'user' + #: Unique identifier of the user account id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True) #: Timestamp where account was created @@ -257,13 +291,16 @@ class Role(db.Model, RoleMixin): name = sqlalchemy.Column(sqlalchemy.String(80), unique=True) #: Description (purpose, notes, ...) of the role description = sqlalchemy.Column(sqlalchemy.UnicodeText) + #: Serialized list of privileges + privileges = sqlalchemy.Column(sqlalchemy.Text) #: User accounts assigned to the role user_accounts = sqlalchemy.orm.relationship( 'UserAccount', back_populates='roles', secondary=roles_users ) - def __init__(self, name, description): + def __init__(self, name, privileges, description): self.name = name + self.privileges = privileges self.description = description def __repr__(self): diff --git a/repocribro/repocribro.py b/repocribro/repocribro.py index e65dc82..66b31a5 100644 --- a/repocribro/repocribro.py +++ b/repocribro/repocribro.py @@ -80,6 +80,10 @@ def __init__(self): super().__init__(PROG_NAME) self.container = DI_Container() + def ext_call(self, what_to_call): + ext_master = self.container.get('ext_master') + ext_master.call(what_to_call) + def create_app(cfg_files=['DEFAULT']): """Factory for making the web Flask application @@ -112,8 +116,12 @@ def create_app(cfg_files=['DEFAULT']): ext_names = ext_master.call('introduce', 'unknown') print('Loaded extensions: {}'.format(', '.join(ext_names))) + from .security import permissions + app.container.set_singleton('permissions', permissions) + ext_master.call('init_first') ext_master.call('init_models') + ext_master.call('init_security') ext_master.call('init_business') ext_master.call('init_filters') ext_master.call('init_blueprints') diff --git a/repocribro/security.py b/repocribro/security.py index 972f036..d670c04 100644 --- a/repocribro/security.py +++ b/repocribro/security.py @@ -2,7 +2,7 @@ import flask_login import flask_principal -from .models import UserAccount, Anonymous +from .models import UserAccount, Anonymous, Role def init_login_manager(db): @@ -28,16 +28,39 @@ def load_user(user_id): return login_manager, principals +class PermissionsContainer: + + def __init__(self, name): + self.x_name = name + self.x_dict = dict() + + def __getattr__(self, key): + return flask_principal.Permission(*self.x_dict[key]) + + class Permissions: - """ Class for prividing various permissions + """ Class for prividing various permissions""" - .. todo:: allow extensions provide permissions to others - """ + def __init__(self): + self.roles = PermissionsContainer('roles') + self.actions = PermissionsContainer('actions') + + def register_role(self, role_name): + self.roles.x_dict[role_name] = \ + (flask_principal.RoleNeed(role_name),) + + def register_action(self, priv_name): + self.actions.x_dict[priv_name] = \ + (flask_principal.ActionNeed(priv_name),) + + @property + def all_roles(self): + return set(self.roles.x_dict.keys()) + + @property + def all_actions(self): + return set(self.actions.x_dict.keys()) - #: Administrator role permission - admin_role = flask_principal.Permission( - flask_principal.RoleNeed('admin') - ) #: All permissions in the app permissions = Permissions() @@ -75,6 +98,44 @@ def clear_session(*args): flask.session.pop(key, None) +def reload_anonymous_role(app, db): + with app.app_context(): + anonymous_role = None + try: + anonymous_role = db.session.query(Role).filter_by( + name=Anonymous.rolename + ).first() + except: + pass + if anonymous_role is not None: + Anonymous.roles.append(anonymous_role) + + +def get_default_user_role(app, db): + user_role = None + with app.app_context(): + try: + user_role = db.session.query(Role).filter_by( + name=UserAccount.default_rolename + ).first() + except: + pass + return user_role + + +def create_default_role(app, db, role): + with app.app_context(): + try: + existing_role = db.session.query(Role).filter_by( + name=role.name + ).first() + if existing_role is None: + db.session.add(role) + db.session.commit() + except: + pass + + @flask_principal.identity_loaded.connect def on_identity_loaded(sender, identity): """Principal helper for loading the identity of logged user @@ -83,15 +144,20 @@ def on_identity_loaded(sender, identity): :param identity: Identity container :type identity: ``flask_principal.Identity`` """ - identity.user = flask_login.current_user + user = flask_login.current_user + identity.user = user - if hasattr(flask_login.current_user, 'id'): + if hasattr(user, 'id'): identity.provides.add( flask_principal.UserNeed(flask_login.current_user.id) ) - if hasattr(flask_login.current_user, 'roles'): - for role in flask_login.current_user.roles: + if hasattr(user, 'roles'): + for role in user.roles: identity.provides.add( flask_principal.RoleNeed(role.name) ) + for priviledge in user.privileges(permissions.all_actions): + identity.provides.add( + flask_principal.ActionNeed(priviledge) + ) diff --git a/repocribro/templates/admin/role.html b/repocribro/templates/admin/role.html index 7b655c6..f35f595 100644 --- a/repocribro/templates/admin/role.html +++ b/repocribro/templates/admin/role.html @@ -21,8 +21,13 @@

{{ role.name }}
- - + + + Privileges separated by semicolon : (see documentation) +
+
+ +
diff --git a/repocribro/templates/admin/tabs/roles.html b/repocribro/templates/admin/tabs/roles.html index 1705c30..bb92eee 100644 --- a/repocribro/templates/admin/tabs/roles.html +++ b/repocribro/templates/admin/tabs/roles.html @@ -15,8 +15,13 @@

Roles

- - + + + Privileges separated by semicolon : (see documentation) +
+
+ +
@@ -25,6 +30,7 @@

Roles

Name Description + Privileges Users @@ -34,6 +40,7 @@

Roles

{{ role.name }} {{ role.description }} + {{ role.privileges }} {{ role.accounts|length }} diff --git a/tests/conftest.py b/tests/conftest.py index 87ff6d8..e634caf 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -114,6 +114,8 @@ def teardown(): _db.app = app _db.create_all() + app.ext_call('init_security') # create default roles + request.addfinalizer(teardown) return _db @@ -161,11 +163,12 @@ def filled_db_session(empty_db_session): session = empty_db_session import datetime from repocribro.models import Role, UserAccount, User, \ - Organization, Repository, Commit, Release, Push + Organization, Repository, Commit, Release, Push, Anonymous # Setup admin role - admin_role = Role('admin', 'Administrators') + admin_role = Role('admin', '*', 'Administrators') session.add(admin_role) + Anonymous.permits = lambda x: True account_banned = UserAccount() account_banned.active = False diff --git a/tests/test_controller_admin.py b/tests/test_controller_admin.py index 62e4965..7641db5 100644 --- a/tests/test_controller_admin.py +++ b/tests/test_controller_admin.py @@ -118,17 +118,18 @@ def test_account_delete(filled_db_session, app_client): def test_role_create_edit_delete(filled_db_session, app_client): from repocribro.models import Role app_client.get('/test/login/admin') - existing_role = {'name': 'admin', 'description': ''} + existing_role = {'name': 'admin', 'privileges': '*', 'description': ''} ret = app_client.post('/admin/roles/create', data=existing_role) assert ret.status == '302 FOUND' - bad_role = {'name': '', 'description': ''} + bad_role = {'name': '', 'privileges': '', 'description': ''} ret = app_client.post('/admin/roles/create', data=bad_role) assert ret.status == '302 FOUND' role = filled_db_session.query(Role).filter_by(name='testadmin').first() assert role is None - new_role = {'name': 'testadmin', 'description': ''} + new_role = {'name': 'testadmin', 'privileges': 'login:s*', + 'description': ''} ret = app_client.post('/admin/roles/create', data=new_role) assert ret.status == '302 FOUND' role = filled_db_session.query(Role).filter_by(name='testadmin').first() @@ -147,7 +148,7 @@ def test_role_create_edit_delete(filled_db_session, app_client): role = filled_db_session.query(Role).filter_by(name='test_admin').first() assert role is None - edit_role = {'name': 'test_admin', 'description': ''} + edit_role = {'name': 'test_admin', 'privileges': '*', 'description': ''} ret = app_client.post('/admin/role/testadmin/edit', data=edit_role) assert ret.status == '302 FOUND' role = filled_db_session.query(Role).filter_by(name='test_admin').first() diff --git a/tests/test_controller_core.py b/tests/test_controller_core.py index d1e880b..2b3926f 100644 --- a/tests/test_controller_core.py +++ b/tests/test_controller_core.py @@ -6,7 +6,7 @@ def test_landing(app_client): app_client.get('/').data.decode('utf-8') -def test_search(app_client): +def test_search(filled_db_session, app_client): res = app_client.get('/search') assert res.status == '200 OK' assert '

Search

' in res.data.decode('utf-8') diff --git a/tests/test_models.py b/tests/test_models.py index f7ffb8b..999b4da 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -150,9 +150,9 @@ def test_repo_push(session, github_data_loader): def test_role_mixin(): - roleA = Role('admin', 'Admin of this great app') - roleB = Role('admin', 'Administrator of the app') - roleC = Role('admininistrator', 'Admin of this great app') + roleA = Role('admin', '*', 'Admin of this great app') + roleB = Role('admin', '*', 'Administrator of the app') + roleC = Role('admininistrator', '*', 'Admin of this great app') assert roleA == roleB assert roleB == roleA assert hash(roleA) == hash(roleB) @@ -171,7 +171,7 @@ def test_anonymous(): assert not anonym.has_role('user') assert not anonym.is_active assert not anonym.is_authenticated - assert anonym.rolenames == [] + assert anonym.rolenames == ['anonymous'] assert anonym.is_anonymous repo = Repository(777, None, 'some/repo', 'repo', 'C++', '', '', '', False, None, None, Repository.VISIBILITY_PRIVATE) @@ -205,7 +205,7 @@ def test_user_mixin(): repo.visibility_type = Repository.VISIBILITY_PUBLIC assert account.sees_repo(repo) - role = Role('admin', '') + role = Role('admin', '*', '') account.roles.append(role) assert account.has_role('admin') assert account.rolenames == ['admin'] diff --git a/tests/test_security.py b/tests/test_security.py index 36d7d6b..3f3e4f5 100644 --- a/tests/test_security.py +++ b/tests/test_security.py @@ -21,14 +21,14 @@ def test_login_logout(app, empty_db_session): def test_permission_admin(app, empty_db_session): with app.test_request_context('/'): - @permissions.admin_role.require(403) + @permissions.roles.admin.require(403) def test(): return 200 with pytest.raises(Forbidden): assert test() == 200 - role_admin = Role('admin', '') + role_admin = Role('admin', '*', '') account = UserAccount() account.id = 666 account.roles.append(role_admin)