Skip to content

Commit 49a65ab

Browse files
committed
Improve grant and revoke to work on models, offers and controllers
As opposed to only changing the controller access level
1 parent bdb2e27 commit 49a65ab

1 file changed

Lines changed: 101 additions & 10 deletions

File tree

juju/user.py

Lines changed: 101 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
import pyrfc3339
44

5-
from . import tag
5+
from . import tag, errors
6+
from .client import client
67

78
log = logging.getLogger(__name__)
89

@@ -31,6 +32,7 @@ def last_connection(self):
3132

3233
@property
3334
def access(self):
35+
"""Identifies the controller access levels of this user"""
3436
return self._user_info.access
3537

3638
@property
@@ -59,19 +61,108 @@ async def set_password(self, password):
5961
await self.controller.change_user_password(self.username, password)
6062
self._user_info.password = password
6163

62-
async def grant(self, acl='login'):
63-
"""Set access level of this user on the controller.
64+
async def modify_model_access(self, acl, action, model_name):
65+
"""Grants or revokes the given access level for this user for a given model
6466
65-
:param str acl: Access control ('login', 'add-model', or 'superuser')
67+
:param str acl: Model access levels (see access module)
68+
:param str action: grant/revoke
69+
:param str model_name: Name of the model
70+
71+
:return bool: True if access changed, Error if user already has it
72+
"""
73+
modelmanager_facade = client.ModelManagerFacade.from_connection(
74+
self.controller.connection())
75+
models = await self.controller.model_uuids()
76+
if model_name not in models:
77+
raise errors.JujuError(f'Unable to find model : {model_name}')
78+
changes = client.ModifyModelAccess(acl, action, tag.model(models[model_name]), self.tag)
79+
await modelmanager_facade.ModifyModelAccess(changes=[changes])
80+
return True
81+
82+
async def modify_controller_access(self, acl, action):
83+
"""Grants or revokes the given access level for this user on the current controller
84+
85+
:param str acl: Controller access levels (see access module)
86+
:param str action: grant/revoke
87+
88+
:return bool: True if access changed, Error if user already has it
89+
"""
90+
controller_facade = client.ControllerFacade.from_connection(self.controller.connection())
91+
changes = client.ModifyControllerAccess(acl, action, self.tag)
92+
await controller_facade.ModifyControllerAccess(changes=[changes])
93+
94+
new_access = acl
95+
if action == 'revoke':
96+
new_access = ''
97+
self._user_info.access = new_access
98+
return True
99+
100+
async def modify_offer_access(self, acl, action, offer_url):
101+
"""Grants or revokes the given access level for this user on a given offer
102+
103+
:param str acl: Controller access levels (see access module)
104+
:param str action: grant/revoke
105+
:param str offer_url: url for the offer
106+
107+
:return bool: True if access changed, Error if user already has it
66108
"""
67-
if await self.controller.grant(self.username, acl):
68-
self._user_info.access = acl
109+
application_offers_facade = client.ApplicationOffersFacade.from_connection(
110+
self.controller.connection())
111+
changes = client.ModifyOfferAccess(acl, action, offer_url, self.tag)
112+
await application_offers_facade.ModifyOfferAccess(changes=[changes])
113+
return True
114+
115+
async def grant_or_revoke(self, acl, action, **kwargs):
116+
"""Grants or revokes the given access level of this user on model, offer or controller,
117+
depending on the access level (see the access module)
118+
119+
:param str acl: Access control level
120+
:param str action: 'grant' or 'revoke'
121+
122+
Depending on the access level, the available keyword parameters are:
123+
:param str model_name: name of the model if acl is one of model access levels
124+
:param str offer_url: url for the offer if acl is one of offer access levels
125+
126+
:return: True if access changed, False if user already has it
127+
"""
128+
try:
129+
if 'model_name' in kwargs:
130+
return await self.modify_model_access(acl, action, kwargs['model_name'])
131+
elif 'offer_url' in kwargs:
132+
return await self.modify_offer_access(acl, action, kwargs['offer_url'])
133+
else:
134+
return await self.modify_controller_access(acl, action)
135+
except errors.JujuError as e:
136+
if 'user already has' in str(e):
137+
return False
138+
else:
139+
raise
140+
141+
async def grant(self, acl, **kwargs):
142+
"""Grant the given access level of this user on model, offer or controller, depending on
143+
the access level (see the access module)
144+
145+
:param str acl: Access control level
146+
147+
Depending on the access level, the available keyword parameters are:
148+
:param str model_name: name of the model if acl is one of model access levels
149+
:param str offer_url: url for the offer if acl is one of offer access levels
150+
151+
:return: None or Error
152+
"""
153+
return await self.grant_or_revoke(acl, 'grant', **kwargs)
154+
155+
async def revoke(self, acl='login', **kwargs):
156+
"""The opposite of user.grant(). Revokes the given access level of this user on model,
157+
offer or controller, depending on the given access level.
158+
159+
:param str acl: Access control level (see access module)
69160
70-
async def revoke(self, acl='login'):
71-
"""Removes all access rights for this user from the controller.
161+
Available keyword parameters are:
162+
:param str model_name: name of the model if acl is one of model access levels
163+
:param str offer_url: url for the offer if acl is one of offer access levels
72164
"""
73-
await self.controller.revoke(self.username, acl)
74-
self._user_info.access = ''
165+
return await self.grant_or_revoke(acl, 'revoke', **kwargs)
75166

76167
async def disable(self):
77168
"""Disable this user.

0 commit comments

Comments
 (0)