Skip to content

Commit 7d86ebc

Browse files
Rasmus Oscar Welanderglpatcern
authored andcommitted
Added user class, tests, example and some minor changes
1 parent 76004fa commit 7d86ebc

File tree

10 files changed

+414
-32
lines changed

10 files changed

+414
-32
lines changed

examples/file_api_example.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
example.py
2+
file_api_example.py
33
44
Example script to demonstrate the usage of the CS3Client class.
55
Start with an empty directory and you should end up with a directory structure like this:
@@ -13,7 +13,7 @@
1313
1414
Authors: Rasmus Welander, Diogo Castro, Giuseppe Lo Presti.
1515
16-
Last updated: 29/07/2024
16+
Last updated: 01/08/2024
1717
"""
1818

1919
import logging
@@ -28,7 +28,9 @@
2828
log = logging.getLogger(__name__)
2929

3030
client = CS3Client(config, "cs3client", log)
31-
client.auth.set_client_secret("relativity")
31+
client.auth.set_token("<your_token_here>")
32+
# OR
33+
# client.auth.set_client_secret("<your_client_secret_here>")
3234

3335
# Authentication
3436
print(client.auth.get_token())

examples/user_api_example.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
"""
2+
user_api_example.py
3+
4+
Example script to demonstrate the usage of the CS3Client class.
5+
6+
7+
Authors: Rasmus Welander, Diogo Castro, Giuseppe Lo Presti.
8+
9+
Last updated: 02/08/2024
10+
"""
11+
12+
import logging
13+
import configparser
14+
from cs3client import CS3Client
15+
16+
config = configparser.ConfigParser()
17+
with open("default.conf") as fdef:
18+
config.read_file(fdef)
19+
# log
20+
log = logging.getLogger(__name__)
21+
22+
client = CS3Client(config, "cs3client", log)
23+
# client.auth.set_token("<your_token_here>")
24+
# OR
25+
client.auth.set_client_secret("<your_client_secret_here>")
26+
27+
28+
res = None
29+
30+
# find_user
31+
res = client.user.find_users("rwel")
32+
if res is not None:
33+
print(res)
34+
35+
# get_user
36+
res = client.user.get_user("https://auth.cern.ch/auth/realms/cern", "asdoiqwe")
37+
38+
if res is not None:
39+
print(res)
40+
41+
# get_user_groups
42+
res = client.user.get_user_groups("https://auth.cern.ch/auth/realms/cern", "rwelande")
43+
44+
if res is not None:
45+
print(res)
46+
47+
# get_user_by_claim (mail)
48+
res = client.user.get_user_by_claim("mail", "[email protected]")
49+
if res is not None:
50+
print(res)
51+
52+
# get_user_by_claim (username)
53+
res = client.user.get_user_by_claim("username", "rwelande")
54+
if res is not None:
55+
print(res)

src/auth.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@
33
44
Authors: Rasmus Welander, Diogo Castro, Giuseppe Lo Presti.
55
6-
Last updated: 29/07/2024
6+
Last updated: 01/08/2024
77
"""
88

9-
from typing import List
109
import grpc
1110
import jwt
1211
import datetime
@@ -76,7 +75,7 @@ def get_token(self) -> tuple[str, str]:
7675
# Check that client secret or token is set
7776
if not self._client_secret and not self._token:
7877
self._log.error("Attempted to authenticate, neither client secret or token was set.")
79-
raise SecretNotSetException("")
78+
raise SecretNotSetException("The client secret (e.g. token, passowrd) is not set")
8079
elif not self._client_secret and self._token:
8180
# Case where ONLY a token is provided but it has expired
8281
self._log.error("The provided token have expired")
@@ -100,7 +99,7 @@ def get_token(self) -> tuple[str, str]:
10099
self._token = res.token
101100
return ("x-access-token", self._token)
102101

103-
def list_auth_providers(self) -> List[str]:
102+
def list_auth_providers(self) -> list[str]:
104103
"""
105104
list authentication providers
106105

src/cs3client.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
44
Authors: Rasmus Welander, Diogo Castro, Giuseppe Lo Presti.
55
6-
Last updated: 29/07/2024
6+
Last updated: 01/08/2024
77
"""
88

99
import grpc
@@ -13,6 +13,7 @@
1313
from configparser import ConfigParser
1414
from auth import Auth
1515
from file import File
16+
from user import User
1617
from config import Config
1718

1819

