Skip to content

Commit 01364ee

Browse files
authored
Merge pull request #71 from oslokommune/DP-1944-initial-permission-api-support
DP-1944 Add initial support for the permission API
2 parents 9e078aa + 36e846a commit 01364ee

3 files changed

Lines changed: 113 additions & 0 deletions

File tree

okdata/sdk/config.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"uploadUrl": "https://api.data-dev.oslo.systems/data-uploader",
2626
"statusApiUrl": "https://api.data-dev.oslo.systems/status-api/status",
2727
"simpleDatasetAuthorizerUrl": "https://api.data-dev.oslo.systems/simple-dataset-authorizer",
28+
"permissionApiUrl": "https://api.data-dev.oslo.systems/okdata-permission-api",
2829
}
2930
OKDATA_CONFIG["prod"] = {
3031
"client_id": None,
@@ -43,6 +44,7 @@
4344
"uploadUrl": "https://api.data.oslo.systems/data-uploader",
4445
"statusApiUrl": "https://api.data.oslo.systems/status-api/status",
4546
"simpleDatasetAuthorizerUrl": "https://api.data.oslo.systems/simple-dataset-authorizer",
47+
"permissionApiUrl": "https://api.data.oslo.systems/okdata-permission-api",
4648
}
4749

4850
OKDATA_DEFAULT_ENVIRONMENT = "prod"

okdata/sdk/permission/client.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import logging
2+
from urllib.parse import quote
3+
4+
# TODO: Polyfill. Replace with `from dataclasses import asdict` once support
5+
# for Python 3.6 is dropped.
6+
from okdata.sdk.permission.user_types import asdict
7+
from okdata.sdk import SDK
8+
9+
log = logging.getLogger()
10+
11+
12+
class PermissionClient(SDK):
13+
def __init__(self, config=None, auth=None, env=None):
14+
self.__name__ = "permission"
15+
super().__init__(config, auth, env)
16+
self.api_url = self.config.get("permissionApiUrl")
17+
18+
def update_permission(
19+
self, resource_name, scope, add_users=[], remove_users=[], retries=0
20+
):
21+
"""Grant or revoke permissions for a resource.
22+
23+
`resource_name` must be given on the form "namespace:type:id", while
24+
`scope` must be given on the form "namespace:type:permission".
25+
26+
`add_users` and `remove_users` are iterables containing the users to
27+
give access to and to revoke access from, respectively. The users
28+
should be instances of the user types defined in
29+
`okdata.sdk.permission.user_types`.
30+
31+
Usage example giving read access to the dataset "my-dataset" to the
32+
user "janedoe":
33+
34+
update_permission(
35+
"okdata:dataset:my-dataset",
36+
"okdata:dataset:read",
37+
add_users=[User("janedoe")],
38+
)
39+
"""
40+
url = "{}/permissions/{}".format(self.api_url, quote(resource_name))
41+
data = {
42+
"add_users": list(map(asdict, add_users)),
43+
"remove_users": list(map(asdict, remove_users)),
44+
"scope": scope,
45+
}
46+
log.info(f"SDK:Updating permissions for {resource_name} with {data}")
47+
return self.put(url, data, retries=retries).json()
48+
49+
def get_my_permissions(self, retries=0):
50+
"""Return a list of permissions associated with the current user."""
51+
url = f"{self.api_url}/my_permissions"
52+
log.info(f"SDK:Listing permissions from: {url}")
53+
return self.get(url, retries=retries).json()
54+
55+
def get_permissions(self, resource_name, retries=0):
56+
"""Return a list of permissions associated with `resource_name`."""
57+
url = "{}/permissions/{}".format(self.api_url, quote(resource_name))
58+
log.info(f"SDK:Getting permissions for {resource_name} from: {url}")
59+
return self.get(url, retries=retries).json()
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# TODO: Use these simplified dataclasses once support for Python 3.6 is
2+
# dropped. Meanwhile we'll use the "polyfill" classes defined below.
3+
#
4+
# from dataclasses import dataclass, field
5+
#
6+
# @dataclass
7+
# class Client:
8+
# user_id: str
9+
# user_type: str = field(default="client", init=False)
10+
#
11+
#
12+
# @dataclass
13+
# class Team:
14+
# user_id: str
15+
# user_type: str = field(default="team", init=False)
16+
#
17+
#
18+
# @dataclass
19+
# class User:
20+
# user_id: str
21+
# user_type: str = field(default="user", init=False)
22+
23+
24+
class Client:
25+
user_id: str
26+
user_type: str
27+
28+
def __init__(self, user_id):
29+
self.user_id = user_id
30+
self.user_type = "client"
31+
32+
33+
class Team:
34+
user_id: str
35+
user_type: str
36+
37+
def __init__(self, user_id):
38+
self.user_id = user_id
39+
self.user_type = "team"
40+
41+
42+
class User:
43+
user_id: str
44+
user_type: str
45+
46+
def __init__(self, user_id):
47+
self.user_id = user_id
48+
self.user_type = "user"
49+
50+
51+
def asdict(obj):
52+
return obj.__dict__

0 commit comments

Comments
 (0)