Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Extend Partial Perms #4733

Merged
merged 51 commits into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
f0f9c09
Merge branch 'beta' into feature/extend-partial-perms
magicznyleszek Nov 13, 2023
9606c05
Merge branch 'beta' into feature/extend-partial-perms
magicznyleszek Nov 14, 2023
9006f22
Merge branch 'beta' into feature/extend-partial-perms
magicznyleszek Nov 16, 2023
18c1033
Merge branch 'rename-partial-permissions-variables' into feature/exte…
magicznyleszek Nov 20, 2023
32fc9ed
Merge branch 'rename-partial-permissions-variables' into feature/exte…
magicznyleszek Nov 21, 2023
8fbd0c0
Merge branch 'hardcode-permissions-labels' into feature/extend-partia…
magicznyleszek Nov 21, 2023
fa37ed0
WIP add …PartialByResponses constants
magicznyleszek Nov 21, 2023
6472ba9
add question select and value textbox (WIP)
magicznyleszek Nov 22, 2023
6529b7e
more wip changes
magicznyleszek Nov 24, 2023
29aeaa3
move UserAssetPermsEditor styles to separate file as CSS module
magicznyleszek Nov 24, 2023
b956f3a
Merge branch 'kobo-select-style-fixes' into feature/extend-partial-perms
magicznyleszek Nov 24, 2023
d93172c
Merge branch 'feature/extend-partial-perms' into feature-extend-parti…
magicznyleszek Nov 24, 2023
58aa3cc
fix renderPartialByResponsesRow layout
magicznyleszek Nov 27, 2023
4ed1f10
add unlisteners to UserAssetPermsEditor
magicznyleszek Nov 27, 2023
936d41a
partial by responses permission saving code
magicznyleszek Nov 27, 2023
cae8cbb
add some tests and make displaying new partial perm possible
magicznyleszek Nov 29, 2023
427229e
fix tests
magicznyleszek Nov 30, 2023
0941496
Merge branch 'beta' into feature/extend-partial-perms
magicznyleszek Dec 14, 2023
4a85ce1
Merge branch 'feature/extend-partial-perms' into feature-extend-parti…
magicznyleszek Dec 14, 2023
b43cabc
Merge branch 'beta' of github.com:kobotoolbox/kpi into feature-extend…
bufke Dec 21, 2023
a7fbe25
Add AND/OR functionality to mongo helper permissions filters
bufke Dec 21, 2023
3ceaacc
Minor fix
bufke Dec 21, 2023
bb05b00
Adjust asset permission assignment api to support AND/OR filters
bufke Dec 22, 2023
8650bcd
Update test_permissions for current implied permission strategy.
bufke Jan 2, 2024
caf7c7f
Lint fix
bufke Jan 2, 2024
96d4e8f
Update docstring for add_implied_permission
bufke Jan 8, 2024
2ab5480
rename userCanSubmission and fix tests for partial permissions
magicznyleszek Jan 9, 2024
ad929a4
Merge branch 'feature-extend-partial-perms--add-partial-by-responses'…
magicznyleszek Jan 9, 2024
ad0bf74
Merge branch 'beta' into feature/extend-partial-perms
magicznyleszek Jan 17, 2024
8e56ef9
Merge branch 'feature/extend-partial-perms' into feature-extend-parti…
magicznyleszek Jan 17, 2024
e5bde96
Merge branch 'beta' into feature/extend-partial-perms
magicznyleszek Jan 17, 2024
a299234
Merge branch 'feature/extend-partial-perms' into feature-extend-parti…
magicznyleszek Jan 17, 2024
e863138
Merge branch 'feature-extend-partial-perms--add-partial-by-responses'…
magicznyleszek Jan 17, 2024
774131d
adjust code to work with latest API architecture changes
magicznyleszek Jan 18, 2024
b997dee
Merge branch 'feature-extend-partial-perms--add-partial-by-responses'…
magicznyleszek Jan 18, 2024
8f68f30
Merge pull request #4781 from kobotoolbox/mongo-helper-and-or
noliveleger Jan 22, 2024
2a9a632
fix tests, handle implied partial permissions properly
magicznyleszek Jan 26, 2024
29b2413
Merge branch 'feature-extend-partial-perms--add-partial-by-responses'…
magicznyleszek Jan 26, 2024
1d1e732
add test for getFormData
magicznyleszek Jan 30, 2024
fcd2d62
Merge branch 'rename-partial-permissions-variables' into feature/exte…
magicznyleszek Jan 30, 2024
1642c99
Merge branch 'hardcode-permissions-labels' into feature/extend-partia…
magicznyleszek Jan 30, 2024
a70a7af
Merge branch 'feature/extend-partial-perms' into feature-extend-parti…
magicznyleszek Jan 30, 2024
9bb2323
Merge branch 'beta' into feature/extend-partial-perms
magicznyleszek Jan 31, 2024
72f6dba
Merge branch 'feature/extend-partial-perms' into feature-extend-parti…
magicznyleszek Jan 31, 2024
6eb7f3d
rename function for more clarity
magicznyleszek Feb 9, 2024
fefe92b
remove unnecessary comment
magicznyleszek Feb 9, 2024
24d16de
small ui improvements
magicznyleszek Feb 9, 2024
de60d66
allow empty value in "by responses" permission, add tests to cover th…
magicznyleszek Feb 10, 2024
5470756
Merge pull request #4824 from kobotoolbox/feature-extend-partial-perm…
magicznyleszek Feb 10, 2024
2efacf3
Merge branch 'beta' into feature/extend-partial-perms
magicznyleszek Feb 12, 2024
25ee4de
Merge branch 'beta' into feature/extend-partial-perms
magicznyleszek Feb 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 81 additions & 7 deletions jsapp/js/components/permissions/permConstants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,21 +81,50 @@ type CheckboxNameRegular =
| 'submissionsEdit'
| 'submissionsValidate'
| 'submissionsDelete';
/** Names of checkboxes for partial permissions (the counterparts). */
/** Names of checkboxes for "by users" partial permissions. */
export type CheckboxNamePartialByUsers =
| 'submissionsViewPartialByUsers'
| 'submissionsEditPartialByUsers'
| 'submissionsValidatePartialByUsers'
| 'submissionsDeletePartialByUsers';
/** Names of checkboxes for "by responses" partial permissions. */
export type CheckboxNamePartialByResponses =
| 'submissionsViewPartialByResponses'
| 'submissionsEditPartialByResponses'
| 'submissionsValidatePartialByResponses'
| 'submissionsDeletePartialByResponses';
/** All checkboxes names combined. */
export type CheckboxNameAll = CheckboxNameRegular | CheckboxNamePartialByUsers;
/** Name of lists of usernames for a partial permissions checkboxes. */
export type CheckboxNameAll =
| CheckboxNameRegular
| CheckboxNamePartialByUsers
| CheckboxNamePartialByResponses;

