Skip to content

Commit 77f43f6

Browse files
authored
Merge branch 'main' into feature/gsk-1486-in-catalog-tests-each-test-is-in-2-copies-the-only-diff-is
2 parents b8645cd + 770acad commit 77f43f6

45 files changed

Lines changed: 1561 additions & 851 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

backend/src/main/java/ai/giskard/security/PermissionEvaluator.java

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,6 @@ public boolean isCurrentUser(String login) {
2626
return login.equals(SecurityUtils.getCurrentAuthenticatedUserLogin());
2727
}
2828

29-
/**
30-
* Determine if a user can write a project, i.e. is admin or is project's owner
31-
*
32-
* @param id id of the project
33-
* @return true if the user can write
34-
*/
35-
public boolean canWriteProject(@NotNull Long id) {
36-
Project project = this.projectRepository.getMandatoryById(id);
37-
38-
return isCurrentUser(project.getOwner().getLogin()) || SecurityUtils.isCurrentUserAdmin();
39-
}
4029

4130
/**
4231
* Determine if the current user is a guest of a project and is granted any of the required roles
@@ -51,9 +40,40 @@ public boolean isGuestWithAnyRole(@NotNull Long projectId, @NotBlank String... r
5140
return SecurityUtils.hasCurrentUserAnyOfAuthorities(roles) && isCurrentUserGuest(project);
5241
}
5342

43+
/**
44+
* Determine if a user can write a project, i.e. is admin or is project's owner
45+
*
46+
* @param project project to check
47+
* @return true if the user can write
48+
*/
49+
public boolean canWriteProject(@NotNull Project project) {
50+
return (isCurrentUserGuest(project) && this.canWrite()) || isCurrentUser(project.getOwner().getLogin()) || SecurityUtils.isCurrentUserAdmin();
51+
}
52+
53+
/**
54+
* Determine if a user can write a project, i.e. is admin or is project's owner
55+
*
56+
* @param id id of the project
57+
* @return true if the user can write
58+
*/
59+
public boolean canWriteProjectId(@NotNull Long id) {
60+
Project project = this.projectRepository.findById(id)
61+
.orElseThrow(() -> new EntityNotFoundException(Entity.PROJECT, id));
62+
63+
return canWriteProject(project);
64+
}
65+
66+
/**
67+
* Determine if a user can write a project, i.e. is admin or is project's owner
68+
*
69+
* @param projectKey key of the project
70+
* @return true if the user can write
71+
*/
5472
public boolean canWriteProjectKey(@NotNull String projectKey) {
55-
Project project = this.projectRepository.findOneByKey(projectKey).orElseThrow(() -> new EntityNotFoundException(Entity.PROJECT, projectKey));
56-
return (isCurrentUser(project.getOwner().getLogin()) || SecurityUtils.isCurrentUserAdmin());
73+
Project project = this.projectRepository.findOneByKey(projectKey)
74+
.orElseThrow(() -> new EntityNotFoundException(Entity.PROJECT, projectKey));
75+
76+
return canWriteProject(project);
5777
}
5878

