Skip to content

Commit

Permalink
QA
Browse files Browse the repository at this point in the history
  • Loading branch information
a-belhadj committed Sep 6, 2023
1 parent 3ceefde commit 18cd17f
Show file tree
Hide file tree
Showing 24 changed files with 246 additions and 141 deletions.
8 changes: 6 additions & 2 deletions profiles/api/serializers/quota_serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,12 @@ def validate(self, attrs):
attrs = super().validate(attrs)
scope = self.instance.scope if self.instance else None
scope = attrs['scope'] if 'scope' in attrs.keys() else scope
attribute_definition = attrs.get("attribute_definition")
limit = attrs.get("limit")

attribute_definition = self.instance.attribute_definition if self.instance else None
attribute_definition = attrs['attribute_definition'] if 'attribute_definition' in attrs.keys() else attribute_definition

limit = self.instance.limit if self.instance else None
limit = attrs['limit'] if 'limit' in attrs.keys() else limit

current_quota = Quota.objects.filter(scope=scope, attribute_definition=attribute_definition).first()
current_limit = 0
Expand Down
38 changes: 37 additions & 1 deletion profiles/api/views/quota_api_views.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,49 @@
from Squest.utils.squest_api_views import SquestListCreateAPIView, SquestRetrieveUpdateDestroyAPIView
from rest_framework.exceptions import MethodNotAllowed
from rest_framework.permissions import IsAuthenticated

from Squest.utils.squest_api_views import SquestListCreateAPIView, SquestRetrieveUpdateDestroyAPIView, \
SquestObjectPermissions
from profiles.api.serializers.quota_serializer import QuotaSerializer
from profiles.filters.quota import QuotaFilter
from profiles.models import Quota



class SquestObjectPermissionsQuota(SquestObjectPermissions):
"""
Custom permission to only allow owners of an object to edit it.
"""
perms_map = {
'GET': ['%(app_label)s.view_%(model_name)s'],
'OPTIONS': [],
'HEAD': [],
'PUT': ['%(app_label)s.change_%(scope)s_%(model_name)s'],
'PATCH': ['%(app_label)s.change_%(scope)s_%(model_name)s'],
'DELETE': ['%(app_label)s.delete_%(model_name)s'],
}

def get_required_object_permissions(self, method, model_cls, obj=None):
scope = obj.scope
if scope.is_team:
scope_str = "team"
elif scope.is_org:
scope_str = "organization"
kwargs = {
'app_label': model_cls._meta.app_label,
'model_name': model_cls._meta.model_name,
'scope': scope_str
}

if method not in self.perms_map:
raise MethodNotAllowed(method)

return [perm % kwargs for perm in self.perms_map[method]]


class QuotaDetails(SquestRetrieveUpdateDestroyAPIView):
serializer_class = QuotaSerializer
queryset = Quota.objects.all()
permission_classes = [IsAuthenticated, SquestObjectPermissionsQuota]



Expand Down
4 changes: 2 additions & 2 deletions profiles/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ def create_roles(sender, **kwargs):
from profiles.default_rbac.default_roles import default_roles
from profiles.models.squest_permission import Permission