/** Name of lists of usernames for "by users" partial permissions checkboxes. */
export type PartialByUsersListName =
| 'submissionsViewPartialByUsersList'
| 'submissionsEditPartialByUsersList'
| 'submissionsDeletePartialByUsersList'
| 'submissionsValidatePartialByUsersList';

/**
* Name of select used by user to choose question for "by responses" partial
* permissions checkboxes.
*/
export type PartialByResponsesQuestionName =
| 'submissionsViewPartialByResponsesQuestion'
| 'submissionsEditPartialByResponsesQuestion'
| 'submissionsDeletePartialByResponsesQuestion'
| 'submissionsValidatePartialByResponsesQuestion';
/**
* Name of textbox used by user to type the condition value for "by responses"
* partial permissions checkboxes.
*/
export type PartialByResponsesValueName =
| 'submissionsViewPartialByResponsesValue'
| 'submissionsEditPartialByResponsesValue'
| 'submissionsDeletePartialByResponsesValue'
| 'submissionsValidatePartialByResponsesValue';

/**
* This list contains the names of all the checkboxes in userAssetPermsEditor.
* Every one of them is strictly connected to a permission, see the pairs at
Expand All @@ -108,17 +137,22 @@ export const CHECKBOX_NAMES = createEnum([
'submissionsAdd',
'submissionsView',
'submissionsViewPartialByUsers',
'submissionsViewPartialByResponses',
'submissionsEdit',
'submissionsEditPartialByUsers',
'submissionsEditPartialByResponses',
'submissionsValidate',
'submissionsValidatePartialByUsers',
'submissionsValidatePartialByResponses',
'submissionsDelete',
'submissionsDeletePartialByUsers',
'submissionsDeletePartialByResponses',
]) as {[P in CheckboxNameAll]: CheckboxNameAll};
Object.freeze(CHECKBOX_NAMES);

/**
* This is a map of pairs that connects a partial checkbox to a permission.
* This is a map of pairs that connects a partial "by users" checkbox to
* a matching permission.
*
* NOTE: a partial checkbox is using a "partial_submissions" permission, but
* in the array of de facto permissions it is using these ones. So for example
Expand All @@ -127,15 +161,29 @@ Object.freeze(CHECKBOX_NAMES);
* and a view_submissions permission - meaning that "Joe can view submissions,
* but only for this limited list of users".
*/
export const PARTIAL_PERM_PAIRS: {
export const PARTIAL_BY_USERS_PERM_PAIRS: {
[key in CheckboxNamePartialByUsers]: PermissionCodename;
} = {
submissionsViewPartialByUsers: 'view_submissions',
submissionsEditPartialByUsers: 'change_submissions',
submissionsValidatePartialByUsers: 'validate_submissions',
submissionsDeletePartialByUsers: 'delete_submissions',
};
Object.freeze(PARTIAL_PERM_PAIRS);
Object.freeze(PARTIAL_BY_USERS_PERM_PAIRS);

/**
* This is a map of pairs that connects a partial "by responses" checkbox to
* a matching permission.
*/
export const PARTIAL_BY_RESPONSES_PERM_PAIRS: {
[key in CheckboxNamePartialByResponses]: PermissionCodename;
} = {
submissionsViewPartialByResponses: 'view_submissions',
submissionsEditPartialByResponses: 'change_submissions',
submissionsValidatePartialByResponses: 'validate_submissions',
submissionsDeletePartialByResponses: 'delete_submissions',
};
Object.freeze(PARTIAL_BY_RESPONSES_PERM_PAIRS);

/**
* This is a map of pairs that connect a checkbox name to a permission name.
Expand All @@ -149,12 +197,16 @@ export const CHECKBOX_PERM_PAIRS: {
submissionsAdd: 'add_submissions',
submissionsView: 'view_submissions',
submissionsViewPartialByUsers: 'partial_submissions',
submissionsViewPartialByResponses: 'partial_submissions',
submissionsEdit: 'change_submissions',
submissionsEditPartialByUsers: 'partial_submissions',
submissionsEditPartialByResponses: 'partial_submissions',
submissionsValidate: 'validate_submissions',
submissionsValidatePartialByUsers: 'partial_submissions',
submissionsValidatePartialByResponses: 'partial_submissions',
submissionsDelete: 'delete_submissions',
submissionsDeletePartialByUsers: 'partial_submissions',
submissionsDeletePartialByResponses: 'partial_submissions',
};
Object.freeze(CHECKBOX_PERM_PAIRS);

Expand All @@ -164,6 +216,8 @@ Object.freeze(CHECKBOX_PERM_PAIRS);
*/
export const PARTIAL_IMPLIED_CHECKBOX_PAIRS = {
[CHECKBOX_NAMES.submissionsEditPartialByUsers]: CHECKBOX_NAMES.submissionsAdd,
[CHECKBOX_NAMES.submissionsEditPartialByResponses]:
CHECKBOX_NAMES.submissionsAdd,
};
Object.freeze(PARTIAL_IMPLIED_CHECKBOX_PAIRS);

Expand All @@ -180,19 +234,39 @@ export const CHECKBOX_LABELS: {[key in CheckboxNameAll]: string} = {
submissionsAdd: t('Add submissions'),
submissionsView: t('View submissions'),
submissionsViewPartialByUsers: t('View submissions only from specific users'),
submissionsViewPartialByResponses: t('View submissions based on a condition'),
submissionsEdit: t('Edit submissions'),
submissionsEditPartialByUsers: t('Edit submissions only from specific users'),
submissionsEditPartialByResponses: t('Edit submissions based on a condition'),
submissionsValidate: t('Validate submissions'),
submissionsValidatePartialByUsers: t(
'Validate submissions only from specific users'
),
submissionsValidatePartialByResponses: t(
'Validate submissions based on a condition'
),
submissionsDelete: t('Delete submissions'),
submissionsDeletePartialByUsers: t(
'Delete submissions only from specific users'
),
submissionsDeletePartialByResponses: t(
'Delete submissions based on a condition'
),
};
Object.freeze(CHECKBOX_LABELS);

export const PARTIAL_BY_USERS_DEFAULT_LABEL = t(
export const PARTIAL_BY_USERS_LABEL = t(
'Act on submissions only from specific users'
);

export const PARTIAL_BY_RESPONSES_LABEL = t(
'Act on submissions based on a condition'
);

// To be used when there are multiple filters in single permission - e.g. it has
// both "by users" and "by responses" defined.
export const PARTIAL_BY_MULTIPLE_LABEL = t(
'Act on submissions based on multiple conditions'
);

export const CHECKBOX_DISABLED_SUFFIX = 'Disabled';
80 changes: 76 additions & 4 deletions jsapp/js/components/permissions/permParser.mocks.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import type {PermissionsConfigResponse} from 'js/dataInterface';
import type {
PermissionsConfigResponse,
PaginatedResponse,
PermissionResponse,
} from 'js/dataInterface';

/**
* Mock permissions endpoints responses for tests.
Expand Down Expand Up @@ -111,7 +115,7 @@ const permissions: PermissionsConfigResponse = {
};

// /api/v2/assets/<uid>/permission-assignments/
const assetWithAnonymousUser = {
const assetWithAnonymousUser: PaginatedResponse<PermissionResponse> = {
count: 7,
next: null,
previous: null,
Expand Down Expand Up @@ -162,7 +166,7 @@ const assetWithAnonymousUser = {
};

// /api/v2/assets/<uid>/permission-assignments/
const assetWithMultipleUsers = {
const assetWithMultipleUsers: PaginatedResponse<PermissionResponse> = {
count: 9,
next: null,
previous: null,
Expand Down Expand Up @@ -231,7 +235,7 @@ const assetWithMultipleUsers = {
};

// /api/v2/assets/<uid>/permission-assignments/
const assetWithPartial = {
const assetWithPartial: PaginatedResponse<PermissionResponse> = {
count: 8,
next: null,
previous: null,
Expand Down Expand Up @@ -288,7 +292,74 @@ const assetWithPartial = {
url: '/api/v2/permissions/view_submissions/',
filters: [{_submitted_by: {$in: ['john', 'olivier']}}],
},
{
url: '/api/v2/permissions/change_submissions/',
filters: [{Where_are_you_from: 'Poland'}],
},
],
},
],
};

// /api/v2/assets/<uid>/permission-assignments/
const assetWithMultiplePartial: PaginatedResponse<PermissionResponse> = {
count: 3,
next: null,
previous: null,
results: [
{
url: '/api/v2/assets/abc123/permission-assignments/asd123/',
user: '/api/v2/users/gwyneth/',
permission: '/api/v2/permissions/add_submissions/',
label: 'Add submissions',
},
{
url: '/api/v2/assets/abc123/permission-assignments/vbn123/',
user: '/api/v2/users/gwyneth/',
permission: '/api/v2/permissions/partial_submissions/',
partial_permissions: [
// This permission is the AND one, which is the only case supported by
// Front-end code
{
url: '/api/v2/permissions/view_submissions/',
filters: [
{
Where_are_you_from: 'Poland',
_submitted_by: {$in: ['dave', 'krzysztof']},
},
],
},
{
url: '/api/v2/permissions/change_submissions/',
filters: [{Your_color: 'blue'}],
},
{
url: '/api/v2/permissions/delete_submissions/',
filters: [{_submitted_by: {$in: ['kate', 'joshua']}}],
},
// This permission is the OR one, which is not supported by Front-end
// code and should be treated as AND
{
url: '/api/v2/permissions/validate_submissions/',
filters: [
{What_is_your_fav_animal: 'Racoon'},
{_submitted_by: 'zachary'},
],
},
],
label: {
default: 'Act on submissions only from specific users',
view_submissions: 'View submissions only from specific users',
change_submissions: 'Edit submissions only from specific users',
delete_submissions: 'Delete submissions only from specific users',
validate_submissions: 'Validate submissions only from specific users',
},
},
{
url: '/api/v2/assets/abc123/permission-assignments/zxc123/',
user: '/api/v2/users/gwyneth/',
permission: '/api/v2/permissions/view_asset/',
label: 'View form',
},
],
};
Expand All @@ -298,4 +369,5 @@ export const endpoints = {
assetWithAnonymousUser,
assetWithMultipleUsers,
assetWithPartial,
assetWithMultiplePartial,
};
Loading
Loading