Skip to content

Commit ab16384

Browse files
authored
chore: add type checks for Authorization with new example. (influxdata#682)
* chore: add type checks for Authorization with new example. * docs: update CHANGELOG.md and examples/README.md
1 parent 2d0adb9 commit ab16384

File tree

6 files changed

+138
-1
lines changed

6 files changed

+138
-1
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
## 1.49.0 [unreleased]
22

3+
### Bug Fixes
4+
5+
1. [#682](https://github.com/influxdata/influxdb-client-python/pull/682): Check core types when creating Authentication instances.
6+
7+
### Examples
8+
9+
1. [#682](https://github.com/influxdata/influxdb-client-python/pull/682): New example for working with Authentication API.
10+
311
## 1.48.0 [2024-11-27]
412

513
### Bug Fixes

examples/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
- [monitoring_and_alerting.py](monitoring_and_alerting.py) - How to create the Check with Slack notification.
2929
- [task_example.py](task_example.py) - How to create a Task by API
3030
- [templates_management.py](templates_management.py) - How to use Templates and Stack API
31+
- [authorizations.py](authorizations.py) - How to create and use authorizations.
3132

3233
## InfluxDB Cloud
3334

examples/authorizations.py

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import os
2+
3+
from influxdb_client import InfluxDBClient, BucketRetentionRules, PermissionResource, Permission, Authorization, \
4+
WriteOptions
5+
from influxdb_client.client.write_api import WriteType
6+
from influxdb_client.rest import ApiException
7+
8+
HOST_URL = os.environ.get("INFLUX_HOST") if os.environ.get("INFLUX_HOST") is not None else "http://localhost:8086"
9+
TOKEN = os.environ.get("INFLUX_TOKEN") if os.environ.get("INFLUX_TOKEN") is not None else "my-token"
10+
ORG = os.environ.get("INFLUX_ORG") if os.environ.get("INFLUX_ORG") is not None else "my-org"
11+
SYS_BUCKET = os.environ.get("INFLUX_DB") if os.environ.get("INFLUX_DB") is not None else "my-bucket"
12+
BUCKET = "special-bucket"
13+
14+
15+
def create_auths():
16+
# Create authorizations with an initial client using all-access permissions
17+
with InfluxDBClient(url=HOST_URL, token=TOKEN, org=ORG, debug=False) as globalClient:
18+
bucket_rules = BucketRetentionRules(type="expire", every_seconds=3600)
19+
bucket = globalClient.buckets_api().create_bucket(bucket_name=BUCKET,
20+
retention_rules=bucket_rules,
21+
org=ORG)
22+
23+
bucket_permission_resource_r = PermissionResource(org=ORG,
24+
org_id=bucket.org_id,
25+
type="buckets",
26+
id=bucket.id)
27+
bucket_permission_resource_w = PermissionResource(org=ORG,
28+
org_id=bucket.org_id,
29+
type="buckets",
30+
id=bucket.id)
31+
read_bucket = Permission(action="read", resource=bucket_permission_resource_r)
32+
write_bucket = Permission(action="write", resource=bucket_permission_resource_w)
33+
permissions = [read_bucket, write_bucket]
34+
auth_payload = Authorization(org_id=bucket.org_id,
35+
permissions=permissions,
36+
description="Shared bucket auth from Authorization object",
37+
id="auth1_base")
38+
auth_api = globalClient.authorizations_api()
39+
# use keyword arguments
40+
auth1 = auth_api.create_authorization(authorization=auth_payload)
41+
# or use positional arguments
42+
auth2 = auth_api.create_authorization(bucket.org_id, permissions)
43+
44+
return auth1, auth2
45+
46+
47+
def try_sys_bucket(client):
48+
print("starting to write")
49+
50+
w_api = client.write_api(write_options=WriteOptions(write_type=WriteType.synchronous))
51+
try:
52+
w_api.write(bucket=SYS_BUCKET, record="cpu,host=r2d2 use=3.14")
53+
except ApiException as ae:
54+
print(f"Write to {SYS_BUCKET} failed (as expected) due to:")
55+
print(ae)
56+
57+
58+
def try_restricted_bucket(client):
59+
print("starting to write")
60+
w_api = client.write_api(write_options=WriteOptions(write_type=WriteType.synchronous))
61+
62+
w_api.write(bucket=BUCKET, record="cpu,host=r2d2 usage=3.14")
63+
print("written")
64+
print("now query")
65+
q_api = client.query_api()
66+
query = f'''
67+
from(bucket:"{BUCKET}")
68+
|> range(start: -5m)
69+
|> filter(fn: (r) => r["_measurement"] == "cpu")'''
70+
71+
tables = q_api.query(query=query, org=ORG)
72+
for table in tables:
73+
for record in table.records:
74+
print(record["_time"].isoformat(sep="T") + " | " + record["host"] + " | " + record["_field"] + "=" + str(record["_value"]))
75+
76+
77+
def main():
78+
"""
79+
a1 is generated using a local Authorization instance
80+
a2 is generated using local permissions and an internally created Authorization
81+
:return: void
82+
"""
83+
print("=== Setting up authorizations ===")
84+
a1, a2 = create_auths()
85+
86+
print("=== Using a1 authorization ===")
87+
client1 = InfluxDBClient(url=HOST_URL, token=a1.token, org=ORG, debug=False)
88+
print(" --- Try System Bucket ---")
89+
try_sys_bucket(client1)
90+
print(" --- Try Special Bucket ---")
91+
try_restricted_bucket(client1)
92+
print()
93+
94+
print("=== Using a2 authorization ===")
95+
client2 = InfluxDBClient(url=HOST_URL, token=a2.token, org=ORG, debug=False)
96+
print(" --- Try System Bucket ---")
97+
try_sys_bucket(client2)
98+
print(" --- Try Special Bucket ---")
99+
try_restricted_bucket(client2)
100+
101+
102+
if __name__ == "__main__":
103+
main()

influxdb_client/client/authorizations_api.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ def __init__(self, influxdb_client):
1111
self._influxdb_client = influxdb_client
1212
self._authorizations_service = AuthorizationsService(influxdb_client.api_client)
1313

14-
def create_authorization(self, org_id=None, permissions: list = None,
14+
def create_authorization(self, org_id: str = None, permissions: list = None,
1515
authorization: Authorization = None) -> Authorization:
1616
"""
1717
Create an authorization.
@@ -23,6 +23,8 @@ def create_authorization(self, org_id=None, permissions: list = None,
2323
2424
"""
2525
if authorization is not None:
26+
if not isinstance(authorization, Authorization):
27+
raise TypeError(f"Attempt to use non-Authorization value for authorization: {authorization}")
2628
return self._authorizations_service.post_authorizations(authorization_post_request=authorization)
2729

2830
# if org_id is not None and permissions is not None:

influxdb_client/domain/authorization.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,12 @@ def __init__(self, created_at=None, updated_at=None, org_id=None, permissions=No
8282
if updated_at is not None:
8383
self.updated_at = updated_at
8484
if org_id is not None:
85+
if not isinstance(org_id, str):
86+
raise TypeError("org_id must be a string.")
8587
self.org_id = org_id
8688
if permissions is not None:
89+
if not isinstance(permissions, list):
90+
raise TypeError("permissions must be a list.")
8791
self.permissions = permissions
8892
if id is not None:
8993
self.id = id

tests/test_AuthorizationApi.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,25 @@ def test_createAuthorization(self):
4545

4646
self.assertEqual(authorization.links["user"], "/api/v2/users/" + self.user.id)
4747

48+
def test_AuthorizationTypeAssert(self):
49+
self.assertRaisesRegex(TypeError, "org_id must be a string.", Authorization, org_id={})
50+
self.assertRaisesRegex(TypeError, "permissions must be a list.", Authorization, permissions={})
51+
52+
def test_createAuthorizationWrongTypes(self):
53+
user_resource = PermissionResource(org_id=self.organization.id, type="users")
54+
read_users = Permission(action="read", resource=user_resource)
55+
56+
org_resource = PermissionResource(org_id=self.organization.id, type="orgs")
57+
write_organizations = Permission(action="write", resource=org_resource)
58+
59+
permissions = [read_users, write_organizations]
60+
self.assertRaisesRegex(TypeError, "org_id must be a string.",
61+
self.authorizations_api.create_authorization, permissions)
62+
self.assertRaisesRegex(TypeError, "permissions must be a list",
63+
self.authorizations_api.create_authorization, "123456789ABCDEF0", "Foo")
64+
self.assertRaisesRegex(TypeError, "Attempt to use non-Authorization value for authorization: Foo",
65+
self.authorizations_api.create_authorization, "123456789ABCDEF0", permissions, "Foo")
66+
4867
def test_authorizationDescription(self):
4968
organization = self.my_organization
5069

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy