graphdb-workbench-tests 3.5.0-reactodia-resource-construct-TR1 → 3.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/e2e-legacy/guides/ttyg/configure-agent/configure-agent-guide.spec.js +2 -1
- package/e2e-legacy/guides/welcome/welcome-guide.spec.js +1 -1
- package/e2e-legacy/home/solr-banner/solr-banner.spec.js +137 -0
- package/e2e-legacy/repository/ontop-repository.spec.js +132 -0
- package/e2e-legacy/resource/resource.spec.js +4 -17
- package/e2e-legacy/setup/aclmanagement/create-rule.spec.js +1 -1
- package/e2e-legacy/setup/aclmanagement/delete-rule.spec.js +1 -1
- package/e2e-legacy/setup/aclmanagement/edit-rule.spec.js +1 -1
- package/e2e-legacy/setup/aclmanagement/render-rules.spec.js +1 -1
- package/e2e-legacy/setup/aclmanagement/reorder-rules.spec.js +1 -1
- package/e2e-legacy/setup/aclmanagement/revert-rules.spec.js +1 -1
- package/e2e-legacy/setup/aclmanagement/scopes.spec.js +2 -2
- package/e2e-legacy/setup/aclmanagement/update-rules.spec.js +2 -2
- package/e2e-legacy/setup/jdbc/jdbc-create.spec.js +1 -1
- package/e2e-legacy/setup/settings/my-settings-initial-state.spec.js +2 -6
- package/e2e-legacy/setup/settings/my-settings.spec.js +1 -1
- package/e2e-legacy/setup/users-and-access/user-and-access.spec.js +706 -337
- package/e2e-legacy/sparql-editor/saved-query/readonly-query.spec.js +1 -1
- package/e2e-legacy/ttyg/agent-select-menu.spec.js +7 -1
- package/e2e-legacy/ttyg/chat-list.spec.js +1 -1
- package/e2e-legacy/ttyg/create-chat.spec.js +1 -1
- package/e2e-legacy/ttyg/edit-agent.spec.js +2 -2
- package/e2e-legacy/ttyg/ttyg-permission.spec.js +2 -1
- package/e2e-security/setup/users-and-access/create-user-permissions.spec.js +15 -15
- package/e2e-security/setup/users-and-access/graphql-user.spec.js +3 -3
- package/e2e-security/setup/users-and-access/repo-admin-role.spec.js +2 -2
- package/eslint.config.js +1 -0
- package/fixtures/ontop/university-complete_edited.obda +106 -0
- package/npm-shrinkwrap.json +448 -278
- package/package.json +5 -6
- package/steps/application-steps.js +1 -1
- package/steps/deprecation-banner/deprecation-banner-steps.js +13 -0
- package/steps/deprecation-steps.js +13 -0
- package/steps/main-menu-steps.js +5 -1
- package/steps/ontop-repository-steps.js +20 -0
- package/steps/repository-steps.js +44 -3
- package/steps/resource/resource-steps.js +0 -8
- package/steps/setup/settings-steps.js +3 -3
- package/steps/setup/user-and-access-steps.js +84 -13
- package/steps/ttyg/ttyg-view-steps.js +15 -1
- package/stubs/repositories/repositories-stubs.js +4 -0
- package/stubs/security-stubs.js +4 -0
- package/support/security-command.js +43 -0
- package/cypress-guides.config.js +0 -45
- package/e2e-legacy/reactodia/reactodia.spec.js +0 -96
- package/steps/reactodia-steps.js +0 -42
|
@@ -7,6 +7,7 @@ import HomeSteps from '../../../steps/home-steps';
|
|
|
7
7
|
import {LoginSteps} from '../../../steps/login-steps';
|
|
8
8
|
import {MainMenuSteps} from '../../../steps/main-menu-steps';
|
|
9
9
|
import {SecurityStubs} from '../../../stubs/security-stubs.js';
|
|
10
|
+
import {RepositorySteps} from '../../../steps/repository-steps.js';
|
|
10
11
|
|
|
11
12
|
describe('User and Access', () => {
|
|
12
13
|
|
|
@@ -16,11 +17,25 @@ describe('User and Access', () => {
|
|
|
16
17
|
const ROLE_CUSTOM_ADMIN = '#roleAdmin';
|
|
17
18
|
const DEFAULT_ADMIN_PASSWORD = 'root';
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
context('', () => {
|
|
20
|
+
context('User and access management', () => {
|
|
21
21
|
const user = 'user';
|
|
22
|
+
let repoName;
|
|
23
|
+
|
|
24
|
+
before(() => {
|
|
25
|
+
repoName = 'user-access-repo1-' + Date.now();
|
|
26
|
+
cy.createRepository({id: repoName});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
after(() => {
|
|
30
|
+
cy.loginAsAdmin().then(() => {
|
|
31
|
+
cy.switchOffSecurity(true);
|
|
32
|
+
cy.switchOffFreeAccess(false);
|
|
33
|
+
});
|
|
34
|
+
cy.deleteRepository(repoName, true);
|
|
35
|
+
});
|
|
22
36
|
|
|
23
37
|
beforeEach(() => {
|
|
38
|
+
SecurityStubs.spyOnUserGet();
|
|
24
39
|
UserAndAccessSteps.visit();
|
|
25
40
|
// Users table should be visible
|
|
26
41
|
UserAndAccessSteps.getUsersTable().should('be.visible');
|
|
@@ -35,191 +50,388 @@ describe('User and Access', () => {
|
|
|
35
50
|
});
|
|
36
51
|
});
|
|
37
52
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
context('Initial state', () => {
|
|
54
|
+
it('Initial state', () => {
|
|
55
|
+
// Create new user button should be visible
|
|
56
|
+
UserAndAccessSteps.getCreateNewUserButton().should('be.visible');
|
|
57
|
+
// Security should be disabled
|
|
58
|
+
UserAndAccessSteps.getSecuritySwitchLabel().should('be.visible').and('contain', 'Security is OFF');
|
|
59
|
+
UserAndAccessSteps.getSecurityCheckbox().should('not.be.checked');
|
|
60
|
+
// Only admin user should be created by default
|
|
61
|
+
UserAndAccessSteps.getTableRow().should('have.length', 1);
|
|
62
|
+
UserAndAccessSteps.findUserInTable('admin');
|
|
63
|
+
UserAndAccessSteps.getUserType().should('be.visible').and('contain', 'Administrator');
|
|
64
|
+
// The admin should have unrestricted rights
|
|
65
|
+
UserAndAccessSteps.getRepositoryRights().should('be.visible').and('contain', 'Unrestricted');
|
|
66
|
+
// And can be edited
|
|
67
|
+
UserAndAccessSteps.getEditUserButton().should('be.visible').and('not.be.disabled');
|
|
68
|
+
// And cannot be deleted
|
|
69
|
+
UserAndAccessSteps.getDeleteUserButton().should('not.exist');
|
|
70
|
+
// Date created should be visible
|
|
71
|
+
UserAndAccessSteps.getDateCreated().should('be.visible');
|
|
72
|
+
});
|
|
56
73
|
});
|
|
57
74
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
75
|
+
context('User creation', () => {
|
|
76
|
+
it('Create user', () => {
|
|
77
|
+
//create a normal read/write user
|
|
78
|
+
createUser(user, PASSWORD, ROLE_USER, {readWrite: true});
|
|
79
|
+
testForUser(user, false);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('Create maintainer user', () => {
|
|
83
|
+
createUser(user, PASSWORD, ROLE_USER, {maintain: true, repoName});
|
|
84
|
+
testForUser(user, false);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('Create repo-manager', () => {
|
|
88
|
+
//create a repo-manager
|
|
89
|
+
createUser(user, PASSWORD, ROLE_REPO_MANAGER);
|
|
90
|
+
testForUser(user, false);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('Create second admin', () => {
|
|
94
|
+
//create a custom admin
|
|
95
|
+
createUser(user, PASSWORD, ROLE_CUSTOM_ADMIN);
|
|
96
|
+
testForUser(user, true);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('Create user with custom role', () => {
|
|
100
|
+
// When I create a read/write user
|
|
101
|
+
UserAndAccessSteps.clickCreateNewUserButton();
|
|
102
|
+
UserAndAccessSteps.typeUsername(user);
|
|
103
|
+
UserAndAccessSteps.typePassword(PASSWORD);
|
|
104
|
+
UserAndAccessSteps.typeConfirmPasswordField(PASSWORD);
|
|
105
|
+
UserAndAccessSteps.selectRoleRadioButton(ROLE_USER);
|
|
106
|
+
// And add a custom role of 1 letter
|
|
107
|
+
UserAndAccessSteps.addTextToCustomRoleField('A');
|
|
108
|
+
UserAndAccessSteps.toggleWriteAccessAny();
|
|
109
|
+
|
|
110
|
+
// Then the 'create' button should be disabled
|
|
111
|
+
UserAndAccessSteps.getConfirmUserCreateButton().should('be.disabled');
|
|
112
|
+
// And the field should show an error
|
|
113
|
+
UserAndAccessSteps.getCustomRoleFieldError().should('contain.text', 'Must be at least 2 symbols long');
|
|
114
|
+
// When I add more text to the custom role tag
|
|
115
|
+
UserAndAccessSteps.addTextToCustomRoleField('A{enter}');
|
|
116
|
+
// Then the 'create' button should be enabled
|
|
117
|
+
UserAndAccessSteps.getConfirmUserCreateButton().should('be.enabled');
|
|
118
|
+
// And the field error should not exist
|
|
119
|
+
UserAndAccessSteps.getCustomRoleFieldError().should('not.be.visible');
|
|
120
|
+
|
|
121
|
+
// When I type an invalid tag
|
|
122
|
+
UserAndAccessSteps.addTextToCustomRoleField('B{enter}');
|
|
123
|
+
// And the field shows an error
|
|
124
|
+
UserAndAccessSteps.getCustomRoleFieldError().should('contain.text', 'Must be at least 2 symbols long');
|
|
125
|
+
// When I delete the invalid text
|
|
126
|
+
UserAndAccessSteps.addTextToCustomRoleField('{backspace}');
|
|
127
|
+
// Then the error should not be visible
|
|
128
|
+
UserAndAccessSteps.getCustomRoleFieldError().should('not.be.visible');
|
|
129
|
+
|
|
130
|
+
// When I create the user with a valid custom role
|
|
131
|
+
UserAndAccessSteps.toggleWriteAccessAny();
|
|
132
|
+
SecurityStubs.spyOnUserCreate();
|
|
133
|
+
UserAndAccessSteps.confirmUserCreate();
|
|
134
|
+
// Then the user should be created with that custom role
|
|
135
|
+
cy.wait('@create-user').its('request.body').then((body) => {
|
|
136
|
+
expect(body).to.deep.eq({
|
|
137
|
+
'password': 'password',
|
|
138
|
+
'grantedAuthorities': [
|
|
139
|
+
'ROLE_USER',
|
|
140
|
+
'CUSTOM_AA',
|
|
141
|
+
'WRITE_REPO_*',
|
|
142
|
+
'READ_REPO_*',
|
|
143
|
+
],
|
|
144
|
+
'appSettings': {
|
|
145
|
+
'DEFAULT_VIS_GRAPH_SCHEMA': true,
|
|
146
|
+
'DEFAULT_INFERENCE': true,
|
|
147
|
+
'DEFAULT_SAMEAS': true,
|
|
148
|
+
'IGNORE_SHARED_QUERIES': false,
|
|
149
|
+
'EXECUTE_COUNT': true,
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
cy.url().should('include', '/users');
|
|
155
|
+
UserAndAccessSteps.findUserInTable(user).should('be.visible');
|
|
156
|
+
UserAndAccessSteps.getUserCustomRoles('@user')
|
|
157
|
+
.should('have.length', 1)
|
|
158
|
+
.eq(0).and('have.text', 'AA');
|
|
159
|
+
// And when I open the edit page for that user, the custom role should be visible in the field without the prefix
|
|
160
|
+
UserAndAccessSteps.openEditUserPage(user);
|
|
161
|
+
cy.wait('@get-user');
|
|
162
|
+
UserAndAccessSteps.getCustomRoleField().find('.tag-item span')
|
|
163
|
+
.should('have.length', 1)
|
|
164
|
+
.eq(0).and('have.text', 'AA');
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it('Adding a role with a CUSTOM_ prefix shows a warning message', () => {
|
|
168
|
+
// When I create a user
|
|
169
|
+
UserAndAccessSteps.clickCreateNewUserButton();
|
|
170
|
+
// And I add a custom role tag with prefix CUSTOM_
|
|
171
|
+
UserAndAccessSteps.addTextToCustomRoleField('CUSTOM_USER{Enter}');
|
|
172
|
+
// There should be a warning text
|
|
173
|
+
UserAndAccessSteps.getPrefixWarning(0).should('contain', 'Custom roles should be entered without the "CUSTOM_" prefix in Workbench');
|
|
174
|
+
});
|
|
63
175
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
176
|
+
it('Warn users when setting no password when creating new user admin', () => {
|
|
177
|
+
UserAndAccessSteps.getUsersTable().should('be.visible');
|
|
178
|
+
createUser(user, PASSWORD, ROLE_CUSTOM_ADMIN, {noPassword: true});
|
|
179
|
+
UserAndAccessSteps.getUsersTable().should('be.visible');
|
|
180
|
+
UserAndAccessSteps.getSplashLoader().should('not.be.visible');
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
// Skipped until image with GDB implementation is available
|
|
184
|
+
it.skip('should create user with maintain repo permission for specific repo', () => {
|
|
185
|
+
SecurityStubs.spyOnUserCreate();
|
|
186
|
+
UserAndAccessSteps.getUsersCatalogContainer().should('be.visible');
|
|
187
|
+
createUser(user, PASSWORD, ROLE_USER, {maintain: true, repoName: repoName});
|
|
188
|
+
// Then the user should be created with that custom role
|
|
189
|
+
cy.wait('@create-user').its('request.body').then((body) => {
|
|
190
|
+
expect(body).to.deep.eq({
|
|
191
|
+
'password': 'password',
|
|
192
|
+
'grantedAuthorities': [
|
|
193
|
+
'ROLE_USER',
|
|
194
|
+
`MAINTAIN_REPO_${repoName}`,
|
|
195
|
+
`WRITE_REPO_${repoName}`,
|
|
196
|
+
`READ_REPO_${repoName}`,
|
|
197
|
+
],
|
|
198
|
+
'appSettings': {
|
|
199
|
+
'DEFAULT_VIS_GRAPH_SCHEMA': true,
|
|
200
|
+
'DEFAULT_INFERENCE': true,
|
|
201
|
+
'DEFAULT_SAMEAS': true,
|
|
202
|
+
'IGNORE_SHARED_QUERIES': false,
|
|
203
|
+
'EXECUTE_COUNT': true,
|
|
204
|
+
},
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
UserAndAccessSteps.getUsersCatalogContainer().should('be.visible');
|
|
208
|
+
assertUserAuthsInCatalog(user, {repo: repoName, read: false, maintain: true, graphql: false});
|
|
209
|
+
|
|
210
|
+
UserAndAccessSteps.openEditUserPage(user);
|
|
211
|
+
cy.wait('@get-user');
|
|
212
|
+
UserAndAccessSteps.getRepositoryRightsList().should('be.visible');
|
|
213
|
+
verifyCheckedUserAuth(repoName, {read: true, write: true, maintain: true, graphql: false});
|
|
214
|
+
verifyDisabledUserAuth(repoName, {read: true, write: true, maintain: false, graphql: true});
|
|
215
|
+
});
|
|
68
216
|
});
|
|
69
217
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
218
|
+
context('Free access', () => {
|
|
219
|
+
it('should toggle free access after Admin has logged in', () => {
|
|
220
|
+
// Given I have available repositories to allow Free Access for
|
|
221
|
+
RepositoriesStubs.stubRepositories();
|
|
222
|
+
RepositoriesStubs.stubFreeAccess();
|
|
223
|
+
// When I enable security
|
|
224
|
+
UserAndAccessSteps.toggleSecurity();
|
|
225
|
+
// When I log in as an Admin
|
|
226
|
+
LoginSteps.loginWithUser('admin', DEFAULT_ADMIN_PASSWORD);
|
|
227
|
+
// Then the page should load
|
|
228
|
+
UserAndAccessSteps.getSplashLoader().should('not.be.visible');
|
|
229
|
+
UserAndAccessSteps.getUsersTable().should('be.visible');
|
|
230
|
+
// The Free Access toggle should be OFF
|
|
231
|
+
UserAndAccessSteps.getFreeAccessSwitchInput().should('not.be.checked');
|
|
232
|
+
// When I toggle Free Access ON
|
|
233
|
+
UserAndAccessSteps.toggleFreeAccess();
|
|
234
|
+
// And I allow free access to a repository
|
|
235
|
+
ModalDialogSteps.getDialog().should('be.visible');
|
|
236
|
+
// Then I click OK in the modal
|
|
237
|
+
ModalDialogSteps.clickOKButton();
|
|
238
|
+
// Then the toggle button should be ON
|
|
239
|
+
UserAndAccessSteps.getFreeAccessSwitchInput().should('be.checked');
|
|
240
|
+
// And I should see a success message
|
|
241
|
+
ToasterSteps.verifySuccess('Free access has been enabled.');
|
|
242
|
+
ToasterSteps.getToast().should('not.exist');
|
|
243
|
+
UserAndAccessSteps.getUsersTable().should('be.visible');
|
|
244
|
+
// When I toggle Free Access OFF
|
|
245
|
+
UserAndAccessSteps.toggleFreeAccess();
|
|
246
|
+
// Then I should see a success message
|
|
247
|
+
ToasterSteps.getToast().should('exist');
|
|
248
|
+
ToasterSteps.getToasterMessage().should('contain', 'Free access has been disabled.');
|
|
249
|
+
});
|
|
74
250
|
});
|
|
75
251
|
|
|
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
|
-
cy.wait('@create-user').its('request.body').then((body) => {
|
|
113
|
-
expect(body).to.deep.eq({
|
|
114
|
-
"password": "password",
|
|
115
|
-
"grantedAuthorities": [
|
|
116
|
-
"ROLE_USER",
|
|
117
|
-
"CUSTOM_AA",
|
|
118
|
-
"WRITE_REPO_*",
|
|
119
|
-
"READ_REPO_*"
|
|
120
|
-
],
|
|
121
|
-
"appSettings": {
|
|
122
|
-
"DEFAULT_VIS_GRAPH_SCHEMA": true,
|
|
123
|
-
"DEFAULT_INFERENCE": true,
|
|
124
|
-
"DEFAULT_SAMEAS": true,
|
|
125
|
-
"IGNORE_SHARED_QUERIES": false,
|
|
126
|
-
"EXECUTE_COUNT": true
|
|
127
|
-
}
|
|
128
|
-
})
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
cy.url().should('include', '/users');
|
|
132
|
-
UserAndAccessSteps.findUserInTable(user).should('be.visible');
|
|
133
|
-
UserAndAccessSteps.getUserCustomRoles('@user')
|
|
134
|
-
.should('have.length', 1)
|
|
135
|
-
.eq(0).and('have.text', 'AA');
|
|
136
|
-
// And when I open the edit page for that user, the custom role should be visible in the field without the prefix
|
|
137
|
-
UserAndAccessSteps.openEditUserPage(user);
|
|
138
|
-
UserAndAccessSteps.getCustomRoleField().find('.tag-item span')
|
|
139
|
-
.should('have.length', 1)
|
|
140
|
-
.eq(0).and('have.text', 'AA');
|
|
252
|
+
context('Login / return URL redirects', () => {
|
|
253
|
+
it('should not add the active repository to the login page URL', () => {
|
|
254
|
+
cy.presetRepository(repoName);
|
|
255
|
+
UserAndAccessSteps.visit();
|
|
256
|
+
cy.url().should('include', `repositoryId=${repoName}`);
|
|
257
|
+
|
|
258
|
+
UserAndAccessSteps.toggleSecurity();
|
|
259
|
+
|
|
260
|
+
cy.url()
|
|
261
|
+
.should('include', '/login')
|
|
262
|
+
.and('not.include', 'repositoryId=');
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
it('should redirect to previous page after logout and then login', () => {
|
|
266
|
+
UserAndAccessSteps.toggleSecurity();
|
|
267
|
+
LoginSteps.loginWithUser('admin', DEFAULT_ADMIN_PASSWORD);
|
|
268
|
+
MainMenuSteps.clickOnSparqlMenu();
|
|
269
|
+
cy.get('h1').should('be.visible').should('contain', 'SPARQL Query & Update');
|
|
270
|
+
cy.url().should('include', '/sparql');
|
|
271
|
+
|
|
272
|
+
LoginSteps.logout();
|
|
273
|
+
cy.url().should('include', '/login');
|
|
274
|
+
LoginSteps.loginWithUser('admin', DEFAULT_ADMIN_PASSWORD);
|
|
275
|
+
cy.url().should('include', '/sparql');
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
it('should redirect to correct return url when user is authenticated and on login page', () => {
|
|
279
|
+
UserAndAccessSteps.visit();
|
|
280
|
+
UserAndAccessSteps.toggleSecurity();
|
|
281
|
+
LoginSteps.loginWithUser('admin', DEFAULT_ADMIN_PASSWORD);
|
|
282
|
+
UserAndAccessSteps.getUsersTable().should('be.visible');
|
|
283
|
+
|
|
284
|
+
cy.visit('/login?r=%252Fsparql');
|
|
285
|
+
cy.reload();
|
|
286
|
+
UserAndAccessSteps.getUrl().should('include', '/sparql');
|
|
287
|
+
});
|
|
141
288
|
});
|
|
289
|
+
});
|
|
142
290
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
291
|
+
context('Verify access states', () => {
|
|
292
|
+
let repoName;
|
|
293
|
+
|
|
294
|
+
before(() => {
|
|
295
|
+
repoName = 'user-access-repo1-' + Date.now();
|
|
296
|
+
cy.createRepository({id: repoName});
|
|
297
|
+
cy.switchOffSecurity(true);
|
|
298
|
+
SecurityStubs.spyOnUserGet();
|
|
150
299
|
});
|
|
151
300
|
|
|
152
|
-
|
|
153
|
-
UserAndAccessSteps.
|
|
154
|
-
|
|
301
|
+
beforeEach(() => {
|
|
302
|
+
UserAndAccessSteps.visit();
|
|
303
|
+
// Users table should be visible
|
|
155
304
|
UserAndAccessSteps.getUsersTable().should('be.visible');
|
|
156
|
-
UserAndAccessSteps.getSplashLoader().should('not.be.visible');
|
|
157
305
|
});
|
|
158
306
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
// When I log in as an Admin
|
|
166
|
-
LoginSteps.loginWithUser('admin', DEFAULT_ADMIN_PASSWORD);
|
|
167
|
-
// Then the page should load
|
|
168
|
-
UserAndAccessSteps.getSplashLoader().should('not.be.visible');
|
|
169
|
-
UserAndAccessSteps.getUsersTable().should('be.visible');
|
|
170
|
-
// The Free Access toggle should be OFF
|
|
171
|
-
UserAndAccessSteps.getFreeAccessSwitchInput().should('not.be.checked');
|
|
172
|
-
// When I toggle Free Access ON
|
|
173
|
-
UserAndAccessSteps.toggleFreeAccess();
|
|
174
|
-
// And I allow free access to a repository
|
|
175
|
-
ModalDialogSteps.getDialog().should('be.visible');
|
|
176
|
-
// Then I click OK in the modal
|
|
177
|
-
ModalDialogSteps.clickOKButton();
|
|
178
|
-
// Then the toggle button should be ON
|
|
179
|
-
UserAndAccessSteps.getFreeAccessSwitchInput().should('be.checked');
|
|
180
|
-
// And I should see a success message
|
|
181
|
-
ToasterSteps.verifySuccess('Free access has been enabled.');
|
|
182
|
-
ToasterSteps.getToast().should('not.exist');
|
|
183
|
-
UserAndAccessSteps.getUsersTable().should('be.visible');
|
|
184
|
-
// When I toggle Free Access OFF
|
|
185
|
-
UserAndAccessSteps.toggleFreeAccess();
|
|
186
|
-
// Then I should see a success message
|
|
187
|
-
ToasterSteps.getToast().should('exist');
|
|
188
|
-
ToasterSteps.getToasterMessage().should('contain', 'Free access has been disabled.');
|
|
307
|
+
after(() => {
|
|
308
|
+
cy.loginAsAdmin().then(() => {
|
|
309
|
+
cy.deleteRepository(repoName, true);
|
|
310
|
+
cy.switchOffFreeAccess(true);
|
|
311
|
+
cy.switchOffSecurity(true);
|
|
312
|
+
});
|
|
189
313
|
});
|
|
190
314
|
|
|
191
|
-
it('
|
|
192
|
-
UserAndAccessSteps.
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
LoginSteps.logout();
|
|
198
|
-
cy.url().should('include', '/login');
|
|
199
|
-
LoginSteps.loginWithUser('admin', DEFAULT_ADMIN_PASSWORD);
|
|
200
|
-
cy.url().should('include', '/sparql');
|
|
315
|
+
it('initial state', () => {
|
|
316
|
+
UserAndAccessSteps.clickCreateNewUserButton();
|
|
317
|
+
verifyCheckedUserAuth('*', {read: false, write: false, maintain: false, graphql: false});
|
|
318
|
+
verifyDisabledUserAuth('*', {read: false, write: false, maintain: true, graphql: true});
|
|
319
|
+
verifyCheckedUserAuth(repoName, {read: false, write: false, maintain: false, graphql: false});
|
|
320
|
+
verifyDisabledUserAuth(repoName, {read: false, write: false, maintain: false, graphql: true});
|
|
201
321
|
});
|
|
202
322
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
323
|
+
context('for non user roles', () => {
|
|
324
|
+
it('admin', () => {
|
|
325
|
+
UserAndAccessSteps.clickCreateNewUserButton();
|
|
326
|
+
UserAndAccessSteps.selectRoleRadioButton(ROLE_CUSTOM_ADMIN);
|
|
327
|
+
verifyCheckedUserAuth('*', {read: true, write: true, maintain: true, graphql: false});
|
|
328
|
+
verifyDisabledUserAuth('*', {read: true, write: true, maintain: true, graphql: true});
|
|
329
|
+
|
|
330
|
+
verifyCheckedUserAuth(repoName, {read: true, write: true, maintain: true, graphql: false});
|
|
331
|
+
verifyDisabledUserAuth(repoName, {read: true, write: true, maintain: true, graphql: true});
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
it('repository manager', () => {
|
|
335
|
+
UserAndAccessSteps.clickCreateNewUserButton();
|
|
336
|
+
UserAndAccessSteps.selectRoleRadioButton(ROLE_REPO_MANAGER);
|
|
337
|
+
|
|
338
|
+
verifyCheckedUserAuth('*', {read: true, write: true, maintain: true, graphql: false});
|
|
339
|
+
verifyDisabledUserAuth('*', {read: true, write: true, maintain: true, graphql: true});
|
|
340
|
+
|
|
341
|
+
verifyCheckedUserAuth(repoName, {read: true, write: true, maintain: true, graphql: false});
|
|
342
|
+
verifyDisabledUserAuth(repoName, {read: true, write: true, maintain: true, graphql: true});
|
|
343
|
+
});
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
context('for specific repo', () => {
|
|
347
|
+
it('read', () => {
|
|
348
|
+
UserAndAccessSteps.clickCreateNewUserButton();
|
|
349
|
+
setRoles({read: true, repoName});
|
|
350
|
+
verifyCheckedUserAuth(repoName, {read: true, write: false, maintain: false, graphql: false});
|
|
351
|
+
verifyDisabledUserAuth(repoName, {read: false, write: false, maintain: false, graphql: false});
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
it('write', () => {
|
|
355
|
+
UserAndAccessSteps.clickCreateNewUserButton();
|
|
356
|
+
setRoles({readWrite: true, repoName});
|
|
357
|
+
verifyCheckedUserAuth(repoName, {read: true, write: true, maintain: false, graphql: false});
|
|
358
|
+
verifyDisabledUserAuth(repoName, {read: true, write: false, maintain: false, graphql: false});
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
it('maintain', () => {
|
|
362
|
+
UserAndAccessSteps.clickCreateNewUserButton();
|
|
363
|
+
setRoles({maintain: true, repoName});
|
|
364
|
+
verifyCheckedUserAuth(repoName, {read: true, write: true, maintain: true, graphql: false});
|
|
365
|
+
verifyDisabledUserAuth(repoName, {read: true, write: true, maintain: false, graphql: true});
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
it('graphql with read', () => {
|
|
369
|
+
UserAndAccessSteps.clickCreateNewUserButton();
|
|
370
|
+
setRoles({read: true, graphql: true, repoName});
|
|
371
|
+
verifyCheckedUserAuth(repoName, {read: true, write: false, maintain: false, graphql: true});
|
|
372
|
+
verifyDisabledUserAuth(repoName, {read: false, write: false, maintain: false, graphql: false});
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
it('graphql with write', () => {
|
|
376
|
+
UserAndAccessSteps.clickCreateNewUserButton();
|
|
377
|
+
setRoles({readWrite: true, graphql: true, repoName});
|
|
378
|
+
verifyCheckedUserAuth(repoName, {read: true, write: true, maintain: false, graphql: true});
|
|
379
|
+
verifyDisabledUserAuth(repoName, {read: true, write: false, maintain: false, graphql: false});
|
|
380
|
+
});
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
context('for any repo', () => {
|
|
384
|
+
let anyRepo = '*';
|
|
385
|
+
|
|
386
|
+
it('read', () => {
|
|
387
|
+
UserAndAccessSteps.clickCreateNewUserButton();
|
|
388
|
+
setRoles({read: true, anyRepo});
|
|
389
|
+
verifyCheckedUserAuth(anyRepo, {read: true, write: false, maintain: false, graphql: false});
|
|
390
|
+
verifyDisabledUserAuth(anyRepo, {read: false, write: false, maintain: true, graphql: false});
|
|
391
|
+
|
|
392
|
+
verifyCheckedUserAuth(repoName, {read: true, write: false, maintain: false, graphql: false});
|
|
393
|
+
verifyDisabledUserAuth(repoName, {read: true, write: false, maintain: false, graphql: false});
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
it('write', () => {
|
|
397
|
+
UserAndAccessSteps.clickCreateNewUserButton();
|
|
398
|
+
setRoles({readWrite: true, anyRepo});
|
|
399
|
+
verifyCheckedUserAuth(anyRepo, {read: true, write: true, maintain: false, graphql: false});
|
|
400
|
+
verifyDisabledUserAuth(anyRepo, {read: true, write: false, maintain: true, graphql: false});
|
|
401
|
+
|
|
402
|
+
verifyCheckedUserAuth(repoName, {read: true, write: true, maintain: false, graphql: false});
|
|
403
|
+
verifyDisabledUserAuth(repoName, {read: true, write: true, maintain: false, graphql: false});
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
it('graphql with read', () => {
|
|
407
|
+
UserAndAccessSteps.clickCreateNewUserButton();
|
|
408
|
+
setRoles({read: true, graphql: true, anyRepo});
|
|
409
|
+
verifyCheckedUserAuth(anyRepo, {read: true, write: false, maintain: false, graphql: true});
|
|
410
|
+
verifyDisabledUserAuth(anyRepo, {read: false, write: false, maintain: true, graphql: false});
|
|
411
|
+
|
|
412
|
+
verifyCheckedUserAuth(repoName, {read: true, write: false, maintain: false, graphql: true});
|
|
413
|
+
verifyDisabledUserAuth(repoName, {read: true, write: false, maintain: false, graphql: true});
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
it('graphql with write', () => {
|
|
417
|
+
UserAndAccessSteps.clickCreateNewUserButton();
|
|
418
|
+
setRoles({readWrite: true, graphql: true, anyRepo});
|
|
419
|
+
verifyCheckedUserAuth(anyRepo, {read: true, write: true, maintain: false, graphql: true});
|
|
420
|
+
verifyDisabledUserAuth(anyRepo, {read: true, write: false, maintain: true, graphql: false});
|
|
208
421
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
422
|
+
verifyCheckedUserAuth(repoName, {read: true, write: true, maintain: false, graphql: true});
|
|
423
|
+
verifyDisabledUserAuth(repoName, {read: true, write: true, maintain: false, graphql: true});
|
|
424
|
+
});
|
|
212
425
|
});
|
|
213
426
|
});
|
|
214
|
-
|
|
215
|
-
context('GraphQL
|
|
427
|
+
|
|
428
|
+
context('GraphQL access', () => {
|
|
216
429
|
let repositoryId1;
|
|
217
430
|
let repositoryId2;
|
|
218
431
|
let repositoryId3;
|
|
219
432
|
const graphqlUser = 'graphqlUser';
|
|
220
433
|
|
|
221
434
|
beforeEach(() => {
|
|
222
|
-
cy.viewport(1280, 1000);
|
|
223
435
|
RepositoriesStubs.spyGetRepositories();
|
|
224
436
|
repositoryId1 = 'user-access-repo1-' + Date.now();
|
|
225
437
|
repositoryId2 = 'user-access-repo2-' + Date.now();
|
|
@@ -231,6 +443,7 @@ describe('User and Access', () => {
|
|
|
231
443
|
UserAndAccessSteps.visit();
|
|
232
444
|
// Users table should be visible
|
|
233
445
|
UserAndAccessSteps.getUsersTable().should('be.visible');
|
|
446
|
+
SecurityStubs.spyOnUserGet();
|
|
234
447
|
});
|
|
235
448
|
|
|
236
449
|
afterEach(() => {
|
|
@@ -245,174 +458,318 @@ describe('User and Access', () => {
|
|
|
245
458
|
|
|
246
459
|
});
|
|
247
460
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
461
|
+
context('GraphQL checkbox behavior', () => {
|
|
462
|
+
it('Create user with GraphQL-only access', () => {
|
|
463
|
+
cy.wait('@getRepositories');
|
|
464
|
+
createUser(graphqlUser, PASSWORD, ROLE_USER, {read: true, graphql: true, repoName: repositoryId2});
|
|
465
|
+
});
|
|
252
466
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
467
|
+
// Fails for unknown reason only in CI
|
|
468
|
+
it('Can create user with different auth combinations', () => {
|
|
469
|
+
cy.wait('@getRepositories');
|
|
470
|
+
cy.wait('@getRepositories');
|
|
471
|
+
UserAndAccessSteps.getUsersCatalogContainer().should('be.visible');
|
|
472
|
+
// WHEN I create a user with read + GraphQL for repository #2
|
|
473
|
+
createUser(graphqlUser, PASSWORD, ROLE_USER, {read: true, graphql: true, repoName: repositoryId2});
|
|
474
|
+
// THEN the user should have read + GraphQL on that repo
|
|
475
|
+
assertUserAuthsInCatalog(graphqlUser, {repo: repositoryId2, read: true, graphql: true});
|
|
476
|
+
// WHEN I open the edit page for that user
|
|
477
|
+
UserAndAccessSteps.openEditUserPage(graphqlUser);
|
|
478
|
+
cy.wait('@get-user');
|
|
479
|
+
// THEN for repository #1, the GraphQL checkbox should be disabled initially
|
|
480
|
+
UserAndAccessSteps.validateGraphqlAccessForRepo(repositoryId1, {disabled: true});
|
|
481
|
+
// WHEN I enable "read" for repository #1
|
|
482
|
+
setUserAuths({repo: repositoryId1, read: true});
|
|
483
|
+
// THEN GraphQL for repository #1 should become enabled
|
|
484
|
+
UserAndAccessSteps.validateGraphqlAccessForRepo(repositoryId1, {disabled: false});
|
|
485
|
+
// WHEN I enable GraphQL with read
|
|
486
|
+
setUserAuths({repo: repositoryId1, graphql: true});
|
|
487
|
+
// THEN GraphQL should be checked and enabled
|
|
488
|
+
UserAndAccessSteps.validateGraphqlAccessForRepo(repositoryId1, {checked: true, disabled: false});
|
|
489
|
+
// THEN for repository #3, GraphQL should be disabled initially
|
|
490
|
+
UserAndAccessSteps.validateGraphqlAccessForRepo(repositoryId3, {disabled: true});
|
|
491
|
+
// WHEN I enable "write" for repository #3
|
|
492
|
+
setUserAuths({repo: repositoryId3, write: true});
|
|
493
|
+
// THEN GraphQL for repository #3 should become enabled
|
|
494
|
+
UserAndAccessSteps.validateGraphqlAccessForRepo(repositoryId3, {disabled: false});
|
|
495
|
+
// And I expect "read" to be checked and disabled
|
|
496
|
+
UserAndAccessSteps.validateReadAccessForRepo(repositoryId3, {checked: true, disabled: true});
|
|
497
|
+
// I enable GraphQL for repository #3
|
|
498
|
+
setUserAuths({repo: repositoryId3, graphql: true});
|
|
499
|
+
// THEN GraphQL should be checked and enabled
|
|
500
|
+
UserAndAccessSteps.validateGraphqlAccessForRepo(repositoryId1, {checked: true, disabled: false});
|
|
501
|
+
// When I remove "read" for repository #2
|
|
502
|
+
UserAndAccessSteps.toggleReadAccessForRepo(repositoryId2);
|
|
503
|
+
// THEN I expect "graphql" to be unchecked and disabled for repository #2
|
|
504
|
+
UserAndAccessSteps.validateGraphqlAccessForRepo(repositoryId2, {checked: false, disabled: true});
|
|
505
|
+
|
|
506
|
+
// WHEN I confirm the user edit
|
|
507
|
+
UserAndAccessSteps.confirmUserEdit();
|
|
508
|
+
// THEN verify the final rights:
|
|
509
|
+
// - repo #1 has no read/write/graphql
|
|
510
|
+
// - repo #2 has read + graphql
|
|
511
|
+
// - repo #3 has write + graphql (and read was auto-checked but disabled)
|
|
512
|
+
assertUserAuthsInCatalog(graphqlUser, {repo: repositoryId1, read: true, write: false, graphql: true});
|
|
513
|
+
assertUserAuthsInCatalog(graphqlUser, {repo: repositoryId2, read: false, write: false, graphql: false});
|
|
514
|
+
assertUserAuthsInCatalog(graphqlUser, {repo: repositoryId3, read: false, write: true, graphql: true});
|
|
515
|
+
});
|
|
293
516
|
});
|
|
294
517
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
518
|
+
context('Menu navigation based on permissions', () => {
|
|
519
|
+
it('Should have access to 5 pages when have graphql only rights', () => {
|
|
520
|
+
cy.wait('@getRepositories');
|
|
521
|
+
cy.wait('@getRepositories');
|
|
522
|
+
// WHEN I create a user with read + GraphQL for repository #2
|
|
523
|
+
createUser(graphqlUser, PASSWORD, ROLE_USER, {readWrite: true, graphql: true, repoName: repositoryId1});
|
|
524
|
+
//enable security
|
|
525
|
+
UserAndAccessSteps.toggleSecurity();
|
|
526
|
+
//login new user
|
|
527
|
+
LoginSteps.loginWithUser(graphqlUser, PASSWORD);
|
|
528
|
+
cy.wait('@getRepositories');
|
|
529
|
+
cy.wait('@getRepositories');
|
|
530
|
+
|
|
531
|
+
MENU_ITEMS_WITHOUT_GRAPHQL.forEach(({path, expectedUrl, checks, expectedTitle}) => {
|
|
532
|
+
navigateMenuPath(path, expectedUrl, expectedTitle);
|
|
533
|
+
|
|
534
|
+
if (checks) {
|
|
535
|
+
runChecks(checks);
|
|
536
|
+
}
|
|
537
|
+
navigateMenuPath(['Import'], '/import', 'Import');
|
|
538
|
+
});
|
|
311
539
|
});
|
|
312
|
-
});
|
|
313
540
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
541
|
+
it('Should not have access endpoints management when have read graphql only rights', () => {
|
|
542
|
+
cy.wait('@getRepositories');
|
|
543
|
+
cy.wait('@getRepositories');
|
|
544
|
+
// WHEN I create a user with read + GraphQL for repository #2
|
|
545
|
+
createUser(graphqlUser, PASSWORD, ROLE_USER, {read: true, graphql: true, repoName: repositoryId1});
|
|
546
|
+
//enable security
|
|
547
|
+
UserAndAccessSteps.toggleSecurity();
|
|
548
|
+
//login new user
|
|
549
|
+
LoginSteps.loginWithUser(graphqlUser, PASSWORD);
|
|
550
|
+
cy.wait('@getRepositories');
|
|
551
|
+
cy.wait('@getRepositories');
|
|
552
|
+
// RepositorySelectorSteps.selectRepository(repositoryId1);
|
|
553
|
+
|
|
554
|
+
GRAPHQL_READ_MENU_ITEMS.forEach(({path, expectedUrl, checks, expectedTitle}) => {
|
|
555
|
+
navigateMenuPath(path, expectedUrl, expectedTitle);
|
|
556
|
+
if (checks) {
|
|
557
|
+
runChecks(checks);
|
|
558
|
+
}
|
|
559
|
+
navigateMenuPath(['Import'], '/import', 'Import');
|
|
560
|
+
});
|
|
329
561
|
});
|
|
330
|
-
});
|
|
331
562
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
563
|
+
it('Should have all access to endpoints management when have REPO_MANAGER role', () => {
|
|
564
|
+
cy.wait('@getRepositories');
|
|
565
|
+
cy.wait('@getRepositories');
|
|
566
|
+
createUser(graphqlUser, PASSWORD, ROLE_REPO_MANAGER);
|
|
567
|
+
//enable security
|
|
568
|
+
UserAndAccessSteps.toggleSecurity();
|
|
569
|
+
HomeSteps.visitAndWaitLoader();
|
|
570
|
+
//login new user
|
|
571
|
+
LoginSteps.loginWithUser(graphqlUser, PASSWORD);
|
|
572
|
+
cy.wait('@getRepositories');
|
|
573
|
+
cy.wait('@getRepositories');
|
|
574
|
+
GRAPHQL_REPO_MANAGER_MENU_ITEMS.forEach(({path, expectedUrl, checks, expectedTitle}) => {
|
|
575
|
+
navigateMenuPath(path, expectedUrl, expectedTitle);
|
|
576
|
+
if (checks) {
|
|
577
|
+
runChecks(checks);
|
|
578
|
+
}
|
|
579
|
+
navigateMenuPath(['Import'], '/import', 'Import');
|
|
580
|
+
});
|
|
581
|
+
});
|
|
582
|
+
|
|
583
|
+
it('Can have Free Access and GraphQL working together', () => {
|
|
584
|
+
cy.wait('@getRepositories');
|
|
585
|
+
cy.wait('@getRepositories');
|
|
586
|
+
//enable security
|
|
587
|
+
UserAndAccessSteps.toggleSecurity();
|
|
588
|
+
//login with the admin
|
|
589
|
+
LoginSteps.loginWithUser('admin', DEFAULT_ADMIN_PASSWORD);
|
|
590
|
+
cy.wait('@getRepositories');
|
|
591
|
+
cy.wait('@getRepositories');
|
|
592
|
+
// The Free Access toggle should be OFF
|
|
593
|
+
UserAndAccessSteps.getFreeAccessSwitchInput().should('not.be.checked');
|
|
594
|
+
// When I toggle Free Access ON
|
|
595
|
+
UserAndAccessSteps.toggleFreeAccess();
|
|
596
|
+
// Then I set repo auths
|
|
597
|
+
UserAndAccessSteps.clickFreeReadAccessRepo(repositoryId1);
|
|
598
|
+
UserAndAccessSteps.clickFreeWriteAccessRepo(repositoryId2);
|
|
599
|
+
UserAndAccessSteps.clickFreeWriteAccessRepo(repositoryId3);
|
|
600
|
+
UserAndAccessSteps.clickFreeGraphqlAccessRepo(repositoryId3);
|
|
601
|
+
// Then I click OK in the modal
|
|
602
|
+
ModalDialogSteps.clickOKButton();
|
|
603
|
+
// Then the toggle button should be ON
|
|
604
|
+
UserAndAccessSteps.getFreeAccessSwitchInput().should('be.checked');
|
|
605
|
+
// And I should see a success message
|
|
606
|
+
ToasterSteps.verifySuccess('Free access has been enabled.');
|
|
607
|
+
UserAndAccessSteps.getUsersTable().should('be.visible');
|
|
608
|
+
|
|
609
|
+
// Then I logout
|
|
610
|
+
LoginSteps.logout();
|
|
611
|
+
HomeSteps.visit();
|
|
612
|
+
// I change the repository to this with GraphQL only rights
|
|
613
|
+
RepositorySelectorSteps.selectRepository(repositoryId3);
|
|
614
|
+
// Then I should have GraphQL only rights
|
|
615
|
+
FREE_ACCESS_MENU_ITEMS_WITHOUT_GRAPHQL.forEach(({path, expectedUrl, checks, expectedTitle}) => {
|
|
616
|
+
navigateMenuPath(path, expectedUrl, expectedTitle);
|
|
617
|
+
if (checks) {
|
|
618
|
+
runChecks(checks);
|
|
619
|
+
}
|
|
620
|
+
navigateMenuPath(['Import'], '/import', 'Import');
|
|
621
|
+
});
|
|
345
622
|
});
|
|
346
623
|
});
|
|
624
|
+
});
|
|
347
625
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
626
|
+
context('User with maintain permission', () => {
|
|
627
|
+
let withoutPermissionRepositoryId;
|
|
628
|
+
let readRepositoryId;
|
|
629
|
+
let writeRepositoryId;
|
|
630
|
+
let graphQLOnlyRepositoryId;
|
|
631
|
+
let maintainedRepositoryId;
|
|
632
|
+
const maintainerUser = 'maintainerUser';
|
|
633
|
+
|
|
634
|
+
beforeEach(() => {
|
|
635
|
+
RepositoriesStubs.spyGetRepositories();
|
|
636
|
+
readRepositoryId = 'readRepositoryId-' + Date.now();
|
|
637
|
+
writeRepositoryId = 'writeRepositoryId-' + Date.now();
|
|
638
|
+
graphQLOnlyRepositoryId = 'graphQLOnlyRepositoryId-' + Date.now();
|
|
639
|
+
maintainedRepositoryId = 'maintainedRepositoryId-' + Date.now();
|
|
640
|
+
withoutPermissionRepositoryId = 'withoutPermissionRepositoryId-' + Date.now();
|
|
641
|
+
cy.createRepository({id: readRepositoryId});
|
|
642
|
+
cy.createRepository({id: writeRepositoryId});
|
|
643
|
+
cy.createRepository({id: graphQLOnlyRepositoryId});
|
|
644
|
+
cy.createRepository({id: maintainedRepositoryId});
|
|
645
|
+
cy.createRepository({id: withoutPermissionRepositoryId});
|
|
646
|
+
UserAndAccessSteps.visit();
|
|
647
|
+
// Users table should be visible
|
|
369
648
|
UserAndAccessSteps.getUsersTable().should('be.visible');
|
|
649
|
+
SecurityStubs.spyOnUserGet();
|
|
650
|
+
});
|
|
370
651
|
|
|
371
|
-
|
|
372
|
-
LoginSteps.logout();
|
|
373
|
-
HomeSteps.visit();
|
|
374
|
-
// I change the repository to this with GraphQL only rights
|
|
375
|
-
RepositorySelectorSteps.selectRepository(repositoryId3);
|
|
376
|
-
// Then I should have GraphQL only rights
|
|
377
|
-
FREE_ACCESS_MENU_ITEMS_WITHOUT_GRAPHQL.forEach(({path, expectedUrl, checks, expectedTitle}) => {
|
|
378
|
-
navigateMenuPath(path, expectedUrl, expectedTitle);
|
|
379
|
-
if (checks) {
|
|
380
|
-
runChecks(checks);
|
|
381
|
-
}
|
|
382
|
-
});
|
|
383
|
-
// Turn free access off
|
|
652
|
+
afterEach(() => {
|
|
384
653
|
cy.loginAsAdmin().then(() => {
|
|
654
|
+
cy.deleteRepository(readRepositoryId, true);
|
|
655
|
+
cy.deleteRepository(writeRepositoryId, true);
|
|
656
|
+
cy.deleteRepository(graphQLOnlyRepositoryId, true);
|
|
657
|
+
cy.deleteRepository(maintainedRepositoryId, true);
|
|
658
|
+
cy.deleteRepository(withoutPermissionRepositoryId, true);
|
|
659
|
+
cy.deleteUser(maintainerUser, true);
|
|
385
660
|
cy.switchOffFreeAccess(true);
|
|
661
|
+
cy.switchOffSecurity(true);
|
|
386
662
|
});
|
|
387
663
|
});
|
|
388
|
-
});
|
|
389
664
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
665
|
+
it('should list all repositories for which a user with maintain permission has at least read permission', () => {
|
|
666
|
+
// Given there are five repositories.
|
|
667
|
+
// And there is a user with permissions for four of them:
|
|
668
|
+
// 1. Maintain permission for one repository.
|
|
669
|
+
createUser(maintainerUser, PASSWORD, ROLE_USER, {maintain: true, repoName: maintainedRepositoryId});
|
|
670
|
+
// 2. Read permission for one repository.
|
|
671
|
+
UserAndAccessSteps.openEditUserPage(maintainerUser);
|
|
672
|
+
cy.wait('@get-user');
|
|
673
|
+
setUserAuths({repo: readRepositoryId, read: true});
|
|
674
|
+
// 3. Write permission for one repository.
|
|
675
|
+
setUserAuths({repo: writeRepositoryId, write: true});
|
|
676
|
+
// 4. GraphQL-only permission for one repository.
|
|
677
|
+
setUserAuths({repo: graphQLOnlyRepositoryId, write: true, graphql: true});
|
|
678
|
+
UserAndAccessSteps.confirmUserEdit();
|
|
397
679
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
680
|
+
// When I log in as a user with repository maintain permission.
|
|
681
|
+
UserAndAccessSteps.toggleSecurity();
|
|
682
|
+
LoginSteps.loginWithUser(maintainerUser, PASSWORD);
|
|
683
|
+
// And navigate to the repository list view.
|
|
684
|
+
RepositorySteps.visit(false);
|
|
685
|
+
|
|
686
|
+
// Then I should see all repositories for which the user has at least read permission.
|
|
687
|
+
RepositorySteps.getRepositories().should('have.length', 4);
|
|
688
|
+
|
|
689
|
+
// And I should see the actions allowed for the repository the user can maintain.
|
|
690
|
+
RepositorySteps.getCopyRepositoryButton(maintainedRepositoryId).should('be.visible');
|
|
691
|
+
RepositorySteps.getEditRepositoryButton(maintainedRepositoryId).should('be.visible');
|
|
692
|
+
RepositorySteps.getDownloadRepositoryConfigurationButton(maintainedRepositoryId).should('be.visible');
|
|
693
|
+
RepositorySteps.getRestartRepositoryButton(maintainedRepositoryId).should('be.visible');
|
|
694
|
+
|
|
695
|
+
// And the delete button should not be available because users with maintain permission
|
|
696
|
+
// are not allowed to delete repositories.
|
|
697
|
+
RepositorySteps.getDeleteRepositoryButton(maintainedRepositoryId).should('not.exist');
|
|
698
|
+
|
|
699
|
+
// And the "Set as default repository" button should not be available because users
|
|
700
|
+
// with maintain permission are not allowed to set the default repository.
|
|
701
|
+
RepositorySteps.getSetDefaultRepositoryButton(maintainedRepositoryId).should('not.exist');
|
|
702
|
+
|
|
703
|
+
// And should see the copy action for all repositories.
|
|
704
|
+
RepositorySteps.getCopyRepositoryButton(writeRepositoryId).should('be.visible');
|
|
705
|
+
RepositorySteps.getCopyRepositoryButton(readRepositoryId).should('be.visible');
|
|
706
|
+
RepositorySteps.getCopyRepositoryButton(graphQLOnlyRepositoryId).should('be.visible');
|
|
707
|
+
|
|
708
|
+
// And no repository management actions should be available for the other repositories.
|
|
709
|
+
RepositorySteps.getEditRepositoryButton(readRepositoryId).should('not.exist');
|
|
710
|
+
RepositorySteps.getDownloadRepositoryConfigurationButton(readRepositoryId).should('not.exist');
|
|
711
|
+
RepositorySteps.getRestartRepositoryButton(readRepositoryId).should('not.exist');
|
|
712
|
+
RepositorySteps.getDeleteRepositoryButton(readRepositoryId).should('not.exist');
|
|
713
|
+
RepositorySteps.getSetDefaultRepositoryButton(readRepositoryId).should('not.exist');
|
|
714
|
+
|
|
715
|
+
RepositorySteps.getEditRepositoryButton(writeRepositoryId).should('not.exist');
|
|
716
|
+
RepositorySteps.getDownloadRepositoryConfigurationButton(writeRepositoryId).should('not.exist');
|
|
717
|
+
RepositorySteps.getRestartRepositoryButton(writeRepositoryId).should('not.exist');
|
|
718
|
+
RepositorySteps.getDeleteRepositoryButton(writeRepositoryId).should('not.exist');
|
|
719
|
+
RepositorySteps.getSetDefaultRepositoryButton(writeRepositoryId).should('not.exist');
|
|
720
|
+
|
|
721
|
+
RepositorySteps.getEditRepositoryButton(graphQLOnlyRepositoryId).should('not.exist');
|
|
722
|
+
RepositorySteps.getDownloadRepositoryConfigurationButton(graphQLOnlyRepositoryId).should('not.exist');
|
|
723
|
+
RepositorySteps.getRestartRepositoryButton(graphQLOnlyRepositoryId).should('not.exist');
|
|
724
|
+
RepositorySteps.getDeleteRepositoryButton(graphQLOnlyRepositoryId).should('not.exist');
|
|
725
|
+
RepositorySteps.getSetDefaultRepositoryButton(graphQLOnlyRepositoryId).should('not.exist');
|
|
726
|
+
|
|
727
|
+
// And the "Create", "Create from file", and "Attach remote repository" page buttons
|
|
728
|
+
// should not be available to a user with maintain permission.
|
|
729
|
+
RepositorySteps.getPageButtons().should('not.exist');
|
|
730
|
+
|
|
731
|
+
// When I select a repository for which I have GraphQL-only permission.
|
|
732
|
+
RepositorySelectorSteps.selectRepository(graphQLOnlyRepositoryId);
|
|
733
|
+
|
|
734
|
+
// Then I should still see all repositories for which the user has at least read permission.
|
|
735
|
+
RepositorySteps.getRepositories().should('have.length', 4);
|
|
736
|
+
});
|
|
405
737
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
738
|
+
it('should not allow a user with maintain permission to rename a repository', () => {
|
|
739
|
+
// Given there is a user with maintain permission for a repository.
|
|
740
|
+
createUser(maintainerUser, PASSWORD, ROLE_USER, {maintain: true, repoName: maintainedRepositoryId});
|
|
741
|
+
UserAndAccessSteps.toggleSecurity();
|
|
742
|
+
LoginSteps.loginWithUser(maintainerUser, PASSWORD);
|
|
743
|
+
RepositorySteps.visit(false);
|
|
744
|
+
|
|
745
|
+
// When the user opens the edit page of the repository they can maintain.
|
|
746
|
+
RepositorySteps.getEditRepositoryButton(maintainedRepositoryId).should('be.visible');
|
|
747
|
+
RepositorySteps.editRepository(maintainedRepositoryId);
|
|
748
|
+
|
|
749
|
+
// Then the repository id should be rendered as read only.
|
|
750
|
+
RepositorySteps.getGDBIdInput()
|
|
751
|
+
.should('have.value', maintainedRepositoryId)
|
|
752
|
+
.and('be.disabled');
|
|
753
|
+
|
|
754
|
+
// And the action which unlocks the repository id field should not be available, because renaming
|
|
755
|
+
// a repository is allowed only for administrators and repository managers.
|
|
756
|
+
RepositorySteps.getRepositoryIdEditElement().should('not.exist');
|
|
757
|
+
|
|
758
|
+
// But the rest of the repository configuration should still be editable.
|
|
759
|
+
RepositorySteps.typeRepositoryTitle('Renaming is not allowed');
|
|
760
|
+
RepositorySteps.getSaveRepositoryButton().click();
|
|
761
|
+
ModalDialogSteps.clickOKButton();
|
|
762
|
+
|
|
763
|
+
// And the repository should keep its original id after the configuration is saved.
|
|
764
|
+
RepositorySteps.getRepositoryFromList(maintainedRepositoryId).should('be.visible');
|
|
765
|
+
RepositorySteps.getEditRepositoryButton(maintainedRepositoryId).should('be.visible');
|
|
766
|
+
});
|
|
767
|
+
});
|
|
413
768
|
|
|
414
769
|
function createUser(username, password, role, opts = {}) {
|
|
415
770
|
UserAndAccessSteps.clickCreateNewUserButton();
|
|
771
|
+
cy.url().should('include', '/user/create');
|
|
772
|
+
UserAndAccessSteps.getUsernameField().should('be.visible').and('be.enabled').and('not.be.disabled');
|
|
416
773
|
UserAndAccessSteps.typeUsername(username);
|
|
417
774
|
UserAndAccessSteps.typePassword(password);
|
|
418
775
|
UserAndAccessSteps.typeConfirmPasswordField(password);
|
|
@@ -421,8 +778,9 @@ describe('User and Access', () => {
|
|
|
421
778
|
|
|
422
779
|
if (role === '#roleUser') {
|
|
423
780
|
setRoles(opts);
|
|
424
|
-
|
|
425
|
-
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
if (role === ROLE_CUSTOM_ADMIN && opts.noPassword) {
|
|
426
784
|
UserAndAccessSteps.getNoPasswordCheckbox().check()
|
|
427
785
|
.then(() => {
|
|
428
786
|
UserAndAccessSteps.getNoPasswordCheckbox()
|
|
@@ -442,16 +800,8 @@ describe('User and Access', () => {
|
|
|
442
800
|
}
|
|
443
801
|
|
|
444
802
|
function setRoles(opts = {}) {
|
|
445
|
-
const {read = false, readWrite = false, graphql = false, repoName = '*'} = opts;
|
|
446
|
-
|
|
447
|
-
clickReadAccessForRepo(repoName);
|
|
448
|
-
}
|
|
449
|
-
if (readWrite) {
|
|
450
|
-
clickWriteAccessForRepo(repoName);
|
|
451
|
-
}
|
|
452
|
-
if (graphql) {
|
|
453
|
-
clickGraphqlAccessForRepo(repoName);
|
|
454
|
-
}
|
|
803
|
+
const {read = false, readWrite = false, graphql = false, maintain = false, repoName = '*'} = opts;
|
|
804
|
+
setUserAuths({repo: repoName, read, write: readWrite, graphql, maintain});
|
|
455
805
|
}
|
|
456
806
|
|
|
457
807
|
function testForUser(name, isAdmin) {
|
|
@@ -470,10 +820,10 @@ describe('User and Access', () => {
|
|
|
470
820
|
}
|
|
471
821
|
}
|
|
472
822
|
|
|
473
|
-
function
|
|
823
|
+
function assertUserAuthsInCatalog(username, {repo, read = false, write = false, maintain = false, graphql = false} = {}) {
|
|
474
824
|
UserAndAccessSteps.findUserRowAlias(username, 'userRow');
|
|
475
825
|
|
|
476
|
-
if (!read && !write) {
|
|
826
|
+
if (!read && !write && !maintain) {
|
|
477
827
|
return UserAndAccessSteps.getRepoLine('@userRow', repo).should('not.exist');
|
|
478
828
|
}
|
|
479
829
|
|
|
@@ -492,6 +842,12 @@ describe('User and Access', () => {
|
|
|
492
842
|
UserAndAccessSteps.findWriteIconAlias('@repoLine').should('not.exist');
|
|
493
843
|
}
|
|
494
844
|
|
|
845
|
+
if (maintain) {
|
|
846
|
+
UserAndAccessSteps.findMaintainIconAlias('@repoLine').should('be.visible');
|
|
847
|
+
} else {
|
|
848
|
+
UserAndAccessSteps.findMaintainIconAlias('@repoLine').should('not.exist');
|
|
849
|
+
}
|
|
850
|
+
|
|
495
851
|
if (graphql) {
|
|
496
852
|
UserAndAccessSteps.findGraphqlIconAlias('@repoLine').should('exist');
|
|
497
853
|
} else {
|
|
@@ -499,28 +855,56 @@ describe('User and Access', () => {
|
|
|
499
855
|
}
|
|
500
856
|
}
|
|
501
857
|
|
|
502
|
-
function
|
|
858
|
+
function setUserAuths({repo, read = false, write = false, graphql = false, maintain = false} = {}) {
|
|
503
859
|
if (read === true) {
|
|
504
860
|
UserAndAccessSteps.toggleReadAccessForRepo(repo);
|
|
861
|
+
UserAndAccessSteps.validateReadAccessForRepo(repo, {checked: read});
|
|
505
862
|
}
|
|
506
863
|
|
|
507
864
|
if (write === true) {
|
|
508
865
|
UserAndAccessSteps.toggleWriteAccessForRepo(repo);
|
|
866
|
+
UserAndAccessSteps.validateWriteAccessForRepo(repo, {checked: write});
|
|
509
867
|
}
|
|
510
868
|
|
|
511
869
|
if (graphql === true) {
|
|
512
870
|
UserAndAccessSteps.toggleGraphqlAccessForRepo(repo);
|
|
871
|
+
UserAndAccessSteps.validateGraphqlAccessForRepo(repo, {checked: graphql});
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
if (maintain === true) {
|
|
875
|
+
UserAndAccessSteps.toggleMaintainRepoForRepo(repo);
|
|
876
|
+
UserAndAccessSteps.validateMaintainAccessForRepo(repo, {checked: maintain});
|
|
513
877
|
}
|
|
514
878
|
}
|
|
515
879
|
|
|
880
|
+
function verifyCheckedUserAuth(repo, {read = false, write = false, graphql = false, maintain = false} = {}) {
|
|
881
|
+
UserAndAccessSteps.validateReadAccessForRepo(repo, {checked: read});
|
|
882
|
+
UserAndAccessSteps.validateWriteAccessForRepo(repo, {checked: write});
|
|
883
|
+
UserAndAccessSteps.validateGraphqlAccessForRepo(repo, {checked: graphql});
|
|
884
|
+
UserAndAccessSteps.validateMaintainAccessForRepo(repo, {checked: maintain});
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
function verifyDisabledUserAuth(repo, {read = false, write = false, graphql = false, maintain = false} = {}) {
|
|
888
|
+
UserAndAccessSteps.validateReadAccessForRepo(repo, {disabled: read});
|
|
889
|
+
UserAndAccessSteps.validateWriteAccessForRepo(repo, {disabled: write});
|
|
890
|
+
UserAndAccessSteps.validateGraphqlAccessForRepo(repo, {disabled: graphql});
|
|
891
|
+
UserAndAccessSteps.validateMaintainAccessForRepo(repo, {disabled: maintain});
|
|
892
|
+
}
|
|
893
|
+
|
|
516
894
|
function navigateMenuPath(pathArray, expectedUrl, expectedTitle) {
|
|
517
895
|
pathArray.forEach((label, index) => {
|
|
518
896
|
if (index === 0) {
|
|
519
897
|
MainMenuSteps.clickOnMenu(label);
|
|
898
|
+
if (pathArray.length > 1) {
|
|
899
|
+
MainMenuSteps.getSubmenuFor(label).scrollIntoView().should('be.visible');
|
|
900
|
+
}
|
|
520
901
|
} else {
|
|
521
902
|
MainMenuSteps.clickOnSubMenu(label);
|
|
903
|
+
}
|
|
904
|
+
if (index === pathArray.length - 1) {
|
|
905
|
+
// wait for the page label on the last navigation step to be visible before moving on
|
|
522
906
|
const title = expectedTitle ? expectedTitle : label;
|
|
523
|
-
cy.get('h1').should('contain', title);
|
|
907
|
+
cy.get('h1').should('be.visible').should('contain', title);
|
|
524
908
|
}
|
|
525
909
|
});
|
|
526
910
|
|
|
@@ -558,9 +942,6 @@ describe('User and Access', () => {
|
|
|
558
942
|
}
|
|
559
943
|
|
|
560
944
|
const noAuthChecks = {
|
|
561
|
-
'div[role="main]': [
|
|
562
|
-
'not.exist',
|
|
563
|
-
],
|
|
564
945
|
'.no-authority-panel .alert-warning': [
|
|
565
946
|
'be.visible',
|
|
566
947
|
['contains.text', 'Some functionalities are not available because'],
|
|
@@ -569,10 +950,6 @@ describe('User and Access', () => {
|
|
|
569
950
|
};
|
|
570
951
|
|
|
571
952
|
const hasAuthChecks = {
|
|
572
|
-
'div[role="main"]': [
|
|
573
|
-
'exist',
|
|
574
|
-
'be.visible',
|
|
575
|
-
],
|
|
576
953
|
'.no-authority-panel .alert-warning': [
|
|
577
954
|
'not.exist',
|
|
578
955
|
],
|
|
@@ -813,13 +1190,5 @@ describe('User and Access', () => {
|
|
|
813
1190
|
expectedUrl: '/sparql-templates',
|
|
814
1191
|
checks: noAuthChecks,
|
|
815
1192
|
},
|
|
816
|
-
|
|
817
|
-
// 7) Help
|
|
818
|
-
{
|
|
819
|
-
path: ['Help', 'REST API'],
|
|
820
|
-
expectedUrl: '/webapi',
|
|
821
|
-
expectedTitle: 'REST API documentation',
|
|
822
|
-
checks: hasAuthChecks,
|
|
823
|
-
},
|
|
824
1193
|
];
|
|
825
1194
|
});
|