Coverage for gws-app/gws/plugin/auth_provider/file/__init__.py: 0%
57 statements
« prev ^ index » next coverage.py v7.8.0, created at 2025-04-17 01:37 +0200
« prev ^ index » next coverage.py v7.8.0, created at 2025-04-17 01:37 +0200
1"""Provider for the file-based authorization.
3This provider works with a local JSON file, which is expected to contain
4a list of user "records" (dicts).
6A record is required to contain fields ``login`` and ``password`` (hashed as per `gws.lib.password.encode`).
8Other fields, if given, are converted to respective `gws.User` properties.
9"""
11import getpass
13import gws
14import gws.base.auth
15import gws.lib.jsonx
16import gws.lib.password
18gws.ext.new.authProvider('file')
21class Config(gws.base.auth.provider.Config):
22 """File-based authorization provider"""
24 path: gws.FilePath
25 """path to the users json file"""
28class Object(gws.base.auth.provider.Object):
29 path: str
30 db: list[dict]
32 def configure(self):
33 self.path = self.cfg('path')
34 self.db = gws.lib.jsonx.from_path(self.path)
36 def authenticate(self, method, credentials):
37 wrong_password = 0
38 found = []
40 username = credentials.get('username')
41 password = credentials.get('password')
42 if not username or not password:
43 return
45 for rec in self.db:
46 login_ok = gws.lib.password.compare(username, rec['login'])
47 password_ok = gws.lib.password.check(password, rec['password'])
48 if login_ok and password_ok:
49 found.append(rec)
50 if login_ok and not password_ok:
51 wrong_password += 1
53 if wrong_password:
54 raise gws.ForbiddenError(f'wrong password for {username!r}')
56 if len(found) > 1:
57 raise gws.ForbiddenError(f'multiple entries for {username!r}')
59 if len(found) == 1:
60 return self._make_user(found[0])
62 def get_user(self, local_uid):
63 for rec in self.db:
64 if rec['login'] == local_uid:
65 return self._make_user(rec)
67 def _make_user(self, rec: dict):
68 user_rec = dict(rec)
70 login = user_rec.pop('login', '')
71 user_rec['localUid'] = user_rec['loginName'] = login
72 user_rec['displayName'] = user_rec.pop('name', login)
73 user_rec.pop('password', '')
75 return gws.base.auth.user.from_record(self, user_rec)
77 @gws.ext.command.cli('authPassword')
78 def passwd(self, p: gws.EmptyRequest):
79 """Encode a password for the authorization file"""
81 while True:
82 p1 = getpass.getpass('Password: ')
83 p2 = getpass.getpass('Repeat : ')
85 if p1 != p2:
86 print('passwords do not match')
87 continue
89 p = gws.lib.password.encode(p1)
90 print(p)
91 break