Merge pull request #4704 from FinnStutzenstein/setPermissionRequest
Request for settings a permission in a group (closes #4698)
This commit is contained in:
commit
65dbf37106
@ -9,6 +9,7 @@ import { Group } from 'app/shared/models/users/group';
|
|||||||
import { ViewGroup } from 'app/site/users/models/view-group';
|
import { ViewGroup } from 'app/site/users/models/view-group';
|
||||||
import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service';
|
import { ViewModelStoreService } from 'app/core/core-services/view-model-store.service';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
import { HttpService } from 'app/core/core-services/http.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shape of a permission
|
* Shape of a permission
|
||||||
@ -53,7 +54,8 @@ export class GroupRepositoryService extends BaseRepository<ViewGroup, Group> {
|
|||||||
mapperService: CollectionStringMapperService,
|
mapperService: CollectionStringMapperService,
|
||||||
viewModelStoreService: ViewModelStoreService,
|
viewModelStoreService: ViewModelStoreService,
|
||||||
translate: TranslateService,
|
translate: TranslateService,
|
||||||
private constants: ConstantsService
|
private constants: ConstantsService,
|
||||||
|
private http: HttpService
|
||||||
) {
|
) {
|
||||||
super(DS, dataSend, mapperService, viewModelStoreService, translate, Group);
|
super(DS, dataSend, mapperService, viewModelStoreService, translate, Group);
|
||||||
this.sortPermsPerApp();
|
this.sortPermsPerApp();
|
||||||
@ -69,6 +71,20 @@ export class GroupRepositoryService extends BaseRepository<ViewGroup, Group> {
|
|||||||
return viewGroup;
|
return viewGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggles the given permisson.
|
||||||
|
*
|
||||||
|
* @param group The group
|
||||||
|
* @param perm The permission to toggle
|
||||||
|
*/
|
||||||
|
public async togglePerm(group: ViewGroup, perm: string): Promise<void> {
|
||||||
|
const set = !group.permissions.includes(perm);
|
||||||
|
return await this.http.post(`rest/${group.collectionString}/${group.id}/set_permission/`, {
|
||||||
|
perm: perm,
|
||||||
|
set: set
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add an entry to appPermissions
|
* Add an entry to appPermissions
|
||||||
*
|
*
|
||||||
|
@ -153,8 +153,7 @@ export class GroupListComponent extends BaseViewComponent implements OnInit {
|
|||||||
* @param perm
|
* @param perm
|
||||||
*/
|
*/
|
||||||
public togglePerm(viewGroup: ViewGroup, perm: string): void {
|
public togglePerm(viewGroup: ViewGroup, perm: string): void {
|
||||||
const updateData = new Group({ permissions: viewGroup.getAlteredPermissions(perm) });
|
this.repo.togglePerm(viewGroup, perm);
|
||||||
this.repo.update(updateData, viewGroup).then(null, this.raiseError);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -41,33 +41,6 @@ export class ViewGroup extends BaseViewModel {
|
|||||||
this._group = group;
|
this._group = group;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an array of permissions where the given perm is included
|
|
||||||
* or removed.
|
|
||||||
*
|
|
||||||
* Avoids touching the local DataStore.
|
|
||||||
*
|
|
||||||
* @param perm
|
|
||||||
*/
|
|
||||||
public getAlteredPermissions(perm: string): string[] {
|
|
||||||
// clone the array, avoids altering the local dataStore
|
|
||||||
const currentPermissions = this.permissions.slice();
|
|
||||||
|
|
||||||
if (this.hasPermission(perm)) {
|
|
||||||
// remove the permission from currentPermissions-List
|
|
||||||
const indexOfPerm = currentPermissions.indexOf(perm);
|
|
||||||
if (indexOfPerm !== -1) {
|
|
||||||
currentPermissions.splice(indexOfPerm, 1);
|
|
||||||
return currentPermissions;
|
|
||||||
} else {
|
|
||||||
return currentPermissions;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
currentPermissions.push(perm);
|
|
||||||
return currentPermissions;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public hasPermission(perm: string): boolean {
|
public hasPermission(perm: string): boolean {
|
||||||
return this.permissions.includes(perm);
|
return this.permissions.includes(perm);
|
||||||
}
|
}
|
||||||
@ -80,7 +53,5 @@ export class ViewGroup extends BaseViewModel {
|
|||||||
return this.group;
|
return this.group;
|
||||||
}
|
}
|
||||||
|
|
||||||
public updateDependencies(update: BaseViewModel): void {
|
public updateDependencies(update: BaseViewModel): void {}
|
||||||
console.log('ViewGroups wants to update Values with : ', update);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ from django.contrib.auth import (
|
|||||||
update_session_auth_hash,
|
update_session_auth_hash,
|
||||||
)
|
)
|
||||||
from django.contrib.auth.forms import AuthenticationForm
|
from django.contrib.auth.forms import AuthenticationForm
|
||||||
|
from django.contrib.auth.models import Permission
|
||||||
from django.contrib.auth.password_validation import validate_password
|
from django.contrib.auth.password_validation import validate_password
|
||||||
from django.contrib.auth.tokens import default_token_generator
|
from django.contrib.auth.tokens import default_token_generator
|
||||||
from django.contrib.sites.shortcuts import get_current_site
|
from django.contrib.sites.shortcuts import get_current_site
|
||||||
@ -314,7 +315,13 @@ class GroupViewSet(ModelViewSet):
|
|||||||
# Every authenticated user can see the metadata.
|
# Every authenticated user can see the metadata.
|
||||||
# Anonymous users can do so if they are enabled.
|
# Anonymous users can do so if they are enabled.
|
||||||
result = self.request.user.is_authenticated or anonymous_is_enabled()
|
result = self.request.user.is_authenticated or anonymous_is_enabled()
|
||||||
elif self.action in ("create", "partial_update", "update", "destroy"):
|
elif self.action in (
|
||||||
|
"create",
|
||||||
|
"partial_update",
|
||||||
|
"update",
|
||||||
|
"destroy",
|
||||||
|
"set_permission",
|
||||||
|
):
|
||||||
# Users with all app permissions can edit groups.
|
# Users with all app permissions can edit groups.
|
||||||
result = (
|
result = (
|
||||||
has_perm(self.request.user, "users.can_see_name")
|
has_perm(self.request.user, "users.can_see_name")
|
||||||
@ -410,6 +417,42 @@ class GroupViewSet(ModelViewSet):
|
|||||||
inform_changed_data(affected_users)
|
inform_changed_data(affected_users)
|
||||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||||
|
|
||||||
|
@detail_route(methods=["post"])
|
||||||
|
@transaction.atomic
|
||||||
|
def set_permission(self, request, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Send {perm: <permissionstring> set: <True/False>} to set or
|
||||||
|
remove the permission from a group
|
||||||
|
"""
|
||||||
|
perm = request.data.get("perm")
|
||||||
|
if not isinstance(perm, str):
|
||||||
|
raise ValidationError("You have to give a permission as string.")
|
||||||
|
set = request.data.get("set")
|
||||||
|
if not isinstance(set, bool):
|
||||||
|
raise ValidationError("You have to give a set value.")
|
||||||
|
|
||||||
|
# check if perm is a valid permission
|
||||||
|
try:
|
||||||
|
app_label, codename = perm.split(".")
|
||||||
|
except ValueError:
|
||||||
|
raise ValidationError("Incorrect permission string")
|
||||||
|
try:
|
||||||
|
permission = Permission.objects.get(
|
||||||
|
content_type__app_label=app_label, codename=codename
|
||||||
|
)
|
||||||
|
except Permission.DoesNotExist:
|
||||||
|
raise ValidationError("Incorrect permission string")
|
||||||
|
|
||||||
|
# add/remove the permission
|
||||||
|
group = self.get_object()
|
||||||
|
if set:
|
||||||
|
group.permissions.add(permission)
|
||||||
|
else:
|
||||||
|
group.permissions.remove(permission)
|
||||||
|
inform_changed_data(group)
|
||||||
|
|
||||||
|
return Response()
|
||||||
|
|
||||||
|
|
||||||
class PersonalNoteViewSet(ModelViewSet):
|
class PersonalNoteViewSet(ModelViewSet):
|
||||||
"""
|
"""
|
||||||
|
@ -10,6 +10,7 @@ from openslides.users.serializers import UserFullSerializer
|
|||||||
from openslides.utils.autoupdate import inform_changed_data
|
from openslides.utils.autoupdate import inform_changed_data
|
||||||
from openslides.utils.test import TestCase
|
from openslides.utils.test import TestCase
|
||||||
|
|
||||||
|
from ...common_groups import GROUP_DEFAULT_PK, GROUP_DELEGATE_PK, GROUP_STAFF_PK
|
||||||
from ..helpers import count_queries
|
from ..helpers import count_queries
|
||||||
|
|
||||||
|
|
||||||
@ -93,8 +94,7 @@ class UserCreate(TestCase):
|
|||||||
|
|
||||||
def test_creation_with_group(self):
|
def test_creation_with_group(self):
|
||||||
self.client.login(username="admin", password="admin")
|
self.client.login(username="admin", password="admin")
|
||||||
# These are the builtin groups 'Delegates' and 'Staff'. The pks are valid.
|
group_pks = (GROUP_DELEGATE_PK, GROUP_STAFF_PK)
|
||||||
group_pks = (2, 3)
|
|
||||||
|
|
||||||
self.client.post(
|
self.client.post(
|
||||||
reverse("user-list"),
|
reverse("user-list"),
|
||||||
@ -107,9 +107,7 @@ class UserCreate(TestCase):
|
|||||||
|
|
||||||
def test_creation_with_default_group(self):
|
def test_creation_with_default_group(self):
|
||||||
self.client.login(username="admin", password="admin")
|
self.client.login(username="admin", password="admin")
|
||||||
# This is the builtin groups 'default'.
|
group_pk = (GROUP_DEFAULT_PK,)
|
||||||
# The pk is valid. But this group can not be added to users.
|
|
||||||
group_pk = (1,)
|
|
||||||
|
|
||||||
response = self.client.post(
|
response = self.client.post(
|
||||||
reverse("user-list"),
|
reverse("user-list"),
|
||||||
@ -382,7 +380,7 @@ class GroupReceive(TestCase):
|
|||||||
user = User(username="test")
|
user = User(username="test")
|
||||||
user.set_password("test")
|
user.set_password("test")
|
||||||
user.save()
|
user.save()
|
||||||
default_group = Group.objects.get(pk=1)
|
default_group = Group.objects.get(pk=GROUP_DEFAULT_PK)
|
||||||
default_group.permissions.all().delete()
|
default_group.permissions.all().delete()
|
||||||
self.client.login(username="test", password="test")
|
self.client.login(username="test", password="test")
|
||||||
|
|
||||||
@ -463,8 +461,7 @@ class GroupUpdate(TestCase):
|
|||||||
def test_simple_update_via_patch(self):
|
def test_simple_update_via_patch(self):
|
||||||
admin_client = APIClient()
|
admin_client = APIClient()
|
||||||
admin_client.login(username="admin", password="admin")
|
admin_client.login(username="admin", password="admin")
|
||||||
# This is the builtin group 'Delegates'. The pk is valid.
|
group_pk = GROUP_DELEGATE_PK
|
||||||
group_pk = 2
|
|
||||||
# This contains one valid permission of the users app.
|
# This contains one valid permission of the users app.
|
||||||
permissions = ("users.can_see_name",)
|
permissions = ("users.can_see_name",)
|
||||||
|
|
||||||
@ -485,13 +482,12 @@ class GroupUpdate(TestCase):
|
|||||||
def test_simple_update_via_put(self):
|
def test_simple_update_via_put(self):
|
||||||
admin_client = APIClient()
|
admin_client = APIClient()
|
||||||
admin_client.login(username="admin", password="admin")
|
admin_client.login(username="admin", password="admin")
|
||||||
# This is the builtin group 'Delegates'. The pk is valid.
|
|
||||||
group_pk = 2
|
|
||||||
# This contains one valid permission of the users app.
|
# This contains one valid permission of the users app.
|
||||||
permissions = ("users.can_see_name",)
|
permissions = ("users.can_see_name",)
|
||||||
|
|
||||||
response = admin_client.put(
|
response = admin_client.put(
|
||||||
reverse("group-detail", args=[group_pk]), {"permissions": permissions}
|
reverse("group-detail", args=[GROUP_DELEGATE_PK]),
|
||||||
|
{"permissions": permissions},
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||||
@ -545,6 +541,54 @@ class GroupUpdate(TestCase):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_set_single_permission(self):
|
||||||
|
admin_client = APIClient()
|
||||||
|
admin_client.login(username="admin", password="admin")
|
||||||
|
|
||||||
|
response = admin_client.post(
|
||||||
|
reverse("group-set-permission", args=[GROUP_DEFAULT_PK]),
|
||||||
|
{"perm": "users.can_manage", "set": True},
|
||||||
|
format="json",
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||||
|
group = Group.objects.get(pk=GROUP_DEFAULT_PK)
|
||||||
|
self.assertTrue(
|
||||||
|
group.permissions.get(
|
||||||
|
content_type__app_label="users", codename="can_manage"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_add_single_permission_wrong_permission(self):
|
||||||
|
admin_client = APIClient()
|
||||||
|
admin_client.login(username="admin", password="admin")
|
||||||
|
|
||||||
|
response = admin_client.post(
|
||||||
|
reverse("group-set-permission", args=[GROUP_DEFAULT_PK]),
|
||||||
|
{"perm": "not_existing.permission", "set": True},
|
||||||
|
format="json",
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
def test_remove_single_permission(self):
|
||||||
|
admin_client = APIClient()
|
||||||
|
admin_client.login(username="admin", password="admin")
|
||||||
|
|
||||||
|
response = admin_client.post(
|
||||||
|
reverse("group-set-permission", args=[GROUP_DEFAULT_PK]),
|
||||||
|
{"perm": "users.can_see_name", "set": False},
|
||||||
|
format="json",
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||||
|
group = Group.objects.get(pk=GROUP_DEFAULT_PK)
|
||||||
|
self.assertFalse(
|
||||||
|
group.permissions.filter(
|
||||||
|
content_type__app_label="users", codename="can_see"
|
||||||
|
).exists()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class GroupDelete(TestCase):
|
class GroupDelete(TestCase):
|
||||||
"""
|
"""
|
||||||
@ -566,10 +610,8 @@ class GroupDelete(TestCase):
|
|||||||
def test_delete_builtin_groups(self):
|
def test_delete_builtin_groups(self):
|
||||||
admin_client = APIClient()
|
admin_client = APIClient()
|
||||||
admin_client.login(username="admin", password="admin")
|
admin_client.login(username="admin", password="admin")
|
||||||
# The pk of builtin group 'Default'
|
|
||||||
group_pk = 1
|
|
||||||
|
|
||||||
response = admin_client.delete(reverse("group-detail", args=[group_pk]))
|
response = admin_client.delete(reverse("group-detail", args=[GROUP_DEFAULT_PK]))
|
||||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user