-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathuser.py
More file actions
97 lines (80 loc) · 3.5 KB
/
user.py
File metadata and controls
97 lines (80 loc) · 3.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#
# Copyright 2022 European Centre for Medium-Range Weather Forecasts (ECMWF)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# In applying this licence, ECMWF does not waive the privileges and immunities
# granted to it by virtue of its status as an intergovernmental organisation nor
# does it submit to any jurisdiction.
#
import logging
import uuid
class User:
__slots__ = ["id", "username", "realm", "roles", "attributes"]
def __init__(self, username=None, realm=None, from_dict=None):
self.username = username
self.realm = realm
self.roles = []
self.attributes = {}
self.id = None
if from_dict is not None:
for k, v in from_dict.items():
self.__setattr__(k, v)
if self.username is None or self.realm is None:
raise AttributeError("User object must be instantiated with username and realm attributes")
self.create_uuid()
def __setattr__(self, attr, value):
if attr == "username" and getattr(self, "username", None) is not None:
raise AttributeError("User username is immutable")
if attr == "realm" and getattr(self, "realm", None) is not None:
raise AttributeError("User realm is immutable")
if attr == "id" and getattr(self, "id", None) is not None:
raise AttributeError("User ID is immutable")
super().__setattr__(attr, value)
def __eq__(self, other):
return isinstance(other, User) and self.id == other.id
def create_uuid(self):
if getattr(self, "id", None) is not None:
return
null_uuid = uuid.UUID(int=0)
unique_string = "{}{}{}{}".format(self.username, len(self.username), self.realm, len(self.realm))
id = str(uuid.uuid5(null_uuid, unique_string))
super().__setattr__("id", id)
def serialize(self):
result = {}
for k in self.__slots__:
v = self.__getattribute__(k)
result[k] = v
return result
def __str__(self):
return f"User({self.realm}:{self.username})"
def has_access(self, roles: list | set | dict | str) -> bool:
"""Checks if the user has any of the provided roles"""
logging.debug(f"User roles: {self.roles}")
logging.debug(f"Allowed roles {roles}")
# roles can be a dict of realm:[roles] mapping; find the relevant realm.
if isinstance(roles, dict):
if self.realm not in roles:
logging.info(
"User {} does not have access to realm {}, roles: {}".format(self.username, self.realm, roles)
)
return False
roles = roles[self.realm]
# roles can be a single value; convert to a list
if not isinstance(roles, (tuple, list, set)):
roles = [roles]
for required_role in roles:
if required_role in self.roles:
logging.debug(f"User {self.username} is authorized with role {required_role}")
return True
return False