]>
Commit | Line | Data |
---|---|---|
11fdf7f2 | 1 | # -*- coding: utf-8 -*- |
11fdf7f2 TL |
2 | |
3 | import cherrypy | |
4 | ||
11fdf7f2 | 5 | from .. import mgr |
f67539c2 TL |
6 | from ..exceptions import DashboardException, RoleAlreadyExists, \ |
7 | RoleDoesNotExist, RoleIsAssociatedWithUser | |
8 | from ..security import Permission | |
9 | from ..security import Scope as SecurityScope | |
11fdf7f2 | 10 | from ..services.access_control import SYSTEM_ROLES |
a4b75251 | 11 | from . import APIDoc, APIRouter, CreatePermission, EndpointDoc, RESTController, UIRouter |
f67539c2 TL |
12 | |
13 | ROLE_SCHEMA = [{ | |
14 | "name": (str, "Role Name"), | |
15 | "description": (str, "Role Descriptions"), | |
16 | "scopes_permissions": ({ | |
17 | "cephfs": ([str], "") | |
18 | }, ""), | |
19 | "system": (bool, "") | |
20 | }] | |
11fdf7f2 TL |
21 | |
22 | ||
a4b75251 TL |
23 | @APIRouter('/role', SecurityScope.USER) |
24 | @APIDoc("Role Management API", "Role") | |
11fdf7f2 TL |
25 | class Role(RESTController): |
26 | @staticmethod | |
27 | def _role_to_dict(role): | |
28 | role_dict = role.to_dict() | |
29 | role_dict['system'] = role_dict['name'] in SYSTEM_ROLES | |
30 | return role_dict | |
31 | ||
32 | @staticmethod | |
33 | def _validate_permissions(scopes_permissions): | |
34 | if scopes_permissions: | |
35 | for scope, permissions in scopes_permissions.items(): | |
36 | if scope not in SecurityScope.all_scopes(): | |
37 | raise DashboardException(msg='Invalid scope', | |
38 | code='invalid_scope', | |
39 | component='role') | |
40 | if any(permission not in Permission.all_permissions() | |
41 | for permission in permissions): | |
42 | raise DashboardException(msg='Invalid permission', | |
43 | code='invalid_permission', | |
44 | component='role') | |
45 | ||
46 | @staticmethod | |
47 | def _set_permissions(role, scopes_permissions): | |
48 | role.reset_scope_permissions() | |
49 | if scopes_permissions: | |
50 | for scope, permissions in scopes_permissions.items(): | |
51 | if permissions: | |
52 | role.set_scope_permissions(scope, permissions) | |
53 | ||
f67539c2 TL |
54 | @EndpointDoc("Display Role list", |
55 | responses={200: ROLE_SCHEMA}) | |
11fdf7f2 | 56 | def list(self): |
9f95a23c | 57 | # type: () -> list |
11fdf7f2 TL |
58 | roles = dict(mgr.ACCESS_CTRL_DB.roles) |
59 | roles.update(SYSTEM_ROLES) | |
60 | roles = sorted(roles.values(), key=lambda role: role.name) | |
61 | return [Role._role_to_dict(r) for r in roles] | |
62 | ||
9f95a23c TL |
63 | @staticmethod |
64 | def _get(name): | |
11fdf7f2 TL |
65 | role = SYSTEM_ROLES.get(name) |
66 | if not role: | |
67 | try: | |
68 | role = mgr.ACCESS_CTRL_DB.get_role(name) | |
69 | except RoleDoesNotExist: | |
70 | raise cherrypy.HTTPError(404) | |
71 | return Role._role_to_dict(role) | |
72 | ||
9f95a23c TL |
73 | def get(self, name): |
74 | # type: (str) -> dict | |
75 | return Role._get(name) | |
76 | ||
77 | @staticmethod | |
78 | def _create(name=None, description=None, scopes_permissions=None): | |
11fdf7f2 TL |
79 | if not name: |
80 | raise DashboardException(msg='Name is required', | |
81 | code='name_required', | |
82 | component='role') | |
83 | Role._validate_permissions(scopes_permissions) | |
84 | try: | |
85 | role = mgr.ACCESS_CTRL_DB.create_role(name, description) | |
86 | except RoleAlreadyExists: | |
87 | raise DashboardException(msg='Role already exists', | |
88 | code='role_already_exists', | |
89 | component='role') | |
90 | Role._set_permissions(role, scopes_permissions) | |
91 | mgr.ACCESS_CTRL_DB.save() | |
92 | return Role._role_to_dict(role) | |
93 | ||
9f95a23c TL |
94 | def create(self, name=None, description=None, scopes_permissions=None): |
95 | # type: (str, str, dict) -> dict | |
96 | return Role._create(name, description, scopes_permissions) | |
97 | ||
11fdf7f2 | 98 | def set(self, name, description=None, scopes_permissions=None): |
9f95a23c | 99 | # type: (str, str, dict) -> dict |
11fdf7f2 TL |
100 | try: |
101 | role = mgr.ACCESS_CTRL_DB.get_role(name) | |
102 | except RoleDoesNotExist: | |
103 | if name in SYSTEM_ROLES: | |
104 | raise DashboardException(msg='Cannot update system role', | |
105 | code='cannot_update_system_role', | |
106 | component='role') | |
107 | raise cherrypy.HTTPError(404) | |
108 | Role._validate_permissions(scopes_permissions) | |
109 | Role._set_permissions(role, scopes_permissions) | |
110 | role.description = description | |
111 | mgr.ACCESS_CTRL_DB.update_users_with_roles(role) | |
112 | mgr.ACCESS_CTRL_DB.save() | |
113 | return Role._role_to_dict(role) | |
114 | ||
115 | def delete(self, name): | |
9f95a23c | 116 | # type: (str) -> None |
11fdf7f2 TL |
117 | try: |
118 | mgr.ACCESS_CTRL_DB.delete_role(name) | |
119 | except RoleDoesNotExist: | |
120 | if name in SYSTEM_ROLES: | |
121 | raise DashboardException(msg='Cannot delete system role', | |
122 | code='cannot_delete_system_role', | |
123 | component='role') | |
124 | raise cherrypy.HTTPError(404) | |
125 | except RoleIsAssociatedWithUser: | |
126 | raise DashboardException(msg='Role is associated with user', | |
127 | code='role_is_associated_with_user', | |
128 | component='role') | |
129 | mgr.ACCESS_CTRL_DB.save() | |
130 | ||
9f95a23c TL |
131 | @RESTController.Resource('POST', status=201) |
132 | @CreatePermission | |
133 | def clone(self, name, new_name): | |
134 | # type: (str, str) -> dict | |
135 | role = Role._get(name) | |
136 | return Role._create(new_name, role.get('description'), | |
137 | role.get('scopes_permissions')) | |
138 | ||
11fdf7f2 | 139 | |
a4b75251 | 140 | @UIRouter('/scope', SecurityScope.USER) |
11fdf7f2 TL |
141 | class Scope(RESTController): |
142 | def list(self): | |
143 | return SecurityScope.all_scopes() |