1 # -*- coding: utf-8 -*-
2 from __future__
import absolute_import
4 from datetime
import datetime
10 from . import BaseController
, ApiController
, RESTController
, Endpoint
, allow_empty_body
12 from ..exceptions
import DashboardException
, UserAlreadyExists
, \
13 UserDoesNotExist
, PasswordPolicyException
, PwdExpirationDateNotValid
14 from ..security
import Scope
15 from ..services
.access_control
import SYSTEM_ROLES
, PasswordPolicy
16 from ..services
.auth
import JwtManager
19 def validate_password_policy(password
, username
=None, old_password
=None):
21 :param password: The password to validate.
22 :param username: The name of the user (optional).
23 :param old_password: The old password (optional).
24 :return: Returns the password complexity credits.
26 :raises DashboardException: If a password policy fails.
28 pw_policy
= PasswordPolicy(password
, username
, old_password
)
31 return pw_policy
.complexity_credits
32 except PasswordPolicyException
as ex
:
33 raise DashboardException(msg
=str(ex
),
34 code
='password_policy_validation_failed',
38 @ApiController('/user', Scope
.USER
)
39 class User(RESTController
):
42 def _user_to_dict(user
):
43 result
= user
.to_dict()
44 del result
['password']
48 def _get_user_roles(roles
):
49 all_roles
= dict(mgr
.ACCESS_CTRL_DB
.roles
)
50 all_roles
.update(SYSTEM_ROLES
)
52 return [all_roles
[rolename
] for rolename
in roles
]
54 raise DashboardException(msg
='Role does not exist',
55 code
='role_does_not_exist',
59 users
= mgr
.ACCESS_CTRL_DB
.users
60 result
= [User
._user
_to
_dict
(u
) for _
, u
in users
.items()]
63 def get(self
, username
):
65 user
= mgr
.ACCESS_CTRL_DB
.get_user(username
)
66 except UserDoesNotExist
:
67 raise cherrypy
.HTTPError(404)
68 return User
._user
_to
_dict
(user
)
70 def create(self
, username
=None, password
=None, name
=None, email
=None,
71 roles
=None, enabled
=True, pwdExpirationDate
=None, pwdUpdateRequired
=True):
73 raise DashboardException(msg
='Username is required',
74 code
='username_required',
78 user_roles
= User
._get
_user
_roles
(roles
)
80 validate_password_policy(password
, username
)
82 user
= mgr
.ACCESS_CTRL_DB
.create_user(username
, password
, name
,
83 email
, enabled
, pwdExpirationDate
,
85 except UserAlreadyExists
:
86 raise DashboardException(msg
='Username already exists',
87 code
='username_already_exists',
89 except PwdExpirationDateNotValid
:
90 raise DashboardException(msg
='Password expiration date must not be in '
92 code
='pwd_past_expiration_date',
96 user
.set_roles(user_roles
)
97 mgr
.ACCESS_CTRL_DB
.save()
98 return User
._user
_to
_dict
(user
)
100 def delete(self
, username
):
101 session_username
= JwtManager
.get_username()
102 if session_username
== username
:
103 raise DashboardException(msg
='Cannot delete current user',
104 code
='cannot_delete_current_user',
107 mgr
.ACCESS_CTRL_DB
.delete_user(username
)
108 except UserDoesNotExist
:
109 raise cherrypy
.HTTPError(404)
110 mgr
.ACCESS_CTRL_DB
.save()
112 def set(self
, username
, password
=None, name
=None, email
=None, roles
=None,
113 enabled
=None, pwdExpirationDate
=None, pwdUpdateRequired
=False):
114 if JwtManager
.get_username() == username
and enabled
is False:
115 raise DashboardException(msg
='You are not allowed to disable your user',
116 code
='cannot_disable_current_user',
120 user
= mgr
.ACCESS_CTRL_DB
.get_user(username
)
121 except UserDoesNotExist
:
122 raise cherrypy
.HTTPError(404)
125 user_roles
= User
._get
_user
_roles
(roles
)
127 validate_password_policy(password
, username
)
128 user
.set_password(password
)
129 if pwdExpirationDate
and \
130 (pwdExpirationDate
< int(time
.mktime(datetime
.utcnow().timetuple()))):
131 raise DashboardException(
132 msg
='Password expiration date must not be in the past',
133 code
='pwd_past_expiration_date', component
='user')
136 if enabled
is not None:
137 user
.enabled
= enabled
138 user
.pwd_expiration_date
= pwdExpirationDate
139 user
.set_roles(user_roles
)
140 user
.pwd_update_required
= pwdUpdateRequired
141 mgr
.ACCESS_CTRL_DB
.save()
142 return User
._user
_to
_dict
(user
)
145 @ApiController('/user')
146 class UserPasswordPolicy(RESTController
):
150 def validate_password(self
, password
, username
=None, old_password
=None):
152 Check if the password meets the password policy.
153 :param password: The password to validate.
154 :param username: The name of the user (optional).
155 :param old_password: The old password (optional).
156 :return: An object with the properties valid, credits and valuation.
157 'credits' contains the password complexity credits and
158 'valuation' the textual summary of the validation.
160 result
= {'valid': False, 'credits': 0, 'valuation': None}
162 result
['credits'] = validate_password_policy(password
, username
, old_password
)
163 if result
['credits'] < 15:
164 result
['valuation'] = 'Weak'
165 elif result
['credits'] < 20:
166 result
['valuation'] = 'OK'
167 elif result
['credits'] < 25:
168 result
['valuation'] = 'Strong'
170 result
['valuation'] = 'Very strong'
171 result
['valid'] = True
172 except DashboardException
as ex
:
173 result
['valuation'] = str(ex
)
177 @ApiController('/user/{username}')
178 class UserChangePassword(BaseController
):
181 def change_password(self
, username
, old_password
, new_password
):
182 session_username
= JwtManager
.get_username()
183 if username
!= session_username
:
184 raise DashboardException(msg
='Invalid user context',
185 code
='invalid_user_context',
188 user
= mgr
.ACCESS_CTRL_DB
.get_user(session_username
)
189 except UserDoesNotExist
:
190 raise cherrypy
.HTTPError(404)
191 if not user
.compare_password(old_password
):
192 raise DashboardException(msg
='Invalid old password',
193 code
='invalid_old_password',
195 validate_password_policy(new_password
, username
, old_password
)
196 user
.set_password(new_password
)
197 mgr
.ACCESS_CTRL_DB
.save()