From 528b33ec0ee7eba03fda3fb246b03cb88f3d7feb Mon Sep 17 00:00:00 2001 From: zhengxie Date: Fri, 20 May 2016 15:14:06 +0800 Subject: [PATCH] Add role permissions --- seahub/api2/authentication.py | 16 ++----- seahub/base/accounts.py | 42 ++++++++++++----- seahub/role_permissions/__init__.py | 0 seahub/role_permissions/admin.py | 3 ++ .../role_permissions/migrations/__init__.py | 0 seahub/role_permissions/models.py | 3 ++ seahub/role_permissions/settings.py | 45 +++++++++++++++++++ seahub/role_permissions/utils.py | 18 ++++++++ seahub/role_permissions/views.py | 3 ++ seahub/settings.py | 24 ++++++++++ .../templates/sysadmin/useradmin_table.html | 9 +++- seahub/utils/user_permissions.py | 26 +++++++++++ seahub/views/sysadmin.py | 12 +++-- tests/seahub/base/test_accounts.py | 16 +++++++ 14 files changed, 188 insertions(+), 29 deletions(-) create mode 100644 seahub/role_permissions/__init__.py create mode 100644 seahub/role_permissions/admin.py create mode 100644 seahub/role_permissions/migrations/__init__.py create mode 100644 seahub/role_permissions/models.py create mode 100644 seahub/role_permissions/settings.py create mode 100644 seahub/role_permissions/utils.py create mode 100644 seahub/role_permissions/views.py create mode 100644 seahub/utils/user_permissions.py diff --git a/seahub/api2/authentication.py b/seahub/api2/authentication.py index 80895c9c52..995b5fc380 100644 --- a/seahub/api2/authentication.py +++ b/seahub/api2/authentication.py @@ -6,10 +6,10 @@ from rest_framework.exceptions import APIException import seaserv from seahub.base.accounts import User -from seahub.constants import GUEST_USER from seahub.api2.models import Token, TokenV2 from seahub.api2.utils import get_client_ip from seahub.utils import within_time_range +from seahub.utils.user_permissions import populate_user_permissions try: from seahub.settings import MULTI_TENANCY except ImportError: @@ -65,16 +65,6 @@ class TokenAuthentication(BaseAuthentication): return self.authenticate_v1(request, key) - def _populate_user_permissions(self, user): - """Disable some operations if ``user`` is a guest. - """ - if user.role == GUEST_USER: - user.permissions.can_add_repo = lambda: False - user.permissions.can_add_group = lambda: False - user.permissions.can_view_org = lambda: False - user.permissions.can_use_global_address_book = lambda: False - user.permissions.can_generate_shared_link = lambda: False - def authenticate_v1(self, request, key): try: token = Token.objects.get(key=key) @@ -91,7 +81,7 @@ class TokenAuthentication(BaseAuthentication): if orgs: user.org = orgs[0] - self._populate_user_permissions(user) + populate_user_permissions(user) if user.is_active: return (user, token) @@ -116,7 +106,7 @@ class TokenAuthentication(BaseAuthentication): if orgs: user.org = orgs[0] - self._populate_user_permissions(user) + populate_user_permissions(user) if user.is_active: need_save = False diff --git a/seahub/base/accounts.py b/seahub/base/accounts.py index e720045850..c93d4ae5d4 100644 --- a/seahub/base/accounts.py +++ b/seahub/base/accounts.py @@ -6,14 +6,16 @@ from django.utils.translation import ugettext_lazy as _ from django.conf import settings from django.contrib.sites.models import RequestSite from django.contrib.sites.models import Site - -from seahub.auth import login -from registration import signals import seaserv from seaserv import ccnet_threaded_rpc, unset_repo_passwd, is_passwd_set, \ seafile_api +from constance import config +from registration import signals +from seahub.auth import login +from seahub.constants import DEFAULT_USER from seahub.profile.models import Profile, DetailedProfile +from seahub.role_permissions.utils import get_enabled_role_permissions_by_role from seahub.utils import is_valid_username, is_user_password_strong, \ clear_token, get_system_admins from seahub.utils.mail import send_html_email_with_dj_template, MAIL_PRIORITY @@ -27,8 +29,6 @@ try: except ImportError: MULTI_TENANCY = False -from constance import config - UNUSABLE_PASSWORD = '!' # This will never be a valid hash class UserManager(object): @@ -102,22 +102,44 @@ class UserPermissions(object): self.user = user def can_add_repo(self): - return True + return get_enabled_role_permissions_by_role(DEFAULT_USER)['can_add_repo'] def can_add_group(self): - return True + return get_enabled_role_permissions_by_role(DEFAULT_USER)['can_add_group'] def can_generate_shared_link(self): - return True + return get_enabled_role_permissions_by_role(DEFAULT_USER)['can_generate_shared_link'] def can_use_global_address_book(self): - return True + return get_enabled_role_permissions_by_role(DEFAULT_USER)['can_use_global_address_book'] def can_view_org(self): if MULTI_TENANCY: return True if self.user.org is not None else False - return False if CLOUD_MODE else True + if CLOUD_MODE: + return False + + return get_enabled_role_permissions_by_role(DEFAULT_USER)['can_view_org'] + + def can_drag_drop_folder_to_sync(self): + return get_enabled_role_permissions_by_role(DEFAULT_USER)['can_drag_drop_folder_to_sync'] + + def can_connect_with_android_clients(self): + return get_enabled_role_permissions_by_role(DEFAULT_USER)['can_connect_with_android_clients'] + + def can_connect_with_ios_clients(self): + return get_enabled_role_permissions_by_role(DEFAULT_USER)['can_connect_with_ios_clients'] + + def can_connect_with_desktop_clients(self): + return get_enabled_role_permissions_by_role(DEFAULT_USER)['can_connect_with_desktop_clients'] + + def can_invite_guest(self): + return get_enabled_role_permissions_by_role(DEFAULT_USER)['can_invite_guest'] + + def can_export_files_via_mobile_client(self): + return get_enabled_role_permissions_by_role(DEFAULT_USER)['can_export_files_via_mobile_client'] + class User(object): is_staff = False diff --git a/seahub/role_permissions/__init__.py b/seahub/role_permissions/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/seahub/role_permissions/admin.py b/seahub/role_permissions/admin.py new file mode 100644 index 0000000000..8c38f3f3da --- /dev/null +++ b/seahub/role_permissions/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/seahub/role_permissions/migrations/__init__.py b/seahub/role_permissions/migrations/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/seahub/role_permissions/models.py b/seahub/role_permissions/models.py new file mode 100644 index 0000000000..71a8362390 --- /dev/null +++ b/seahub/role_permissions/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/seahub/role_permissions/settings.py b/seahub/role_permissions/settings.py new file mode 100644 index 0000000000..220bdc9ced --- /dev/null +++ b/seahub/role_permissions/settings.py @@ -0,0 +1,45 @@ +import logging + +from django.conf import settings + +from seahub.constants import DEFAULT_USER + +# Get an instance of a logger +logger = logging.getLogger(__name__) + +DEFAULT_ENABLED_ROLE_PERMISSIONS = { + DEFAULT_USER: { + 'can_add_repo': True, + 'can_add_group': True, + 'can_view_org': True, + 'can_use_global_address_book': True, + 'can_generate_shared_link': True, + 'can_invite_guest': False, + # followings are not implemented yet + 'can_drag_drop_folder_to_sync': True, + 'can_connect_with_android_clients': True, + 'can_connect_with_ios_clients': True, + 'can_connect_with_desktop_clients': True, + 'can_export_files_via_mobile_client': True, + }, +} + +_default_role_perms = DEFAULT_ENABLED_ROLE_PERMISSIONS.copy() +_default_role_perms.update(settings.ENABLED_ROLE_PERMISSIONS) # merge outter dict + +def get_enabled_role_permissions(): + ret = {} + for role, perms in _default_role_perms.iteritems(): + default_perms = _default_role_perms['default'].copy() + default_perms.update(perms) # merge inner dict + ret[role] = default_perms + + # check role permission syntax + for k in default_perms.keys(): + if k not in DEFAULT_ENABLED_ROLE_PERMISSIONS[DEFAULT_USER].keys(): + print '"%s" is not valid permission, please review the ENABLED_ROLE_PERMISSIONS setting.' % k + logger.warn('"%s" is not valid permission, please review the ENABLED_ROLE_PERMISSIONS setting.' % k) + + return ret + +ENABLED_ROLE_PERMISSIONS = get_enabled_role_permissions() diff --git a/seahub/role_permissions/utils.py b/seahub/role_permissions/utils.py new file mode 100644 index 0000000000..4d23a7a1fc --- /dev/null +++ b/seahub/role_permissions/utils.py @@ -0,0 +1,18 @@ +from .settings import ENABLED_ROLE_PERMISSIONS +from seahub.constants import DEFAULT_USER + +def get_available_roles(): + """Get available roles defined in `ENABLED_ROLE_PERMISSIONS`. + """ + return ENABLED_ROLE_PERMISSIONS.keys() + +def get_enabled_role_permissions_by_role(role): + """Get permissions dict(perm_name: bool) of a role. + """ + if not role: + role = DEFAULT_USER + + if role not in ENABLED_ROLE_PERMISSIONS.keys(): + assert False, '%s is not a valid role' % role + + return ENABLED_ROLE_PERMISSIONS[role] diff --git a/seahub/role_permissions/views.py b/seahub/role_permissions/views.py new file mode 100644 index 0000000000..91ea44a218 --- /dev/null +++ b/seahub/role_permissions/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/seahub/settings.py b/seahub/settings.py index c891be6a25..c9d87cafe6 100644 --- a/seahub/settings.py +++ b/seahub/settings.py @@ -503,6 +503,30 @@ ENABLE_GLOBAL_ADDRESSBOOK = True ##################### ENABLE_FOLDER_PERM = False +#################### +# Role permissions # +#################### +# default permissions: +# 'default': { +# 'can_add_repo': True, +# 'can_add_group': True, +# 'can_view_org': True, +# 'can_user_global_address_book': True, +# 'can_generate_shared_link': True, +# 'can_invite_guest': False, +# } +from seahub.constants import GUEST_USER +ENABLED_ROLE_PERMISSIONS = { + GUEST_USER: { + 'can_add_repo': False, + 'can_add_group': False, + 'can_view_org': False, + 'can_use_global_address_book': False, + 'can_generate_shared_link': False, + 'can_invite_guest': False, + }, +} + ##################### # Sudo Mode # ##################### diff --git a/seahub/templates/sysadmin/useradmin_table.html b/seahub/templates/sysadmin/useradmin_table.html index 7a2a48f744..784f927b55 100644 --- a/seahub/templates/sysadmin/useradmin_table.html +++ b/seahub/templates/sysadmin/useradmin_table.html @@ -46,14 +46,19 @@
{% if user.is_guest %} {% trans "Guest" %} - {% else %} + {% elif user.is_default %} {% trans "Default" %} + {% else %} + {{user.role}} {% endif %}
{% else %} -- diff --git a/seahub/utils/user_permissions.py b/seahub/utils/user_permissions.py new file mode 100644 index 0000000000..e68fd9a2e3 --- /dev/null +++ b/seahub/utils/user_permissions.py @@ -0,0 +1,26 @@ +from seahub.constants import DEFAULT_USER, GUEST_USER +from seahub.utils import is_pro_version + +def populate_user_permissions(user): + if is_pro_version(): + from seahub_extra.auth_extra.utils import populate_user_permissions + populate_user_permissions(user) + else: + # use default user permissions + pass + +def get_basic_user_roles(): + """Get predefined user roles. + """ + return [DEFAULT_USER, GUEST_USER] + +def get_user_role(user): + """Get a user's role. + """ + if user.role is None or user.role == '' or user.role == DEFAULT_USER: + return DEFAULT_USER + + if user.role == GUEST_USER: + return GUEST_USER + + return user.role # custom user role diff --git a/seahub/views/sysadmin.py b/seahub/views/sysadmin.py index d073429627..50bef74af8 100644 --- a/seahub/views/sysadmin.py +++ b/seahub/views/sysadmin.py @@ -34,6 +34,7 @@ from seahub.auth import authenticate from seahub.auth.decorators import login_required, login_required_ajax from seahub.constants import GUEST_USER, DEFAULT_USER from seahub.institutions.models import Institution, InstitutionAdmin +from seahub.role_permissions.utils import get_available_roles from seahub.utils import IS_EMAIL_CONFIGURED, string2list, is_valid_username, \ is_pro_version, send_html_email, get_user_traffic_list, get_server_id, \ clear_token, gen_file_get_url, is_org_context, handle_virus_record, \ @@ -45,6 +46,8 @@ from seahub.utils.licenseparse import parse_license from seahub.utils.sysinfo import get_platform_name from seahub.utils.mail import send_html_email_with_dj_template from seahub.utils.ms_excel import write_xls +from seahub.utils.user_permissions import (get_basic_user_roles, + get_user_role) from seahub.views.ajax import (get_related_users_by_org_repo, get_related_users_by_repo) from seahub.views import get_system_default_repo_id, gen_path_link @@ -267,10 +270,8 @@ def sys_user_admin(request): _populate_user_quota_usage(user) # check user's role - if user.role == GUEST_USER: - user.is_guest = True - else: - user.is_guest = False + user.is_guest = True if get_user_role(user) == GUEST_USER else False + user.is_default = True if get_user_role(user) == DEFAULT_USER else False # populate user last login time user.last_login = None @@ -288,6 +289,8 @@ def sys_user_admin(request): platform = get_platform_name() server_id = get_server_id() pro_server = 1 if is_pro_version() else 0 + extra_user_roles = [x for x in get_available_roles() + if x not in get_basic_user_roles()] return render_to_response( 'sysadmin/sys_useradmin.html', { @@ -305,6 +308,7 @@ def sys_user_admin(request): 'is_pro': is_pro_version(), 'pro_server': pro_server, 'enable_user_plan': enable_user_plan, + 'extra_user_roles': extra_user_roles, }, context_instance=RequestContext(request)) @login_required diff --git a/tests/seahub/base/test_accounts.py b/tests/seahub/base/test_accounts.py index d89beadde2..d196083ea8 100644 --- a/tests/seahub/base/test_accounts.py +++ b/tests/seahub/base/test_accounts.py @@ -15,3 +15,19 @@ class UserTest(BaseTestCase): assert len(Email.objects.all()) > 0 # email = Email.objects.all()[0] # print email.html_message + + +class UserPermissionsTest(BaseTestCase): + def test_permissions(self): + assert self.user.permissions.can_add_repo() is True + assert self.user.permissions.can_add_group() is True + assert self.user.permissions.can_generate_shared_link() is True + assert self.user.permissions.can_use_global_address_book() is True + assert self.user.permissions.can_view_org() is True + assert self.user.permissions.can_drag_drop_folder_to_sync() is True + assert self.user.permissions.can_connect_with_android_clients() is True + assert self.user.permissions.can_connect_with_ios_clients() is True + assert self.user.permissions.can_connect_with_desktop_clients() is True + assert self.user.permissions.can_invite_guest() is False + + assert self.user.permissions.can_export_files_via_mobile_client() is True