5979
/**
@@ -87,7 +107,7 @@ public void validateCanReadProject(@NotNull Long id) {
87107
}
88108

89109
public void validateCanWriteProject(@NotNull Long id) {
90-
if (!canWriteProject(id)) {
110+
if (!canWriteProjectId(id)) {
91111
throw new AccessDeniedException("Access denied to project id " + id);
92112
}
93113
}

backend/src/main/java/ai/giskard/service/UserDeletionService.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ public void enableUser(String login) {
9999
.findOneByLogin(login)
100100
.ifPresentOrElse(user -> {
101101
user.setEnabled(true);
102+
userRepository.save(user);
102103
log.info("Enable user : {}", user);
103104
},
104105
() -> log.warn("Cannot enable user because its login wasn't found : {}", login));

backend/src/main/java/ai/giskard/web/rest/controllers/ProjectController.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public List<ProjectDTO> list() throws NotInDatabaseException {
5454
* @param id id of the existing project
5555
* @return updated project
5656
*/
57-
@PreAuthorize("@permissionEvaluator.canWriteProject( #id)")
57+
@PreAuthorize("@permissionEvaluator.canWriteProjectId( #id)")
5858
@PutMapping(value = "/project/{id}")
5959
public ProjectDTO updateProject(@RequestBody ProjectPostDTO projectDTO, @PathVariable("id") Long id) {
6060
Project updatedProject = this.projectService.update(id, projectDTO);
@@ -102,7 +102,7 @@ public ProjectDTO getProject(@RequestParam(value = "id", required = false) Long
102102
* @return msg Deleted if deleted
103103
*/
104104
@DeleteMapping(value = "/project/{id}")
105-
@PreAuthorize("@permissionEvaluator.canWriteProject( #id)")
105+
@PreAuthorize("@permissionEvaluator.canWriteProjectId( #id)")
106106
public void delete(@PathVariable("id") Long id) {
107107
this.projectService.delete(id);
108108
}
@@ -115,7 +115,7 @@ public void delete(@PathVariable("id") Long id) {
115115
* @return updated project
116116
*/
117117
@DeleteMapping(value = "/project/{id}/guests/{userId}")
118-
@PreAuthorize("@permissionEvaluator.canWriteProject( #id)")
118+
@PreAuthorize("@permissionEvaluator.canWriteProjectId( #id)")
119119
public ProjectDTO uninvite(@PathVariable("id") Long id, @PathVariable("userId") Long userId) {
120120
Project project = this.projectService.uninvite(id, userId);
121121
return giskardMapper.projectToProjectDTO(project);
@@ -128,7 +128,7 @@ public ProjectDTO uninvite(@PathVariable("id") Long id, @PathVariable("userId")
128128
* @param userId user's id
129129
* @return project updated
130130
*/
131-
@PreAuthorize("@permissionEvaluator.canWriteProject( #id)")
131+
@PreAuthorize("@permissionEvaluator.canWriteProjectId( #id)")
132132
@PutMapping(value = "/project/{id}/guests/{userId}")
133133
@Transactional
134134
public ProjectDTO invite(@PathVariable("id") Long id, @PathVariable("userId") Long userId) {

backend/src/main/java/ai/giskard/web/rest/controllers/TestFunctionController.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@ public class TestFunctionController {
2121
private final TestFunctionRepository testFunctionRepository;
2222
private final TestFunctionService testFunctionService;
2323

24-
@GetMapping("/tests/{testUuid}")
24+
@GetMapping({"/tests/{testUuid}", "/project/{projectKey}/tests/{testUuid}"})
2525
@Transactional(readOnly = true)
2626
public TestFunctionDTO getTestFunction(@PathVariable("testUuid") @NotNull UUID testUuid) {
2727
return giskardMapper.toDTO(testFunctionRepository.getMandatoryById(testUuid));
2828
}
2929

30-
@PutMapping("/tests/{testUuid}")
30+
@PutMapping({"/tests/{testUuid}", "/project/{projectKey}/tests/{testUuid}"})
3131
@Transactional
3232
public TestFunctionDTO updateTestFunction(@PathVariable("testUuid") @NotNull UUID testUuid,
3333
@Valid @RequestBody TestFunctionDTO testFunction) {

backend/src/main/java/ai/giskard/web/rest/controllers/testing/TestSuiteController.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ public TestSuiteCompleteDTO listTestSuite(@PathVariable("projectId") @NotNull Lo
9797
}
9898

9999
@PostMapping("project/{projectId}/suite/{suiteId}/test")
100-
@PreAuthorize("@permissionEvaluator.canWriteProject(#projectId)")
100+
@PreAuthorize("@permissionEvaluator.canWriteProjectId(#projectId)")
101101
@Transactional
102102
public TestSuiteDTO addTestToSuite(@PathVariable("projectId") long projectId,
103103
@PathVariable("suiteId") long suiteId,
@@ -128,7 +128,7 @@ public TestSuiteExecutionDTO tryTestSuite(@PathVariable("projectId") @NotNull Lo
128128

129129

130130
@PutMapping("project/{projectId}/suite/{suiteId}/test/{testId}/inputs")
131-
@PreAuthorize("@permissionEvaluator.canWriteProject(#projectId)")
131+
@PreAuthorize("@permissionEvaluator.canWriteProjectId(#projectId)")
132132
@Transactional
133133
public TestSuiteDTO updateTestInputs(@PathVariable("projectId") long projectId,
134134
@PathVariable("suiteId") long suiteId,

backend/src/test/java/ai/giskard/service/PermissionUT.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ void canWriteAITESTER() {
100100
@WithMockUser(username = ADMIN_KEY, authorities = AuthoritiesConstants.ADMIN)
101101
void canWriteProjectADMIN() {
102102
Project project = projectRepository.getOneByName(initService.getProjectByCreatorLogin(ADMIN_KEY));
103-
assertThat(permissionEvaluator.canWriteProject(project.getId())).isTrue();
103+
assertThat(permissionEvaluator.canWriteProjectId(project.getId())).isTrue();
104104
}
105105

106106
/**
@@ -110,7 +110,7 @@ void canWriteProjectADMIN() {
110110
@WithMockUser(username = AI_TESTER_KEY, authorities = AuthoritiesConstants.AITESTER)
111111
void canWriteProjectAITESTER() {
112112
Project project = projectRepository.getOneByName(initService.getProjectByCreatorLogin(AI_TESTER_KEY));
113-
assertThat(permissionEvaluator.canWriteProject(project.getId())).isTrue();
113+
assertThat(permissionEvaluator.canWriteProjectId(project.getId())).isTrue();
114114
}
115115

116116
/**
@@ -120,7 +120,7 @@ void canWriteProjectAITESTER() {
120120
@WithMockUser(username = AI_CREATOR_KEY, authorities = AuthoritiesConstants.AICREATOR)
121121
void canWriteProjectAICREATOR() {
122122
Project project = projectRepository.getOneByName(initService.getProjectByCreatorLogin(AI_CREATOR_KEY));
123-
assertThat(permissionEvaluator.canWriteProject(project.getId())).isTrue();
123+
assertThat(permissionEvaluator.canWriteProjectId(project.getId())).isTrue();
124124
}
125125

126126

@@ -131,7 +131,7 @@ void canWriteProjectAICREATOR() {
131131
@WithMockUser(username = ADMIN_KEY, authorities = AuthoritiesConstants.ADMIN)
132132
void canWriteOtherProjectADMIN() {
133133
Project project = projectRepository.getOneByName(initService.getProjectByCreatorLogin(AI_TESTER_KEY));
134-
assertThat(permissionEvaluator.canWriteProject(project.getId())).isTrue();
134+
assertThat(permissionEvaluator.canWriteProjectId(project.getId())).isTrue();
135135
}
136136

137137
/**
@@ -141,7 +141,7 @@ void canWriteOtherProjectADMIN() {
141141
@WithMockUser(username = AI_TESTER_KEY, authorities = AuthoritiesConstants.AITESTER)
142142
void canWriteOtherProjectAITESTER() {
143143
Project project = projectRepository.getOneByName(initService.getProjectByCreatorLogin(AI_CREATOR_KEY));
144-
assertThat(permissionEvaluator.canWriteProject(project.getId())).isFalse();
144+
assertThat(permissionEvaluator.canWriteProjectId(project.getId())).isFalse();
145145
}
146146

147147
/**
@@ -151,7 +151,7 @@ void canWriteOtherProjectAITESTER() {
151151
@WithMockUser(username = AI_CREATOR_KEY, authorities = AuthoritiesConstants.AICREATOR)
152152
void canWriteOtherProjectAICREATOR() {
153153
Project project = projectRepository.getOneByName(initService.getProjectByCreatorLogin(AI_TESTER_KEY));
154-
assertThat(permissionEvaluator.canWriteProject(project.getId())).isFalse();
154+
assertThat(permissionEvaluator.canWriteProjectId(project.getId())).isFalse();
155155
}
156156

157157

@@ -172,7 +172,7 @@ void canReadProjectADMIN() {
172172
@WithMockUser(username = AI_CREATOR_KEY, authorities = AuthoritiesConstants.AICREATOR)
173173
void canReadProjectAICREATOR() {
174174
Project project = projectRepository.getOneByName(initService.getProjectByCreatorLogin(AI_CREATOR_KEY));
175-
assertThat(permissionEvaluator.canWriteProject(project.getId())).isTrue();
175+
assertThat(permissionEvaluator.canWriteProjectId(project.getId())).isTrue();
176176
}
177177

178178
/**
@@ -182,7 +182,7 @@ void canReadProjectAICREATOR() {
182182
@WithMockUser(username = AI_TESTER_KEY, authorities = AuthoritiesConstants.AITESTER)
183183
void canReadProjectAITESTER() {
184184
Project project = projectRepository.getOneByName(initService.getProjectByCreatorLogin(AI_TESTER_KEY));
185-
assertThat(permissionEvaluator.canWriteProject(project.getId())).isTrue();
185+
assertThat(permissionEvaluator.canWriteProjectId(project.getId())).isTrue();
186186
}
187187

188188
/**
@@ -202,7 +202,7 @@ void canReadAnotherProjectADMIN() {
202202
@WithMockUser(username = AI_CREATOR_KEY, authorities = AuthoritiesConstants.AICREATOR)
203203
void canReadAnotherProjectAICREATOR() {
204204
Project project = projectRepository.getOneByName(initService.getProjectByCreatorLogin(AI_CREATOR_KEY));
205-
assertThat(permissionEvaluator.canWriteProject(project.getId())).isTrue();
205+
assertThat(permissionEvaluator.canWriteProjectId(project.getId())).isTrue();
206206
}
207207

208208
/**
@@ -212,7 +212,7 @@ void canReadAnotherProjectAICREATOR() {
212212
@WithMockUser(username = AI_TESTER_KEY, authorities = AuthoritiesConstants.AITESTER)
213213
void canReadAnotherProjectAITESTER() {
214214
Project project = projectRepository.getOneByName(initService.getProjectByCreatorLogin(ADMIN_KEY));
215-
assertThat(permissionEvaluator.canWriteProject(project.getId())).isFalse();
215+
assertThat(permissionEvaluator.canWriteProjectId(project.getId())).isFalse();
216216
}
217217

218218
/**

frontend/src/socket.ts

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,38 @@
1-
import {reactive} from 'vue';
2-
import {Client, Frame} from '@stomp/stompjs';
3-
import {apiURL} from './env';
4-
import {getLocalToken, httpUrlToWsUrl} from './utils';
5-
import {useMainStore} from './stores/main';
6-
import {TYPE} from 'vue-toastification';
1+
import { reactive } from 'vue';
2+
import { Client, Frame } from '@stomp/stompjs';
3+
import { apiURL } from './env';
4+
import { getLocalToken, httpUrlToWsUrl } from './utils';
5+
import { useMainStore } from './stores/main';
6+
import { TYPE } from 'vue-toastification';
77

88
export const state = reactive({
99
workerStatus: {
10-
connected: false,
10+
connected: undefined,
1111
},
1212
});
13-
let jwtToken = getLocalToken() || "";
13+
let jwtToken = getLocalToken() || '';
1414
export const client = new Client({
1515
onStompError: async (frame: Frame) => {
1616
if (frame.headers.message.includes('AccessDeniedException')) {
17-
await client.deactivate()
18-
useMainStore().addNotification({content: "Failed to establish websocket connection.", color: TYPE.ERROR});
19-
console.error(`Failed to establish websocket connection: ${frame.headers.message}`)
17+
await client.deactivate();
18+
useMainStore().addNotification({ content: 'Failed to establish websocket connection.', color: TYPE.ERROR });
19+
console.error(`Failed to establish websocket connection: ${frame.headers.message}`);
2020
}
2121
},
22-
connectHeaders: {jwt: jwtToken},
22+
connectHeaders: { jwt: jwtToken },
2323
brokerURL: httpUrlToWsUrl(apiURL) + '/websocket',
2424
onConnect: () => {
2525
client.subscribe('/topic/worker-status', message => {
2626
const data = JSON.parse(message.body);
2727

28-
if (!state.workerStatus.connected && data.connected) {
28+
if (state.workerStatus.connected === false && data.connected === true) {
2929
useMainStore().addNotification({
3030
content: 'ML Worker is connected!',
3131
color: TYPE.SUCCESS,
3232
});
3333
}
3434

35-
if (state.workerStatus.connected && !data.connected) {
35+
if (state.workerStatus.connected === true && data.connected === false) {
3636
useMainStore().addNotification({
3737
content: 'ML Worker is disconnected!',
3838
color: TYPE.ERROR,

0 commit comments

Comments
 (0)