eficens-iam-sdk 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- eficens_iam_sdk-0.1.0/PKG-INFO +56 -0
- eficens_iam_sdk-0.1.0/README.md +34 -0
- eficens_iam_sdk-0.1.0/pyproject.toml +36 -0
- eficens_iam_sdk-0.1.0/setup.cfg +4 -0
- eficens_iam_sdk-0.1.0/src/eficens_iam_sdk.egg-info/PKG-INFO +56 -0
- eficens_iam_sdk-0.1.0/src/eficens_iam_sdk.egg-info/SOURCES.txt +9 -0
- eficens_iam_sdk-0.1.0/src/eficens_iam_sdk.egg-info/dependency_links.txt +1 -0
- eficens_iam_sdk-0.1.0/src/eficens_iam_sdk.egg-info/requires.txt +1 -0
- eficens_iam_sdk-0.1.0/src/eficens_iam_sdk.egg-info/top_level.txt +1 -0
- eficens_iam_sdk-0.1.0/src/iam_sdk/__init__.py +3 -0
- eficens_iam_sdk-0.1.0/src/iam_sdk/client.py +132 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: eficens-iam-sdk
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python SDK for the Eficens IAM service
|
|
5
|
+
Author: Eficens
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/SheshadriChamarty/IAM
|
|
8
|
+
Project-URL: Repository, https://github.com/SheshadriChamarty/IAM
|
|
9
|
+
Project-URL: Issues, https://github.com/SheshadriChamarty/IAM/issues
|
|
10
|
+
Keywords: iam,auth,authorization,rbac,eficens
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Typing :: Typed
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
Requires-Dist: httpx<1.0,>=0.28
|
|
22
|
+
|
|
23
|
+
# Python IAM SDK
|
|
24
|
+
|
|
25
|
+
Thin Python client for the IAM service.
|
|
26
|
+
|
|
27
|
+
## Install
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pip install eficens-iam-sdk
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Usage
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
from iam_sdk import IamClient
|
|
37
|
+
|
|
38
|
+
iam = IamClient(
|
|
39
|
+
base_url="https://api-iam.eficensittest.com/v1",
|
|
40
|
+
project_id="your-project-id",
|
|
41
|
+
api_key="your-project-api-key",
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
tokens = iam.login("user@example.com", "secret")
|
|
45
|
+
profile = iam.introspect(tokens.access_token)
|
|
46
|
+
allowed = iam.check("todo.tasks.create", tokens.access_token)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Surface
|
|
50
|
+
|
|
51
|
+
- `login(email, password)`
|
|
52
|
+
- `refresh(refresh_token)`
|
|
53
|
+
- `exchange_id_token(id_token)`
|
|
54
|
+
- `introspect(access_token)`
|
|
55
|
+
- `check(permission, access_token)`
|
|
56
|
+
- `batch_check(checks, access_token)`
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Python IAM SDK
|
|
2
|
+
|
|
3
|
+
Thin Python client for the IAM service.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install eficens-iam-sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
from iam_sdk import IamClient
|
|
15
|
+
|
|
16
|
+
iam = IamClient(
|
|
17
|
+
base_url="https://api-iam.eficensittest.com/v1",
|
|
18
|
+
project_id="your-project-id",
|
|
19
|
+
api_key="your-project-api-key",
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
tokens = iam.login("user@example.com", "secret")
|
|
23
|
+
profile = iam.introspect(tokens.access_token)
|
|
24
|
+
allowed = iam.check("todo.tasks.create", tokens.access_token)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Surface
|
|
28
|
+
|
|
29
|
+
- `login(email, password)`
|
|
30
|
+
- `refresh(refresh_token)`
|
|
31
|
+
- `exchange_id_token(id_token)`
|
|
32
|
+
- `introspect(access_token)`
|
|
33
|
+
- `check(permission, access_token)`
|
|
34
|
+
- `batch_check(checks, access_token)`
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "eficens-iam-sdk"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Python SDK for the Eficens IAM service"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { text = "MIT" }
|
|
11
|
+
authors = [{ name = "Eficens" }]
|
|
12
|
+
requires-python = ">=3.10"
|
|
13
|
+
keywords = ["iam", "auth", "authorization", "rbac", "eficens"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3.10",
|
|
20
|
+
"Programming Language :: Python :: 3.11",
|
|
21
|
+
"Programming Language :: Python :: 3.12",
|
|
22
|
+
"Typing :: Typed",
|
|
23
|
+
]
|
|
24
|
+
dependencies = [
|
|
25
|
+
"httpx>=0.28,<1.0",
|
|
26
|
+
]
|
|
27
|
+
[project.urls]
|
|
28
|
+
Homepage = "https://github.com/SheshadriChamarty/IAM"
|
|
29
|
+
Repository = "https://github.com/SheshadriChamarty/IAM"
|
|
30
|
+
Issues = "https://github.com/SheshadriChamarty/IAM/issues"
|
|
31
|
+
|
|
32
|
+
[tool.setuptools]
|
|
33
|
+
package-dir = {"" = "src"}
|
|
34
|
+
|
|
35
|
+
[tool.setuptools.packages.find]
|
|
36
|
+
where = ["src"]
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: eficens-iam-sdk
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python SDK for the Eficens IAM service
|
|
5
|
+
Author: Eficens
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/SheshadriChamarty/IAM
|
|
8
|
+
Project-URL: Repository, https://github.com/SheshadriChamarty/IAM
|
|
9
|
+
Project-URL: Issues, https://github.com/SheshadriChamarty/IAM/issues
|
|
10
|
+
Keywords: iam,auth,authorization,rbac,eficens
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Typing :: Typed
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
Requires-Dist: httpx<1.0,>=0.28
|
|
22
|
+
|
|
23
|
+
# Python IAM SDK
|
|
24
|
+
|
|
25
|
+
Thin Python client for the IAM service.
|
|
26
|
+
|
|
27
|
+
## Install
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pip install eficens-iam-sdk
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Usage
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
from iam_sdk import IamClient
|
|
37
|
+
|
|
38
|
+
iam = IamClient(
|
|
39
|
+
base_url="https://api-iam.eficensittest.com/v1",
|
|
40
|
+
project_id="your-project-id",
|
|
41
|
+
api_key="your-project-api-key",
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
tokens = iam.login("user@example.com", "secret")
|
|
45
|
+
profile = iam.introspect(tokens.access_token)
|
|
46
|
+
allowed = iam.check("todo.tasks.create", tokens.access_token)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Surface
|
|
50
|
+
|
|
51
|
+
- `login(email, password)`
|
|
52
|
+
- `refresh(refresh_token)`
|
|
53
|
+
- `exchange_id_token(id_token)`
|
|
54
|
+
- `introspect(access_token)`
|
|
55
|
+
- `check(permission, access_token)`
|
|
56
|
+
- `batch_check(checks, access_token)`
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
src/eficens_iam_sdk.egg-info/PKG-INFO
|
|
4
|
+
src/eficens_iam_sdk.egg-info/SOURCES.txt
|
|
5
|
+
src/eficens_iam_sdk.egg-info/dependency_links.txt
|
|
6
|
+
src/eficens_iam_sdk.egg-info/requires.txt
|
|
7
|
+
src/eficens_iam_sdk.egg-info/top_level.txt
|
|
8
|
+
src/iam_sdk/__init__.py
|
|
9
|
+
src/iam_sdk/client.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
httpx<1.0,>=0.28
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
iam_sdk
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
import httpx
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class IamError(Exception):
|
|
10
|
+
def __init__(self, message: str, status_code: int, detail: Any = None):
|
|
11
|
+
super().__init__(message)
|
|
12
|
+
self.status_code = status_code
|
|
13
|
+
self.detail = detail
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass
|
|
17
|
+
class TokenResponse:
|
|
18
|
+
access_token: str
|
|
19
|
+
refresh_token: str
|
|
20
|
+
token_type: str = "bearer"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class IamClient:
|
|
24
|
+
def __init__(self, base_url: str, project_id: str, api_key: str | None = None, timeout: float = 10.0):
|
|
25
|
+
self.base_url = base_url.rstrip("/")
|
|
26
|
+
self.project_id = project_id
|
|
27
|
+
self.api_key = api_key
|
|
28
|
+
self.timeout = timeout
|
|
29
|
+
|
|
30
|
+
def login(self, email: str, password: str) -> TokenResponse:
|
|
31
|
+
data = self._request(
|
|
32
|
+
"/auth/token",
|
|
33
|
+
method="POST",
|
|
34
|
+
json={
|
|
35
|
+
"grant_type": "password",
|
|
36
|
+
"project_id": self.project_id,
|
|
37
|
+
"email": email,
|
|
38
|
+
"password": password,
|
|
39
|
+
},
|
|
40
|
+
)
|
|
41
|
+
return TokenResponse(**data)
|
|
42
|
+
|
|
43
|
+
def refresh(self, refresh_token: str) -> TokenResponse:
|
|
44
|
+
data = self._request(
|
|
45
|
+
"/auth/token",
|
|
46
|
+
method="POST",
|
|
47
|
+
json={
|
|
48
|
+
"grant_type": "refresh_token",
|
|
49
|
+
"refresh_token": refresh_token,
|
|
50
|
+
},
|
|
51
|
+
)
|
|
52
|
+
return TokenResponse(**data)
|
|
53
|
+
|
|
54
|
+
def exchange_id_token(self, id_token: str) -> TokenResponse:
|
|
55
|
+
data = self._request(
|
|
56
|
+
"/auth/token",
|
|
57
|
+
method="POST",
|
|
58
|
+
json={
|
|
59
|
+
"grant_type": "id_token",
|
|
60
|
+
"project_id": self.project_id,
|
|
61
|
+
"id_token": id_token,
|
|
62
|
+
},
|
|
63
|
+
)
|
|
64
|
+
return TokenResponse(**data)
|
|
65
|
+
|
|
66
|
+
def introspect(self, access_token: str) -> dict[str, Any]:
|
|
67
|
+
return self._request(
|
|
68
|
+
"/auth/introspect",
|
|
69
|
+
method="POST",
|
|
70
|
+
access_token=access_token,
|
|
71
|
+
require_api_key=True,
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
def check(self, permission: str, access_token: str) -> bool:
|
|
75
|
+
result = self._request(
|
|
76
|
+
"/authz/check",
|
|
77
|
+
method="POST",
|
|
78
|
+
access_token=access_token,
|
|
79
|
+
require_api_key=True,
|
|
80
|
+
include_project_header=True,
|
|
81
|
+
json={"permission": permission},
|
|
82
|
+
)
|
|
83
|
+
return bool(result["allowed"])
|
|
84
|
+
|
|
85
|
+
def batch_check(self, checks: list[dict[str, str]], access_token: str) -> dict[str, Any]:
|
|
86
|
+
return self._request(
|
|
87
|
+
"/authz/batch-check",
|
|
88
|
+
method="POST",
|
|
89
|
+
access_token=access_token,
|
|
90
|
+
require_api_key=True,
|
|
91
|
+
include_project_header=True,
|
|
92
|
+
json={"checks": checks},
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
def _request(
|
|
96
|
+
self,
|
|
97
|
+
path: str,
|
|
98
|
+
*,
|
|
99
|
+
method: str,
|
|
100
|
+
json: dict[str, Any] | None = None,
|
|
101
|
+
access_token: str | None = None,
|
|
102
|
+
require_api_key: bool = False,
|
|
103
|
+
include_project_header: bool = False,
|
|
104
|
+
) -> dict[str, Any]:
|
|
105
|
+
headers: dict[str, str] = {}
|
|
106
|
+
if access_token:
|
|
107
|
+
headers["Authorization"] = f"Bearer {access_token}"
|
|
108
|
+
if require_api_key:
|
|
109
|
+
if not self.api_key:
|
|
110
|
+
raise IamError("API key is required for this operation", 0)
|
|
111
|
+
headers["X-Api-Key"] = self.api_key
|
|
112
|
+
if include_project_header:
|
|
113
|
+
headers["X-Project-Id"] = self.project_id
|
|
114
|
+
|
|
115
|
+
with httpx.Client(timeout=self.timeout) as client:
|
|
116
|
+
response = client.request(
|
|
117
|
+
method,
|
|
118
|
+
f"{self.base_url}{path}",
|
|
119
|
+
headers=headers,
|
|
120
|
+
json=json,
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
if response.is_error:
|
|
124
|
+
detail: Any
|
|
125
|
+
try:
|
|
126
|
+
detail = response.json()
|
|
127
|
+
except ValueError:
|
|
128
|
+
detail = None
|
|
129
|
+
message = detail.get("detail") if isinstance(detail, dict) else response.text or "IAM request failed"
|
|
130
|
+
raise IamError(str(message), response.status_code, detail)
|
|
131
|
+
|
|
132
|
+
return response.json()
|