mirror of
https://github.com/ansible/awx.git
synced 2024-10-31 23:51:09 +03:00
Add permissions checks for the organization host limit
This commit is contained in:
parent
0e8e5f65e1
commit
36ed890c14
@ -330,6 +330,25 @@ class BaseAccess(object):
|
||||
elif "features" not in validation_info:
|
||||
raise LicenseForbids(_("Features not found in active license."))
|
||||
|
||||
def check_org_host_limit(self, data, add_host_name=None):
|
||||
validation_info = get_licenser().validate()
|
||||
if validation_info.get('license_type', 'UNLICENSED') == 'open':
|
||||
return
|
||||
|
||||
inventory = get_object_from_data('inventory', Inventory, data)
|
||||
org = inventory.organization
|
||||
if org is None or org.max_hosts == 0:
|
||||
return
|
||||
|
||||
active_count = Host.objects.org_active_count(org.id)
|
||||
if active_count > org.max_hosts:
|
||||
raise PermissionDenied(_("Organization host limit of %s has been exceeded.") % org.max_hosts)
|
||||
|
||||
if add_host_name:
|
||||
host_exists = Host.objects.filter(inventory__organization=org.id, name=add_host_name).exists()
|
||||
if not host_exists and active_count == org.max_hosts:
|
||||
raise PermissionDenied(_("Organization host limit of %s has been reached.") % org.max_hosts)
|
||||
|
||||
def get_user_capabilities(self, obj, method_list=[], parent_obj=None, capabilities_cache={}):
|
||||
if obj is None:
|
||||
return {}
|
||||
@ -360,7 +379,7 @@ class BaseAccess(object):
|
||||
user_capabilities[display_method] = self.user.is_superuser
|
||||
continue
|
||||
elif display_method == 'copy' and isinstance(obj, Project) and obj.scm_type == '':
|
||||
# Connot copy manual project without errors
|
||||
# Cannot copy manual project without errors
|
||||
user_capabilities[display_method] = False
|
||||
continue
|
||||
elif display_method in ['start', 'schedule'] and isinstance(obj, Group): # TODO: remove in 3.3
|
||||
@ -628,7 +647,7 @@ class OAuth2ApplicationAccess(BaseAccess):
|
||||
return self.model.objects.filter(organization__in=org_access_qs)
|
||||
|
||||
def can_change(self, obj, data):
|
||||
return self.user.is_superuser or self.check_related('organization', Organization, data, obj=obj,
|
||||
return self.user.is_superuser or self.check_related('organization', Organization, data, obj=obj,
|
||||
role_field='admin_role', mandatory=True)
|
||||
|
||||
def can_delete(self, obj):
|
||||
@ -636,7 +655,7 @@ class OAuth2ApplicationAccess(BaseAccess):
|
||||
|
||||
def can_add(self, data):
|
||||
if self.user.is_superuser:
|
||||
return True
|
||||
return True
|
||||
if not data:
|
||||
return Organization.accessible_objects(self.user, 'admin_role').exists()
|
||||
return self.check_related('organization', Organization, data, role_field='admin_role', mandatory=True)
|
||||
@ -650,29 +669,29 @@ class OAuth2TokenAccess(BaseAccess):
|
||||
- I am the user of the token.
|
||||
I can create an OAuth2 app token when:
|
||||
- I have the read permission of the related application.
|
||||
I can read, change or delete a personal token when:
|
||||
I can read, change or delete a personal token when:
|
||||
- I am the user of the token
|
||||
- I am the superuser
|
||||
I can create an OAuth2 Personal Access Token when:
|
||||
- I am a user. But I can only create a PAT for myself.
|
||||
- I am a user. But I can only create a PAT for myself.
|
||||
'''
|
||||
|
||||
model = OAuth2AccessToken
|
||||
|
||||
|
||||
select_related = ('user', 'application')
|
||||
|
||||
def filtered_queryset(self):
|
||||
|
||||
def filtered_queryset(self):
|
||||
org_access_qs = Organization.objects.filter(
|
||||
Q(admin_role__members=self.user) | Q(auditor_role__members=self.user))
|
||||
return self.model.objects.filter(application__organization__in=org_access_qs) | self.model.objects.filter(user__id=self.user.pk)
|
||||
|
||||
|
||||
def can_delete(self, obj):
|
||||
if (self.user.is_superuser) | (obj.user == self.user):
|
||||
return True
|
||||
elif not obj.application:
|
||||
return False
|
||||
return self.user in obj.application.organization.admin_role
|
||||
|
||||
|
||||
def can_change(self, obj, data):
|
||||
return self.can_delete(obj)
|
||||
|
||||
@ -840,6 +859,10 @@ class HostAccess(BaseAccess):
|
||||
|
||||
# Check to see if we have enough licenses
|
||||
self.check_license(add_host_name=data.get('name', None))
|
||||
|
||||
# Check the per-org limit
|
||||
self.check_org_host_limit(data, add_host_name=data.get('name', None))
|
||||
|
||||
return True
|
||||
|
||||
def can_change(self, obj, data):
|
||||
@ -852,6 +875,9 @@ class HostAccess(BaseAccess):
|
||||
if data and 'name' in data:
|
||||
self.check_license(add_host_name=data['name'])
|
||||
|
||||
# Check the per-org limit
|
||||
self.check_org_host_limit(data, add_host_name=data['name'])
|
||||
|
||||
# Checks for admin or change permission on inventory, controls whether
|
||||
# the user can edit variable data.
|
||||
return obj and self.user in obj.inventory.admin_role
|
||||
@ -1346,7 +1372,7 @@ class JobTemplateAccess(BaseAccess):
|
||||
return self.user in project.use_role
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
@check_superuser
|
||||
def can_copy_related(self, obj):
|
||||
'''
|
||||
@ -1362,6 +1388,10 @@ class JobTemplateAccess(BaseAccess):
|
||||
# Check license.
|
||||
if validate_license:
|
||||
self.check_license()
|
||||
|
||||
# Check the per-org limit
|
||||
self.check_org_host_limit({'inventory': obj})
|
||||
|
||||
if obj.survey_enabled:
|
||||
self.check_license(feature='surveys')
|
||||
if Instance.objects.active_count() > 1:
|
||||
@ -1520,6 +1550,9 @@ class JobAccess(BaseAccess):
|
||||
if validate_license:
|
||||
self.check_license()
|
||||
|
||||
# Check the per-org limit
|
||||
self.check_org_host_limit({'inventory': obj})
|
||||
|
||||
# A super user can relaunch a job
|
||||
if self.user.is_superuser:
|
||||
return True
|
||||
@ -1886,6 +1919,10 @@ class WorkflowJobTemplateAccess(BaseAccess):
|
||||
if validate_license:
|
||||
# check basic license, node count
|
||||
self.check_license()
|
||||
|
||||
# Check the per-org limit
|
||||
self.check_org_host_limit({'inventory': obj})
|
||||
|
||||
# if surveys are added to WFJTs, check license here
|
||||
if obj.survey_enabled:
|
||||
self.check_license(feature='surveys')
|
||||
@ -1957,6 +1994,9 @@ class WorkflowJobAccess(BaseAccess):
|
||||
if validate_license:
|
||||
self.check_license()
|
||||
|
||||
# Check the per-org limit
|
||||
self.check_org_host_limit({'inventory': obj})
|
||||
|
||||
if self.user.is_superuser:
|
||||
return True
|
||||
|
||||
@ -2033,6 +2073,9 @@ class AdHocCommandAccess(BaseAccess):
|
||||
if validate_license:
|
||||
self.check_license()
|
||||
|
||||
# Check the per-org limit
|
||||
self.check_org_host_limit(data)
|
||||
|
||||
# If a credential is provided, the user should have use access to it.
|
||||
if not self.check_related('credential', Credential, data, role_field='use_role'):
|
||||
return False
|
||||
@ -2442,7 +2485,7 @@ class ActivityStreamAccess(BaseAccess):
|
||||
model = ActivityStream
|
||||
prefetch_related = ('organization', 'user', 'inventory', 'host', 'group',
|
||||
'inventory_update', 'credential', 'credential_type', 'team',
|
||||
'ad_hoc_command', 'o_auth2_application', 'o_auth2_access_token',
|
||||
'ad_hoc_command', 'o_auth2_application', 'o_auth2_access_token',
|
||||
'notification_template', 'notification', 'label', 'role', 'actor',
|
||||
'schedule', 'custom_inventory_script', 'unified_job_template',
|
||||
'workflow_job_template_node',)
|
||||
|
Loading…
Reference in New Issue
Block a user