Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into feature/cosv-on-cre…
Browse files Browse the repository at this point in the history
…ating#2532
  • Loading branch information
nulls committed Oct 18, 2023
2 parents b09289a + bfdb7f8 commit ed8047d
Show file tree
Hide file tree
Showing 20 changed files with 272 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ enum class FrontendRoutes(val path: String) {
INDEX(""),
MANAGE_ORGANIZATIONS("organizations"),
NOT_FOUND("not-found"),
PROFILE("profile"),
PROJECTS("projects"),
REGISTRATION("registration"),
SANDBOX("sandbox"),
Expand All @@ -48,6 +47,7 @@ enum class FrontendRoutes(val path: String) {
VULNERABILITIES("$VULN/list"),
VULNERABILITY_SINGLE("$VULN/collection"),
VULN_COSV_SCHEMA("$VULN/schema"),
VULN_PROFILE("$VULN/profile"),
VULN_TOP_RATING("$VULN/top-rating"),
;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import com.saveourtool.save.storage.concatS3Key
import com.saveourtool.save.utils.*
import com.saveourtool.save.v1
import org.reactivestreams.Publisher
import org.springframework.dao.DataIntegrityViolationException
import org.springframework.data.domain.PageRequest
import org.springframework.http.HttpHeaders
import org.springframework.http.HttpStatus
Expand All @@ -21,9 +22,11 @@ import org.springframework.http.ResponseEntity
import org.springframework.http.codec.multipart.FilePart
import org.springframework.security.core.Authentication
import org.springframework.web.bind.annotation.*
import org.springframework.web.server.ResponseStatusException
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono
import reactor.core.scheduler.Schedulers
import java.nio.ByteBuffer
import java.nio.file.Files
import kotlin.io.path.*

Expand Down Expand Up @@ -115,7 +118,7 @@ class RawCosvFileController(
contentLength = contentLength,
)
val content = filePart.content().map { it.asByteBuffer() }
return rawCosvFileStorage.upload(key, content)
return rawCosvFileStorage.uploadAndWrapDuplicateKeyException(key, content)
}

/**
Expand Down Expand Up @@ -183,7 +186,7 @@ class RawCosvFileController(
"Processing ${file.absolutePathString()}"
}
val contentLength = file.fileSize()
rawCosvFileStorage.upload(
rawCosvFileStorage.uploadAndWrapDuplicateKeyException(
key = RawCosvFileDto(
concatS3Key(archiveFile.fileName, file.relativeTo(contentDir).toString()),
organizationName = organizationName,
Expand Down Expand Up @@ -414,5 +417,20 @@ class RawCosvFileController(

// to show progress bar
private val firstFakeResponse = UnzipRawCosvFileResponse(5, 100, updateCounters = true)

private fun RawCosvFileStorage.uploadAndWrapDuplicateKeyException(
key: RawCosvFileDto,
content: Flux<ByteBuffer>,
): Mono<RawCosvFileDto> {
val result = key.contentLength?.let {
upload(key, it, content)
} ?: upload(key, content)
return result.onErrorResume { error ->
when (error) {
is DataIntegrityViolationException -> Mono.error(ResponseStatusException(HttpStatus.BAD_REQUEST, "Duplicate file name ${key.fileName}", error))
else -> Mono.error(error)
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,15 @@ class RawCosvFileS3KeyManager(
}

@Transactional
override fun updateKeyByContentLength(key: RawCosvFileDto, contentLength: Long): RawCosvFileDto =
key.contentLength?.let {
repository.getByIdOrNotFound(key.requiredId())
.let { entity ->
repository.save(entity.apply { this.contentLength = contentLength }).toDto()
}
} ?: key
override fun updateKeyByContentLength(
key: RawCosvFileDto,
contentLength: Long,
): RawCosvFileDto = key.contentLength
?.let { key }
?: run {
repository.getByIdOrNotFound(key.requiredId())
.let { entity ->
repository.save(entity.apply { this.contentLength = contentLength }).toDto()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,8 @@ import com.saveourtool.save.storage.DefaultStorageProjectReactor
import com.saveourtool.save.storage.ReactiveStorageWithDatabase
import com.saveourtool.save.storage.deleteUnexpectedKeys
import com.saveourtool.save.utils.*
import org.springframework.dao.DataIntegrityViolationException
import org.springframework.data.domain.PageRequest
import org.springframework.http.HttpStatus
import org.springframework.stereotype.Component
import org.springframework.web.server.ResponseStatusException
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono
import java.nio.ByteBuffer
Expand Down Expand Up @@ -54,18 +51,6 @@ class RawCosvFileStorage(
}
.publishOn(s3Operations.scheduler)

override fun upload(key: RawCosvFileDto, content: Flux<ByteBuffer>): Mono<RawCosvFileDto> {
val result = key.contentLength?.let {
upload(key, it, content)
} ?: super.upload(key, content)
return result.onErrorResume { error ->
when (error) {
is DataIntegrityViolationException -> Mono.error(ResponseStatusException(HttpStatus.BAD_REQUEST, "Duplicate file name ${key.fileName}", error))
else -> Mono.error(error)
}
}
}

/**
* @param organizationName
* @param userName
Expand Down
1 change: 1 addition & 0 deletions save-frontend/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ kotlin {
implementation(npm("react-avatar-image-cropper", "^1.4.2"))
implementation(npm("react-circle", "^1.1.1"))
implementation(npm("react-diff-viewer-continued", "^3.2.6"))
implementation(npm("react-json-view", "^1.21.3"))
implementation(npm("multi-range-slider-react", "^2.0.5"))
// react-sigma
implementation(npm("@react-sigma/core", "^3.1.0"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ fun ChildrenBuilder.renderAvatar(
isLinkActive: Boolean = true,
styleBuilder: CSSProperties.() -> Unit,
) {
val newLink = (link ?: "/${FrontendRoutes.PROFILE}/${userInfo?.name}").takeIf { userInfo?.status != UserStatus.DELETED && isLinkActive }
val newLink = (link ?: "/${FrontendRoutes.VULN_PROFILE}/${userInfo?.name}").takeIf { userInfo?.status != UserStatus.DELETED && isLinkActive }
return renderAvatar(
userInfo?.avatar?.avatarRenderer() ?: AVATAR_PROFILE_PLACEHOLDER,
classes,
Expand Down Expand Up @@ -151,7 +151,7 @@ fun ChildrenBuilder.renderUserAvatarWithName(
}
return if (userInfo.status != UserStatus.DELETED) {
Link {
to = "/${FrontendRoutes.PROFILE}/${userInfo.name}"
to = "/${FrontendRoutes.VULN_PROFILE}/${userInfo.name}"
renderImg()
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ private fun ChildrenBuilder.renderLeftColumn(
width = 80.0
onError = { setAvatar(AVATAR_PLACEHOLDER) }
}
to = "/${FrontendRoutes.PROFILE}/$name"
to = "/${FrontendRoutes.VULN_PROFILE}/$name"
}
}
div {
Expand All @@ -230,7 +230,7 @@ private fun ChildrenBuilder.renderLeftColumn(
h1 {
className = ClassName("col-12 text-center font-weight-bold h5")
Link {
to = "/${FrontendRoutes.PROFILE}/$name"
to = "/${FrontendRoutes.VULN_PROFILE}/$name"
+name
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ val userBoard: FC<UserBoardProps> = FC { props ->
div {
className = ClassName(props.avatarOuterClasses.orEmpty())
figure {
renderAvatar(user, props.avatarInnerClasses.orEmpty(), "/${FrontendRoutes.PROFILE}/${user.name}") {
renderAvatar(user, props.avatarInnerClasses.orEmpty(), "/${FrontendRoutes.VULN_PROFILE}/${user.name}") {
// just some default values in case you don't want to provide value
// in this case you will get small avatar
width = props.widthAndHeight ?: 4.rem
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ val topBarUserField: FC<TopBarUserFieldProps> = FC { props ->
props.userInfo?.name?.let { name ->
dropdownEntry(faUser, "Profile".t()) { attrs ->
attrs.onClick = {
navigate(to = "/${FrontendRoutes.PROFILE}/$name")
navigate(to = "/${FrontendRoutes.VULN_PROFILE}/$name")
}
}
dropdownEntry(faCog, "Settings".t()) { attrs ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ val cardUser: FC<IndexViewProps> = FC { props ->
}
+"${"Welcome".t()}${props.userInfo?.name?.let { ", " } ?: ""}"
Link {
to = "/${FrontendRoutes.PROFILE}/${props.userInfo?.name}"
to = "/${FrontendRoutes.VULN_PROFILE}/${props.userInfo?.name}"
b {
+(props.userInfo?.name?.let { " @$it " } ?: "")
}
Expand Down Expand Up @@ -242,7 +242,7 @@ val cardUser: FC<IndexViewProps> = FC { props ->
className = ClassName("col-3")
p {
Link {
to = "/${FrontendRoutes.PROFILE}/${props.userInfo?.name}"
to = "/${FrontendRoutes.VULN_PROFILE}/${props.userInfo?.name}"
+countVulnerability.toString()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,19 @@ import react.Props

import react.dom.html.ReactHTML.div
import react.dom.html.ReactHTML.main
import react.router.useNavigate
import react.useEffect
import web.cssom.*
import kotlinx.browser.window

@Suppress("EMPTY_BLOCK_STRUCTURE_ERROR")
val indexView: FC<IndexViewProps> = FC { props ->
val navigate = useNavigate()
useEffect {
if (window.location.run { hostname in setOf("cosv.dev", "cosv.gitlink.org.cn") && pathname == "/" }) {
navigate("/vuln")
}
}
useBackground(Style.INDEX)
particles()
main {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ enum class UserProfileTab {
companion object : TabMenuBar<UserProfileTab> {
override val nameOfTheHeadUrlSection = ""
override val defaultTab: UserProfileTab = VULNERABILITIES
override val regexForUrlClassification = "/${FrontendRoutes.PROFILE}"
override val regexForUrlClassification = "/${FrontendRoutes.VULN_PROFILE}"
override fun valueOf(elem: String): UserProfileTab = UserProfileTab.valueOf(elem)
override fun values(): Array<UserProfileTab> = UserProfileTab.values()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ val leftSettingsColumn: FC<SettingsProps> = FC { props ->
className = ClassName("row justify-content-center")
h6 {
Link {
to = "/${FrontendRoutes.PROFILE}/${props.userInfo?.name}"
to = "/${FrontendRoutes.VULN_PROFILE}/${props.userInfo?.name}"
style = jso {
textDecoration = TextDecoration.underline
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import kotlinx.serialization.json.Json

private val json = Json { prettyPrint = true }

val vulnerabilityChangesTab: FC<VulnerabilityChangesTabProps> = FC { props ->
val vulnerabilityChangesTab: FC<VulnerabilityChangesTab> = FC { props ->

val (cosvVersions, setCosvVersions) = useState(emptyList<CosvFileDto>())

Expand Down Expand Up @@ -126,7 +126,7 @@ val vulnerabilityChangesTab: FC<VulnerabilityChangesTabProps> = FC { props ->
/**
* [Props] of vulnerability changes tab component
*/
external interface VulnerabilityChangesTabProps : Props {
external interface VulnerabilityChangesTab : Props {
/**
* Vulnerability identifier
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,17 +244,16 @@ internal val headerMenu: FC<HeaderMenuProps> = FC { props ->
props.setIsTableView { !it }
}
}
if (props.selectedMenu == VulnerabilityTab.INFO) {
a {
buttonBuilder(
faDownload,
"secondary",
classes = "mr-2",
isOutline = true,
title = "Download vulnerability in COSV".t(),
) { }
href = "$apiUrl/vulnerabilities/download?identifier=${props.vulnerability.cosv.id}"
}

a {
buttonBuilder(
faDownload,
"secondary",
classes = "mr-2",
isOutline = true,
title = "Download vulnerability in COSV".t(),
) { }
href = "$apiUrl/vulnerabilities/download?identifier=${props.vulnerability.cosv.id}"
}

if (props.permissions.isSuperAdmin ||
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
@file:Suppress("FILE_NAME_MATCH_CLASS", "HEADER_MISSING_IN_NON_SINGLE_CLASS_FILE")

package com.saveourtool.save.frontend.components.views.vuln

import com.saveourtool.save.entities.cosv.VulnerabilityExt
import com.saveourtool.save.frontend.externals.jsonview.reactJson
import react.FC
import react.Props

import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json

val vulnerabilityRawDataTab: FC<VulnerabilityRawDataTabProps> = FC { props ->
reactJson {
src = JSON.parse(Json.encodeToString(props.vulnerability.cosv))
name = false
theme = "bright:inverted"
}
}

/**
* [Props] of vulnerability changes tab component
*/
external interface VulnerabilityRawDataTabProps : Props {
/**
* Vulnerability identifier
*/
var vulnerability: VulnerabilityExt
}
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ val vulnerabilityView: FC<VulnerabilitiesViewProps> = FC { props ->
VulnerabilityTab.CHANGES -> vulnerabilityChangesTab {
this.identifier = props.identifier
}

VulnerabilityTab.RAW -> vulnerabilityRawDataTab {
this.vulnerability = vulnerability
}
}
}
}
Expand All @@ -163,13 +167,14 @@ enum class VulnerabilityTab {
COMMENTS,
HISTORY,
CHANGES,
RAW,
// PROPOSED_CHANGES,
;

companion object : TabMenuBar<VulnerabilityTab> {
override val nameOfTheHeadUrlSection = ""
override val defaultTab: VulnerabilityTab = INFO
override val regexForUrlClassification = "/${FrontendRoutes.PROFILE}"
override val regexForUrlClassification = "/${FrontendRoutes.VULN_PROFILE}"
override fun valueOf(elem: String): VulnerabilityTab = VulnerabilityTab.valueOf(elem)
override fun values(): Array<VulnerabilityTab> = VulnerabilityTab.values()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
@file:Suppress("HEADER_MISSING_IN_NON_SINGLE_CLASS_FILE", "FILE_NAME_MATCH_CLASS")
@file:JsModule("react-json-view")
@file:JsNonModule

package com.saveourtool.save.frontend.externals.jsonview

import react.FC
import react.Props
import kotlin.js.Json

/**
* External declaration of [reactJson] react component
*/
@JsName("default")
external val reactJson: FC<ReactJsonViewProps>

/**
* Props of [ReactJsonViewProps]
*/
external interface ReactJsonViewProps : Props {
/**
* Input JSON
*/
var src: Json

/**
* name : {} or no name in case of false
*/
var name: Boolean

/**
* theme for the background
*/
var theme: String
// FixMe: onAdd?: ((add: InteractionProps) => false | any) | false;
// FixMe: onEdit?: ((edit: InteractionProps) => false | any) | false;
// FixMe: onDelete?: ((del: InteractionProps) => false | any) | false;
}
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ val basicRouting: FC<AppProps> = FC { props ->
uploadVulnerabilityView.create() to UPLOAD_VULNERABILITY,
vulnerabilityView.create() to "$VULNERABILITY_SINGLE/:identifier",
demoCollectionView.create() to DEMO,
userProfileView.create() to "$PROFILE/:name",
userProfileView.create() to "$VULN_PROFILE/:name",
topRatingView.create() to VULN_TOP_RATING,
termsOfUsageView.create() to TERMS_OF_USE,
cookieTermsOfUse.create() to COOKIE,
Expand Down
Loading

0 comments on commit ed8047d

Please sign in to comment.