-
Notifications
You must be signed in to change notification settings - Fork 816
/
accesscontrol.test.ts
132 lines (125 loc) · 5.05 KB
/
accesscontrol.test.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import { AccessControlMatrix } from '../accesscontrol';
import { MODEL_OPERATIONS } from '../utils';
test('test access control on object and field', () => {
/*
given the following schema
type Student
@model
@auth(rules: [
{ allow: groups, groups: ["admin"] }
{ allow: groups, groups: ["student"], operations: [read] }
]) {
studentID: ID
name: String
#acm protect email only studentID can update their own email
email: AWSEmail @auth(rules: [
{ allow: owner, ownerField: "studentID", operations: [update] }
{ allow: groups, groups: ["admin"] }
])
# only allowed to student and admin
ssn: String @auth(rules: [
{ allow: owner, ownerField: "studentID", operations: [read] }
{ allow: groups, groups: ["admin"] }
])
}
*/
// create an acm for the student type
const adminRole = 'userPools:staticGroup:admin';
const studentGroupRole = 'userPools:staticGroup:student';
const studentOwnerRole = 'userPools:owner:studentID';
const studentTypeFields = ['studentID', 'name', 'email', 'ssn'];
const acm = new AccessControlMatrix({
name: 'Student',
resources: studentTypeFields,
operations: MODEL_OPERATIONS,
});
// add OBJECT rules first
// add admin role which has full access on all CRUD operations for all fields
acm.setRole({
role: adminRole,
operations: MODEL_OPERATIONS,
});
// add the student static group rule which only has read access
acm.setRole({
role: studentGroupRole,
operations: ['read'],
});
studentTypeFields.forEach(field => {
// check that admin has CRUD access on all fields
expect(acm.isAllowed(adminRole, field, 'create')).toBe(true);
expect(acm.isAllowed(adminRole, field, 'read')).toBe(true);
expect(acm.isAllowed(adminRole, field, 'update')).toBe(true);
expect(acm.isAllowed(adminRole, field, 'delete')).toBe(true);
// check that studentGroupRole has access to read only
expect(acm.isAllowed(studentGroupRole, field, 'read')).toBe(true);
expect(acm.isAllowed(studentGroupRole, field, 'create')).toBe(false);
expect(acm.isAllowed(studentGroupRole, field, 'update')).toBe(false);
expect(acm.isAllowed(studentGroupRole, field, 'delete')).toBe(false);
});
// when adding a field rule on email we need to overwrite it
acm.resetAccessForResource('email');
expect(acm.isAllowed(studentGroupRole, 'email', 'read')).toBe(false);
acm.setRole({
role: studentOwnerRole,
operations: ['update'],
resource: 'email',
});
expect(acm.isAllowed(adminRole, 'email', 'update')).toBe(false);
expect(acm.isAllowed(studentOwnerRole, 'email', 'update')).toBe(true);
});
test('test access control only on field', () => {
/*
given the following schema
type Student
@model {
studentID: ID
name: String
# only allows read access on email and ssn for studentID ownerfield can also only update email
email: AWSEmail @auth(rules: [
{ allow: owner, ownerField: "studentID", operations: [read, update] }
])
ssn: String @auth(rules: [
{ allow: owner, ownerField: "studentID", operations: [read] }
])
}
*/
// create an acm for the student type
const studentOwnerRole = 'userPools:owner:studentID';
const studentTypeFields = ['studentID', 'name', 'email', 'ssn'];
const acm = new AccessControlMatrix({
name: 'Student',
resources: studentTypeFields,
operations: MODEL_OPERATIONS,
});
// set role for email field
acm.setRole({ role: studentOwnerRole, operations: ['read', 'update'], resource: 'email' });
// set role for ssn field
acm.setRole({ role: studentOwnerRole, operations: ['read'], resource: 'ssn' });
// expect the correct permissions are assigned for email field
expect(acm.isAllowed(studentOwnerRole, 'email', 'update')).toBe(true);
expect(acm.isAllowed(studentOwnerRole, 'email', 'read')).toBe(true);
expect(acm.isAllowed(studentOwnerRole, 'email', 'delete')).toBe(false);
expect(acm.isAllowed(studentOwnerRole, 'email', 'create')).toBe(false);
// expect the correct permissions are assigned for ssn field
expect(acm.isAllowed(studentOwnerRole, 'ssn', 'create')).toBe(false);
expect(acm.isAllowed(studentOwnerRole, 'ssn', 'read')).toBe(true);
expect(acm.isAllowed(studentOwnerRole, 'ssn', 'update')).toBe(false);
expect(acm.isAllowed(studentOwnerRole, 'ssn', 'delete')).toBe(false);
});
test('that adding a role again without a resource is not allowed', () => {
const blogOwnerRole = 'userPools:owner';
const blogFields = ['id', 'owner', 'name', 'content'];
const acm = new AccessControlMatrix({
name: 'Blog',
resources: blogFields,
operations: MODEL_OPERATIONS,
});
acm.setRole({ role: blogOwnerRole, operations: MODEL_OPERATIONS });
for (let field of blogFields) {
expect(acm.isAllowed(blogOwnerRole, field, 'create')).toBe(true);
expect(acm.isAllowed(blogOwnerRole, field, 'read')).toBe(true);
expect(acm.isAllowed(blogOwnerRole, field, 'update')).toBe(true);
expect(acm.isAllowed(blogOwnerRole, field, 'delete')).toBe(true);
}
expect(() => acm.setRole({ role: blogOwnerRole, operations: ['read'] })).toThrow(`@auth ${blogOwnerRole} already exists for Blog`);
});