Skip to content

Commit 4f51ee2

Browse files
ArrgentumArrgentumgithub-actions[bot]
authored
demo manager controller check permission in backend (#1688)
## Whats added: - Add check to permission in backend ## Issue(#1676) * Update backend-api-docs.json Co-authored-by: Arrgentum <alexeyvotintsev@yandex.ru> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent 76902ca commit 4f51ee2

2 files changed

Lines changed: 161 additions & 32 deletions

File tree

save-backend/backend-api-docs.json

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1803,6 +1803,26 @@
18031803
}
18041804
},
18051805
"description": "Successfully fetched demo status."
1806+
},
1807+
"403": {
1808+
"content": {
1809+
"*/*": {
1810+
"schema": {
1811+
"$ref": "#/components/schemas/DemoInfo"
1812+
}
1813+
}
1814+
},
1815+
"description": "Not enough permission for accessing given project."
1816+
},
1817+
"404": {
1818+
"content": {
1819+
"*/*": {
1820+
"schema": {
1821+
"$ref": "#/components/schemas/DemoInfo"
1822+
}
1823+
}
1824+
},
1825+
"description": "Could not find project in organization or demo for it."
18061826
}
18071827
},
18081828
"summary": "Get demo info.",
@@ -1854,6 +1874,15 @@
18541874
"responses": {
18551875
"200": {
18561876
"description": "Successfully added demo."
1877+
},
1878+
"403": {
1879+
"description": "Not enough permission for accessing given project."
1880+
},
1881+
"404": {
1882+
"description": "Could not find project in organization."
1883+
},
1884+
"409": {
1885+
"description": "Please provide github repository"
18571886
}
18581887
},
18591888
"summary": "Add demo for a tool.",
@@ -1908,6 +1937,38 @@
19081937
}
19091938
},
19101939
"description": "Successfully fetched demo status."
1940+
},
1941+
"403": {
1942+
"content": {
1943+
"*/*": {
1944+
"schema": {
1945+
"type": "string",
1946+
"enum": [
1947+
"NOT_CREATED",
1948+
"RUNNING",
1949+
"STARTING",
1950+
"STOPPED"
1951+
]
1952+
}
1953+
}
1954+
},
1955+
"description": "Not enough permission for accessing given project."
1956+
},
1957+
"404": {
1958+
"content": {
1959+
"*/*": {
1960+
"schema": {
1961+
"type": "string",
1962+
"enum": [
1963+
"NOT_CREATED",
1964+
"RUNNING",
1965+
"STARTING",
1966+
"STOPPED"
1967+
]
1968+
}
1969+
}
1970+
},
1971+
"description": "Could not find project in organization or demo for it."
19111972
}
19121973
},
19131974
"summary": "Get demo status.",
@@ -1948,6 +2009,12 @@
19482009
"type": "string"
19492010
}
19502011
},
2012+
{
2013+
"description": "a file to upload",
2014+
"in": "query",
2015+
"name": "file",
2016+
"required": true
2017+
},
19512018
{
19522019
"example": "basic",
19532020
"in": "header",
@@ -1963,7 +2030,8 @@
19632030
"properties": {
19642031
"file": {
19652032
"type": "string",
1966-
"format": "binary"
2033+
"format": "binary",
2034+
"description": "a file to upload"
19672035
}
19682036
},
19692037
"required": [
@@ -1984,6 +2052,28 @@
19842052
}
19852053
},
19862054
"description": "Successfully added demo."
2055+
},
2056+
"403": {
2057+
"content": {
2058+
"*/*": {
2059+
"schema": {
2060+
"type": "integer",
2061+
"format": "int64"
2062+
}
2063+
}
2064+
},
2065+
"description": "Not enough permission for accessing given project."
2066+
},
2067+
"404": {
2068+
"content": {
2069+
"*/*": {
2070+
"schema": {
2071+
"type": "integer",
2072+
"format": "int64"
2073+
}
2074+
}
2075+
},
2076+
"description": "Could not find project in organization."
19872077
}
19882078
},
19892079
"summary": "Attach file to demo.",

save-backend/src/main/kotlin/com/saveourtool/save/backend/controllers/DemoManagerController.kt

Lines changed: 70 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
package com.saveourtool.save.backend.controllers
22

