Skip to content
This repository was archived by the owner on Dec 16, 2025. It is now read-only.

Commit 0ed5bbe

Browse files
Permissions module (#205)
* Add Permissions for API resources * Add proper error handling * Add tests for Permissions module * Update documentation * Format with black * Rename get_permission to get. * Move create_permission checks moved create_permission checks to _make_create_permission_request * Restrict update_paths to ole for Permission. * Restrict update_paths to ole for Permission. * update tests * Format with black * Update test cases make enum constructs redable
1 parent 5e9ff4f commit 0ed5bbe

File tree

6 files changed

+826
-0
lines changed

6 files changed

+826
-0
lines changed

google/generativeai/client.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,3 +251,11 @@ def get_default_retriever_client() -> glm.RetrieverClient:
251251

252252
def get_default_retriever_async_client() -> glm.RetrieverAsyncClient:
253253
return _client_manager.get_default_client("retriever_async")
254+
255+
256+
def get_dafault_permission_client() -> glm.PermissionServiceClient:
257+
return _client_manager.get_default_client("permission")
258+
259+
260+
def get_dafault_permission_async_client() -> glm.PermissionServiceAsyncClient:
261+
return _client_manager.get_default_client("permission_async")

google/generativeai/permission.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# -*- coding: utf-8 -*-
2+
# Copyright 2024 Google LLC
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
from __future__ import annotations
16+
17+
import google.ai.generativelanguage as glm
18+
19+
from google.generativeai.types import permission_types
20+
21+
22+
def get_permission(
23+
name: str,
24+
client: glm.PermissionServiceClient | None = None,
25+
) -> permission_types.Permission:
26+
"""Get a permission by name.
27+
28+
Args:
29+
name: The name of the permission.
30+
31+
Returns:
32+
The permission as an instance of `permission_types.Permission`.
33+
"""
34+
return permission_types.Permission.get(name=name, client=client)
35+
36+
37+
async def get_permission_async(
38+
name: str,
39+
client: glm.PermissionServiceAsyncClient | None = None,
40+
) -> permission_types.Permission:
41+
"""
42+
This is the async version of `permission.get_permission`.
43+
"""
44+
return await permission_types.Permission.get_async(name=name, client=client)
Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
# -*- coding: utf-8 -*-
2+
# Copyright 2024 Google LLC
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
from __future__ import annotations
16+
17+
import dataclasses
18+
from typing import Optional, Union, Any
19+
20+
import google.ai.generativelanguage as glm
21+
22+
from google.protobuf import field_mask_pb2
23+
24+
from google.generativeai.client import get_dafault_permission_client
25+
from google.generativeai.client import get_dafault_permission_async_client
26+
from google.generativeai.utils import flatten_update_paths
27+
from google.generativeai import string_utils
28+
29+
30+
GranteeType = glm.Permission.GranteeType
31+
Role = glm.Permission.Role
32+
33+
GranteeTypeOptions = Union[str, int, GranteeType]
34+
RoleOptions = Union[str, int, Role]
35+
36+
_GRANTEE_TYPE: dict[GranteeTypeOptions, GranteeType] = {
37+
GranteeType.GRANTEE_TYPE_UNSPECIFIED: GranteeType.GRANTEE_TYPE_UNSPECIFIED,
38+
0: GranteeType.GRANTEE_TYPE_UNSPECIFIED,
39+
"grantee_type_unspecified": GranteeType.GRANTEE_TYPE_UNSPECIFIED,
40+
"unspecified": GranteeType.GRANTEE_TYPE_UNSPECIFIED,
41+
GranteeType.USER: GranteeType.USER,
42+
1: GranteeType.USER,
43+
"user": GranteeType.USER,
44+
GranteeType.GROUP: GranteeType.GROUP,
45+
2: GranteeType.GROUP,
46+
"group": GranteeType.GROUP,
47+
GranteeType.EVERYONE: GranteeType.EVERYONE,
48+
3: GranteeType.EVERYONE,
49+
"everyone": GranteeType.EVERYONE,
50+
}
51+
52+
_ROLE: dict[RoleOptions, Role] = {
53+
Role.ROLE_UNSPECIFIED: Role.ROLE_UNSPECIFIED,
54+
0: Role.ROLE_UNSPECIFIED,
55+
"role_unspecified": Role.ROLE_UNSPECIFIED,
56+
"unspecified": Role.ROLE_UNSPECIFIED,
57+
Role.OWNER: Role.OWNER,
58+
1: Role.OWNER,
59+
"owner": Role.OWNER,
60+
Role.WRITER: Role.WRITER,
61+
2: Role.WRITER,
62+
"writer": Role.WRITER,
63+
Role.READER: Role.READER,
64+
3: Role.READER,
65+
"reader": Role.READER,
66+
}
67+
68+
69+
def to_grantee_type(x: GranteeTypeOptions) -> GranteeType:
70+
if isinstance(x, str):
71+
x = x.lower()
72+
return _GRANTEE_TYPE[x]
73+
74+
75+
def to_role(x: RoleOptions) -> Role:
76+
if isinstance(x, str):
77+
x = x.lower()
78+
return _ROLE[x]
79+
80+
81+
@string_utils.prettyprint
82+
@dataclasses.dataclass
83+
class Permission:
84+
"""
85+
A permission to access a resource.
86+
"""
87+
88+
name: str
89+
role: Role
90+
grantee_type: Optional[GranteeType]
91+
email_address: Optional[str] = None
92+
93+
def delete(
94+
self,
95+
client: glm.PermissionServiceClient | None = None,
96+
) -> None:
97+
"""
98+
Delete permission (self).
99+
"""
100+
if client is None:
101+
client = get_dafault_permission_client()
102+
delete_request = glm.DeletePermissionRequest(name=self.name)
103+
client.delete_permission(request=delete_request)
104+
105+
async def delete_async(
106+
self,
107+
client: glm.PermissionServiceAsyncClient | None = None,
108+
) -> None:
109+
"""
110+
This is the async version of `Permission.delete`.
111+
"""
112+
if client is None:
113+
client = get_dafault_permission_async_client()
114+
delete_request = glm.DeletePermissionRequest(name=self.name)
115+
await client.delete_permission(request=delete_request)
116+
117+
# TODO (magashe): Add a method to validate update value. As of now only `role` is supported as a mask path
118+
def _apply_update(self, path, value):
119+
parts = path.split(".")
120+
for part in parts[:-1]:
121+
self = getattr(self, part)
122+
setattr(self, parts[-1], value)
123+
124+
def update(
125+
self,
126+
updates: dict[str, Any],
127+
client: glm.PermissionServiceClient | None = None,
128+
) -> Permission:
129+
"""
130+
Update a list of fields for a specified permission.
131+
132+
Args:
133+
updates: The list of fields to update.
134+
Currently only `role` is supported as an update path.
135+
136+
Returns:
137+
`Permission` object with specified updates.
138+
"""
139+
if client is None:
140+
client = get_dafault_permission_client()
141+
142+
updates = flatten_update_paths(updates)
143+
for update_path in updates:
144+
if update_path != "role":
145+
raise ValueError(
146+
f"As of now, only `role` can be updated for `Permission`. Got: `{update_path}` instead."
147+
)
148+
field_mask = field_mask_pb2.FieldMask()
149+
150+
for path in updates.keys():
151+
field_mask.paths.append(path)
152+
for path, value in updates.items():
153+
self._apply_update(path, value)
154+
155+
update_request = glm.UpdatePermissionRequest(
156+
permission=self.to_dict(), update_mask=field_mask
157+
)
158+
client.update_permission(request=update_request)
159+
return self
160+
161+
async def update_async(
162+
self,
163+
updates: dict[str, Any],
164+
client: glm.PermissionServiceAsyncClient | None = None,
165+
) -> Permission:
166+
"""
167+
This is the async version of `Permission.update`.
168+
"""
169+
if client is None:
170+
client = get_dafault_permission_async_client()
171+
172+
updates = flatten_update_paths(updates)
173+
for update_path in updates:
174+
if update_path != "role":
175+
raise ValueError(
176+
f"As of now, only `role` can be updated for `Permission`. Got: `{update_path}` instead."
177+
)
178+
field_mask = field_mask_pb2.FieldMask()
179+
180+
for path in updates.keys():
181+
field_mask.paths.append(path)
182+
for path, value in updates.items():
183+
self._apply_update(path, value)
184+
185+
update_request = glm.UpdatePermissionRequest(
186+
permission=self.to_dict(), update_mask=field_mask
187+
)
188+
await client.update_permission(request=update_request)
189+
return self
190+
191+
def to_dict(self) -> dict[str, Any]:
192+
return {
193+
"name": self.name,
194+
"role": self.role,
195+
"grantee_type": self.grantee_type,
196+
"email_address": self.email_address,
197+
}
198+
199+
@classmethod
200+
def get(
201+
cls,
202+
name: str,
203+
client: glm.PermissionServiceClient | None = None,
204+
) -> Permission:
205+
"""
206+
Get information about a specific permission.
207+
208+
Args:
209+
name: The name of the permission to get.
210+
211+
Returns:
212+
Requested permission as an instance of `Permission`.
213+
"""
214+
if client is None:
215+
client = get_dafault_permission_client()
216+
get_perm_request = glm.GetPermissionRequest(name=name)
217+
get_perm_response = client.get_permission(request=get_perm_request)
218+
get_perm_response = type(get_perm_response).to_dict(get_perm_response)
219+
return cls(**get_perm_response)
220+
221+
@classmethod
222+
async def get_async(
223+
cls,
224+
name: str,
225+
client: glm.PermissionServiceAsyncClient | None = None,
226+
) -> Permission:
227+
"""
228+
This is the async version of `Permission.get`.
229+
"""
230+
if client is None:
231+
client = get_dafault_permission_async_client()
232+
get_perm_request = glm.GetPermissionRequest(name=name)
233+
get_perm_response = await client.get_permission(request=get_perm_request)
234+
get_perm_response = type(get_perm_response).to_dict(get_perm_response)
235+
return cls(**get_perm_response)

0 commit comments

Comments
 (0)