@@ -41,6 +42,7 @@ def __init__(self, config: ConfigParser, config_category: str, log: logging.Logg
4142
self._gateway: cs3gw_grpc.GatewayAPIStub = cs3gw_grpc.GatewayAPIStub(self.channel)
4243
self.auth = Auth(self._config, self._log, self._gateway)
4344
self.file = File(self._config, self._log, self._gateway, self.auth)
45+
self.user = User(self._config, self._log, self._gateway, self.auth)
4446

4547
def _create_channel(self) -> grpc.Channel:
4648
"""

src/exceptions/exceptions.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
66
Authors: Rasmus Welander, Diogo Castro, Giuseppe Lo Presti.
77
8-
Last updated: 29/07/2024
8+
Last updated: 01/08/2024
99
"""
1010

1111

@@ -15,7 +15,7 @@ class AuthenticationException(Exception):
1515
"""
1616

1717
def __init__(self, message: str = ""):
18-
super().__init__("Operation not permitted" + " " + message)
18+
super().__init__(message)
1919

2020

2121
class NotFoundException(IOError):
@@ -24,7 +24,7 @@ class NotFoundException(IOError):
2424
"""
2525

2626
def __init__(self, message: str = ""):
27-
super().__init__("No such file or directory" + " " + message)
27+
super().__init__(message)
2828

2929

3030
class SecretNotSetException(Exception):
@@ -33,17 +33,17 @@ class SecretNotSetException(Exception):
3333
"""
3434

3535
def __init__(self, message: str = ""):
36-
super().__init__("The client secret (e.g. token, passowrd) is not set" + " " + message)
36+
super().__init__(message)
3737

3838

3939
class FileLockedException(IOError):
4040
"""
41-
Standard error thrown when attempting to overwrite a file/xattr in O_EXCL mode
42-
or when a lock operation cannot be performed because of failed preconditions
41+
Standard error thrown when attempting to overwrite a file/xattr or when
42+
a lock operation cannot be performed because of failed preconditions
4343
"""
4444

4545
def __init__(self, message: str = ""):
46-
super().__init__("File/xattr exists but EXCL mode requested, lock mismatch or lock expired" + " " + message)
46+
super().__init__(message)
4747

4848

4949
class UnknownException(Exception):

src/file.py

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
44
Authors: Rasmus Welander, Diogo Castro, Giuseppe Lo Presti.
55
6-
Last updated: 29/07/2024
6+
Last updated: 02/08/2024
77
"""
88

99
import time
@@ -47,41 +47,40 @@ def _log_not_found_info(self, resource: Resource, res: any, operation: str) -> N
4747
def _log_precondition_info(self, resource: Resource, res: any, operation: str) -> None:
4848
self._log.info(
4949
f'msg="Failed precondition on {operation}" {resource.get_file_ref_str()} '
50-
f'userid="{self._config.auth_client_id}" trace="{res.status.trace}"'
50+
f'userid="{self._config.auth_client_id}" trace="{res.status.trace}" '
5151
f'reason="{res.status.message.replace('"', "'")}"'
5252
)
5353

5454
def _log_authentication_error(self, resource: Resource, res: any, operation: str) -> None:
5555
self._log.error(
5656
f'msg="Authentication failed on {operation}" {resource.get_file_ref_str()} '
57-
f'userid="{self._config.auth_client_id}" trace="{res.status.trace}"'
57+
f'userid="{self._config.auth_client_id}" trace="{res.status.trace}" '
5858
f'reason="{res.status.message.replace('"', "'")}"'
5959
)
6060

6161
def _log_unknown_error(self, resource: Resource, res: any, operation: str) -> None:
6262
self._log.error(
6363
f'msg="Failed to {operation}, unknown error" {resource.get_file_ref_str()} '
64-
f'userid="{self._config.auth_client_id}" trace="{res.status.trace}"'
64+
f'userid="{self._config.auth_client_id}" trace="{res.status.trace}" '
6565
f'reason="{res.status.message.replace('"', "'")}"'
6666
)
6767

68-
def _handle_errors(self, resource: Resource, res: any, operation: str, msg: str = "") -> None:
68+
def _handle_errors(self, resource: Resource, res: any, operation: str) -> None:
6969
if res.status.code == cs3code.CODE_NOT_FOUND:
7070
self._log_not_found_info(resource, res, operation)
71-
self._log.info(f'msg="Invoked {operation} on missing file" {resource.get_file_ref_str()}')
72-
raise NotFoundException(message=msg)
71+
raise NotFoundException(message=f"No such file or directory: {res.status.message}")
7372
if res.status.code in [cs3code.CODE_FAILED_PRECONDITION, cs3code.CODE_ABORTED]:
7473
self._log_precondition_info(resource, res, operation)
75-
raise FileLockedException(message=msg)
74+
raise FileLockedException(message=f"Lock mismatch or lock expired: {res.status.message}")
7675
if res.status.code == cs3code.CODE_UNAUTHENTICATED:
7776
self._log_authentication_error(resource, res, operation)
78-
raise AuthenticationException(message=msg)
77+
raise AuthenticationException(message=f"Operation not permitted: {res.status.message}")
7978
if res.status.code != cs3code.CODE_OK:
8079
if "path not found" in str(res):
8180
self._log.info(f'msg="Invoked {operation} on missing file" {resource.get_file_ref_str()}')
82-
raise NotFoundException(message=msg)
81+
raise NotFoundException(message=f"No such file or directory: {res.status.message}")
8382
self._log_unknown_error(resource, res, operation)
84-
raise UnknownException(res.status.message)
83+
raise UnknownException(message=f"Unknown error: {res.status.message}")
8584

8685
def stat(self, resource: Resource) -> cs3spr.ResourceInfo:
8786
"""
@@ -154,7 +153,7 @@ def rename_file(self, resource: Resource, newresource: Resource) -> None:
154153
"""
155154
req = cs3sp.MoveRequest(source=resource.ref, destination=newresource.ref)
156155
res = self._gateway.Move(request=req, metadata=[self._auth.get_token()])
157-
self._handle_errors(resource, res, "rename_file")
156+
self._handle_errors(resource, res, "rename file")
158157
self._log.debug(f'msg="Invoked renamefile" result="{res}"')
159158

160159
def remove_file(self, resource: Resource) -> None:
@@ -254,10 +253,10 @@ def write_file(self, resource: Resource, content: str | bytes, size: int) -> Non
254253
self._log.info(
255254
f'msg="Got conflict on PUT, file is locked" reason="{putres.reason}" {resource.get_file_ref_str()}'
256255
)
257-
raise FileLockedException()
256+
raise FileLockedException(f"Lock mismatch or lock expired: {putres.reason}")
258257
if putres.status_code == http.client.UNAUTHORIZED:
259258
self._log_authentication_error(resource, putres, "write")
260-
raise AuthenticationException()
259+
raise AuthenticationException(f"Operation not permitted: {putres.reason}")
261260
if putres.status_code != http.client.OK:
262261
if (
263262
size == 0

0 commit comments

Comments
 (0)