33
import com.saveourtool.save.backend.configs.ConfigProperties
4+
import com.saveourtool.save.backend.security.ProjectPermissionEvaluator
45
import com.saveourtool.save.backend.service.LnkProjectGithubService
56
import com.saveourtool.save.backend.service.ProjectService
67
import com.saveourtool.save.configs.RequiresAuthorizationSourceHeader
78
import com.saveourtool.save.demo.DemoDto
89
import com.saveourtool.save.demo.DemoInfo
910
import com.saveourtool.save.demo.DemoStatus
11+
import com.saveourtool.save.permission.Permission
1012
import com.saveourtool.save.spring.utils.applyAll
11-
import com.saveourtool.save.utils.EmptyResponse
12-
import com.saveourtool.save.utils.blockingToMono
13+
import com.saveourtool.save.utils.*
1314
import com.saveourtool.save.utils.switchIfEmptyToNotFound
14-
import com.saveourtool.save.utils.switchIfEmptyToResponseException
1515
import com.saveourtool.save.v1
1616

1717
import io.swagger.v3.oas.annotations.Operation
@@ -39,6 +39,7 @@ import reactor.core.publisher.Mono
3939
class DemoManagerController(
4040
private val projectService: ProjectService,
4141
private val lnkProjectGithubService: LnkProjectGithubService,
42+
private val projectPermissionEvaluator: ProjectPermissionEvaluator,
4243
configProperties: ConfigProperties,
4344
customizers: List<WebClientCustomizer>,
4445
) {
@@ -60,6 +61,9 @@ class DemoManagerController(
6061
description = "Add demo for a tool.",
6162
)
6263
@ApiResponse(responseCode = "200", description = "Successfully added demo.")
64+
@ApiResponse(responseCode = "403", description = "Not enough permission for accessing given project.")
65+
@ApiResponse(responseCode = "404", description = "Could not find project in organization.")
66+
@ApiResponse(responseCode = "409", description = "Please provide github repository")
6367
fun addDemo(
6468
@PathVariable organizationName: String,
6569
@PathVariable projectName: String,
@@ -74,6 +78,9 @@ class DemoManagerController(
7478
.switchIfEmptyToNotFound {
7579
"Could not find project $projectName in organization $organizationName."
7680
}
81+
.requireOrSwitchToResponseException({ projectPermissionEvaluator.hasPermission(authentication, this, Permission.DELETE) }, HttpStatus.FORBIDDEN) {
82+
"Not enough permission for accessing given project."
83+
}
7784
.flatMap { project ->
7885
blockingToMono {
7986
demoDto.githubProjectCoordinates?.let { githubCoordinates ->
@@ -105,13 +112,16 @@ class DemoManagerController(
105112
Parameter(name = "organizationName", `in` = ParameterIn.PATH, description = "name of saveourtool organization", required = true),
106113
Parameter(name = "projectName", `in` = ParameterIn.PATH, description = "name of saveourtool project", required = true),
107114
Parameter(name = "version", `in` = ParameterIn.QUERY, description = "version to attach the file to", required = true),
115+
Parameter(name = "file", `in` = ParameterIn.DEFAULT, description = "a file to upload", required = true),
108116
)
109117
@Operation(
110118
method = "POST",
111119
summary = "Attach file to demo.",
112120
description = "Attach file to demo.",
113121
)
114122
@ApiResponse(responseCode = "200", description = "Successfully added demo.")
123+
@ApiResponse(responseCode = "403", description = "Not enough permission for accessing given project.")
124+
@ApiResponse(responseCode = "404", description = "Could not find project in organization.")
115125
fun uploadFile(
116126
@PathVariable organizationName: String,
117127
@PathVariable projectName: String,
@@ -127,6 +137,9 @@ class DemoManagerController(
127137
.switchIfEmptyToNotFound {
128138
"Could not find project $projectName in organization $organizationName."
129139
}
140+
.requireOrSwitchToResponseException({ projectPermissionEvaluator.hasPermission(authentication, this, Permission.DELETE) }, HttpStatus.FORBIDDEN) {
141+
"Not enough permission for accessing given project."
142+
}
130143
.flatMap {
131144
webClientDemo.post()
132145
.uri("/demo/internal/$organizationName/$projectName/upload-file?version=$version")
@@ -148,23 +161,36 @@ class DemoManagerController(
148161
description = "Get demo status.",
149162
)
150163
@ApiResponse(responseCode = "200", description = "Successfully fetched demo status.")
164+
@ApiResponse(responseCode = "403", description = "Not enough permission for accessing given project.")
165+
@ApiResponse(responseCode = "404", description = "Could not find project in organization or demo for it.")
151166
fun getDemoStatus(
152167
@PathVariable organizationName: String,
153168
@PathVariable projectName: String,
154169
authentication: Authentication,
155-
): Mono<DemoStatus> = webClientDemo.get()
156-
.uri("/demo/internal/$organizationName/$projectName/status")
157-
.retrieve()
158-
.onStatus({ !it.is2xxSuccessful }) {
159-
Mono.error(
160-
ResponseStatusException(
161-
HttpStatus.NOT_FOUND,
162-
"Demo for $organizationName/$projectName is not found.",
163-
)
164-
)
170+
): Mono<DemoStatus> = blockingToMono {
171+
projectService.findByNameAndOrganizationNameAndCreatedStatus(projectName, organizationName)
172+
}
173+
.switchIfEmptyToNotFound {
174+
"Could not find project $projectName in organization $organizationName."
175+
}
176+
.requireOrSwitchToResponseException({ projectPermissionEvaluator.hasPermission(authentication, this, Permission.READ) }, HttpStatus.FORBIDDEN) {
177+
"Not enough permission for accessing given project."
178+
}
179+
.flatMap {
180+
webClientDemo.get()
181+
.uri("/demo/internal/$organizationName/$projectName/status")
182+
.retrieve()
183+
.onStatus({ !it.is2xxSuccessful }) {
184+
Mono.error(
185+
ResponseStatusException(
186+
HttpStatus.NOT_FOUND,
187+
"Demo for $organizationName/$projectName is not found.",
188+
)
189+
)
190+
}
191+
.bodyToMono<DemoStatus>()
192+
.defaultIfEmpty(DemoStatus.NOT_CREATED)
165193
}
166-
.bodyToMono<DemoStatus>()
167-
.defaultIfEmpty(DemoStatus.NOT_CREATED)
168194

169195
@GetMapping("/{organizationName}/{projectName}")
170196
@RequiresAuthorizationSourceHeader
@@ -179,26 +205,39 @@ class DemoManagerController(
179205
description = "Get demo info.",
180206
)
181207
@ApiResponse(responseCode = "200", description = "Successfully fetched demo status.")
208+
@ApiResponse(responseCode = "403", description = "Not enough permission for accessing given project.")
209+
@ApiResponse(responseCode = "404", description = "Could not find project in organization or demo for it.")
182210
fun getDemoInfo(
183211
@PathVariable organizationName: String,
184212
@PathVariable projectName: String,
185213
authentication: Authentication,
186-
): Mono<DemoInfo> = webClientDemo.get()
187-
.uri("/demo/internal/$organizationName/$projectName")
188-
.retrieve()
189-
.onStatus({ !it.is2xxSuccessful }) {
190-
Mono.error(
191-
ResponseStatusException(
192-
HttpStatus.NOT_FOUND,
193-
"Demo for $organizationName/$projectName is not found.",
214+
): Mono<DemoInfo> = blockingToMono {
215+
projectService.findByNameAndOrganizationNameAndCreatedStatus(projectName, organizationName)
216+
}
217+
.switchIfEmptyToNotFound {
218+
"Could not find project $projectName in organization $organizationName."
219+
}
220+
.requireOrSwitchToResponseException({ projectPermissionEvaluator.hasPermission(authentication, this, Permission.WRITE) }, HttpStatus.FORBIDDEN) {
221+
"Not enough permission for accessing given project."
222+
}
223+
.flatMap {
224+
webClientDemo.get()
225+
.uri("/demo/internal/$organizationName/$projectName")
226+
.retrieve()
227+
.onStatus({ !it.is2xxSuccessful }) {
228+
Mono.error(
229+
ResponseStatusException(
230+
HttpStatus.NOT_FOUND,
231+
"Demo for $organizationName/$projectName is not found.",
232+
)
233+
)
234+
}
235+
.bodyToMono<DemoInfo>()
236+
.defaultIfEmpty(
237+
DemoInfo(
238+
DemoDto.emptyForProject(organizationName, projectName),
239+
DemoStatus.NOT_CREATED,
240+
)
194241
)
195-
)
196242
}
197-
.bodyToMono<DemoInfo>()
198-
.defaultIfEmpty(
199-
DemoInfo(
200-
DemoDto.emptyForProject(organizationName, projectName),
201-
DemoStatus.NOT_CREATED,
202-
)
203-
)
204243
}

0 commit comments

Comments
 (0)