role_migration_filter = Role.objects.filter(name="Organization member migration/0014_auto_20230622_1722")
role_migration_filter = Role.objects.filter(name="Squest user migration/0014_auto_20230622_1722")
if role_migration_filter.exists():
role_migration = role_migration_filter.first()
role_migration.name = "Organization member"
role_migration.name = "Squest user"
role_migration.save()
codenames = list(
map(lambda default_permissions: default_permissions.split('.')[1],
Expand Down
96 changes: 17 additions & 79 deletions profiles/default_rbac/default_roles.py
Original file line number Diff line number Diff line change
@@ -1,104 +1,42 @@
default_roles = {
"Organization member": {
"Squest user": {
"description": "Can view organization",
"permissions": [
"profiles.consume_quota_scope"
"service_catalog.request_on_instance",
"service_catalog.request_on_service",

"profiles.view_organization"
]
},
"Team member": {
"description": "Can view team",
"permissions": [
"profiles.view_team",
]
},
"Organization manager": {
"description": "Can view and manage Organization's users.",
"permissions": [
"profiles.view_organization",
"profiles.view_users_organization",
"profiles.add_users_organization",
"profiles.delete_users_organization",

"profiles.view_team",
"profiles.add_team",
"profiles.view_team",
"profiles.change_team",
"profiles.delete_team",

"profiles.view_users_team",
"profiles.add_users_team",
"profiles.delete_users_team",
]
},
"Team manager": {
"description": "Can view and manage Team's users.",
"permissions": [
"profiles.view_team",
"profiles.view_users_team",
"profiles.add_users_team",
"profiles.delete_users_team",
]
},
"Instance viewer": {
"description": "Can view Instance and all related objects.",
"permissions": [
"service_catalog.view_instance",
"service_catalog.view_request",
"service_catalog.view_requestmessage",
"service_catalog.view_supportmessage",
"service_catalog.view_support",

]
},
"Catalog user": {
"description": "Can request services in catalog",
"permissions": [
"profiles.consume_quota_scope"
]
},
"Instance Operator": {
"description": "Can request services and day 2 operations",
"permissions": [
"profiles.consume_quota_scope"

"service_catalog.view_instance",
"service_catalog.view_request",
"service_catalog.view_requestmessage",
"service_catalog.view_supportmessage",
"service_catalog.view_support",

"service_catalog.request_on_instance",
"service_catalog.request_on_service",
"service_catalog.view_request",
"service_catalog.cancel_request",

"service_catalog.add_message",
"service_catalog.view_message",
"service_catalog.change_message",
"service_catalog.delete_message",

"service_catalog.add_message",
"service_catalog.view_message",
"service_catalog.change_message",
"service_catalog.delete_message",
"service_catalog.view_requestmessage",
"service_catalog.add_requestmessage",
"service_catalog.change_requestmessage",

"service_catalog.view_support",
"service_catalog.add_support",
"service_catalog.view_support",
"service_catalog.change_support",

]
},
"Workflow approver": {
"description": "Can approve a step (for Approval Workflow only)",
"permissions": [
"service_catalog.approve_request_approvalstep",
"service_catalog.view_admin_fill_in_survey"
"service_catalog.view_supportmessage",
"service_catalog.add_supportmessage",
"service_catalog.change_supportmessage",

"profiles.view_quota",
]
},
"Request approver": {
"description": "Can approve a request",
"permissions": [
"service_catalog.accept_request",
"service_catalog.view_admin_fill_in_survey"
]
},

}
}
17 changes: 17 additions & 0 deletions profiles/migrations/0019_alter_quota_options.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 3.2.13 on 2023-09-05 14:48

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('profiles', '0018_auto_20230803_1126'),
]

operations = [
migrations.AlterModelOptions(
name='quota',
options={'default_permissions': ('add', 'delete', 'view', 'list'), 'permissions': [('change_team_quota', 'Can change quota at team level'), ('change_organization_quota', 'Can change quota at organization level')]},
),
]
7 changes: 6 additions & 1 deletion profiles/models/quota.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@
class Quota(SquestModel):
class Meta:
unique_together = ('scope', 'attribute_definition')
default_permissions = ('add', 'change', 'delete', 'view', 'list')
default_permissions = ('add', 'delete', 'view', 'list')

permissions = [
("change_team_quota", "Can change quota at team level"),
("change_organization_quota", "Can change quota at organization level"),
]

scope = ForeignKey("Scope",
blank=False,
Expand Down
3 changes: 1 addition & 2 deletions profiles/tables/organization_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@ class Meta:

def render_users(self, value, record):
link = reverse("profiles:organization_details", kwargs={'pk': record.id})
return format_html(f'<a href="{link}#rbac" class="btn btn-default bg-sm">{record.users.count()}</a>')
return format_html(f'<a href="{link}#users" class="btn btn-default bg-sm">{record.users.count()}</a>')

def render_teams(self, value, record):
link = reverse("profiles:organization_details", kwargs={'pk': record.id})
return format_html(f'<a href="{link}#teams" class="btn btn-default bg-sm">{record.teams.count()}</a>')

4 changes: 2 additions & 2 deletions profiles/tables/team_quota_limit_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@


class TeamQuotaLimitTable(Table):

scope = LinkColumn()
limit = LinkColumn()
consumed = LinkColumn()

class Meta:
model = Quota
attrs = {"id": "quota_team_table", "class": "table squest-pagination-tables"}
fields = ("scope", "limit")
fields = ("scope", "limit", "consumed")
2 changes: 1 addition & 1 deletion profiles/tables/team_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class Meta:

def render_users(self, value, record):
link = reverse("profiles:team_details", kwargs={'pk': record.id})
return format_html(f'<a href="{link}#rbac" class="btn btn-default bg-sm">{record.users.count()}</a>')
return format_html(f'<a href="{link}#users" class="btn btn-default bg-sm">{record.users.count()}</a>')


class TeamUserTable(SquestTable):
Expand Down
11 changes: 7 additions & 4 deletions profiles/templatetags/squest_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ def generate_sidebar(user):
'name': 'Global permission',
'view_name': 'profiles:globalpermission_rbac',
'icon': 'fas fa-globe',
'permission_required': 'profiles.can_view_globalpermission',
'permission_required': 'profiles.view_users_globalpermission',
'active': [
"globalpermission_rbac", "globalpermission_rbac_create", "globalpermission_rbac_delete"
]
Expand Down Expand Up @@ -176,7 +176,7 @@ def generate_sidebar(user):
'name': 'Users',
'view_name': 'profiles:user_list',
'icon': 'fas fa-user-friends',
'permission_required': 'profiles.list_team',
'permission_required': 'profiles.list_user',
'active': [
"user_list", "user_details"
]
Expand Down Expand Up @@ -280,10 +280,12 @@ def generate_sidebar(user):
group_items = list()

for view in views:
user_has_perm = False
view_data_copy = copy.deepcopy(view)
if "treeview_items" not in view:
view_permission = view.get('permission_required', None)
if (view_permission is None) or (view_permission is not None and user.has_perm(view_permission)):
user_has_perm = True
is_group_visible = True
else:
view_data_copy["active"] = list()
Expand All @@ -293,11 +295,12 @@ def generate_sidebar(user):
view_data_copy["active"] += child_view_data_copy["active"]
view_permission = child_view.get('permission_required', None)
if (view_permission is None) or (view_permission is not None and user.has_perm(view_permission)):
user_has_perm = True
is_group_visible = True
child_group.append(child_view_data_copy)
view_data_copy["treeview_items"] = child_group

group_items.append(view_data_copy)
if user_has_perm:
group_items.append(view_data_copy)

if is_group_visible:
sidebar_menu[group_name] = group_items
Expand Down
12 changes: 11 additions & 1 deletion profiles/views/quota.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from django.core.exceptions import ImproperlyConfigured
from django.db.models import Sum
from django.shortcuts import get_object_or_404
from django_tables2 import RequestConfig
Expand Down Expand Up @@ -32,7 +33,16 @@ class QuotaEditView(SquestFormView):
pk_url_kwarg = "scope_id"

def get_permission_required(self):
return f"profiles.change_quota"
object = self.get_object()
if object.is_team:
return "profiles.change_team_quota"
elif object.is_org:
return f"profiles.change_organization_quota"
else:
raise ImproperlyConfigured(
'{0} is missing the permission_required attribute. Define {0}.permission_required, or override '
'{0}.get_permission_required().'.format(self.__class__.__name__)
)

def get_success_url(self):
return self.scope.get_absolute_url() + "#quotas"
Expand Down
2 changes: 1 addition & 1 deletion project-static/squest/js/squest.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ function add_tab_management() {
if (hash) {
$('ul#tabs.squest-default-active li.nav-item a[href="' + hash + '"]').trigger('click');
} else {
$("ul#tabs.squest-default-active li.nav-item a:first").trigger("click");
$("ul#tabs.squest-default-active li.nav-item a:first").tab("show");
}
}

Expand Down
3 changes: 1 addition & 2 deletions service_catalog/management/commands/insert_testing_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@ def handle(self, *args, **options):
organization.append(Organization.objects.get_or_create(name=billing_group)[0])


Organization.objects.get(name="Orchestration").add_user_in_role(User.objects.get(username="Anthony"),Role.objects.get(name="Organization member"))
Organization.objects.get(name="Orchestration").add_user_in_role(User.objects.get(username="Anthony"),Role.objects.get(name="Instance viewer"))
Organization.objects.get(name="Orchestration").add_user_in_role(User.objects.get(username="Anthony"),Role.objects.get(name="Squest user"))

job_templates = JobTemplate.objects.all()
services = dict()
Expand Down
2 changes: 1 addition & 1 deletion service_catalog/migrations/0014_auto_20230622_1722.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
def billing_group_to_org(apps, schema_editor):
Role = apps.get_model('profiles', 'Role')
role_org_member, _ = Role.objects.get_or_create(
name="Organization member migration/0014_auto_20230622_1722",
name="Squest user migration/0014_auto_20230622_1722",
defaults={'description': 'Can view organization'},
)
BillingGroup = apps.get_model('profiles', 'BillingGroup')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@
<div class="col-12">
<div class="card">
<div class="card-body">
<div class="alert alert-info alert-dismissible">
<i class="icon fas fa-info"></i>
<div class="callout callout-info">
List of permissions granted to all users
</div>
{% render_table default_permissions %}
Expand Down
Loading

0 comments on commit 18cd17f

Please sign in to comment.