Skip to content

Commit

Permalink
Feature implement profile page in web UI 3584 (#3812)
Browse files Browse the repository at this point in the history
* implement profile page in web ui #3584

* implement profile page in web ui #3584

* pr fixes
  • Loading branch information
hamidonos authored Jan 20, 2025
1 parent 5232f5a commit edd834d
Show file tree
Hide file tree
Showing 14 changed files with 251 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import com.mercedesbenz.sechub.sharedkernel.usecases.user.UseCaseUserRequestsNewApiToken;

/**
* Request new api token by a given onetimetoken. Can be done anonymous
* Request new api token by a given email address. Can be done anonymously
*
* @author Albert Tregnaghi
*
Expand Down
38 changes: 19 additions & 19 deletions sechub-openapi-java/src/main/resources/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2684,25 +2684,6 @@ paths:
## User Self Service ##
#######################

/api/anonymous/apitoken/{oneTimeToken}:
get:
summary: User clicks link to get new api token
description: User clicks link to get new api token
operationId: anonymousGetNewApiTokenByOneTimeToken
parameters:
- name: oneTimeToken
description: A one time token the user has got by a previous mail from SecHub server
in: path
required: true
schema:
type: string
responses:
"200":
description: "Answer containing the new api token or error message if request could not be fulfilled"
security: [ ]
tags:
- User Self Service

/api/management/user:
get:
summary: User fetches his user details
Expand Down Expand Up @@ -3230,6 +3211,25 @@ paths:
tags:
- Sign Up

/api/anonymous/apitoken/{oneTimeToken}:
get:
summary: User clicks link to get new api token
description: User clicks link to get new api token
operationId: anonymousGetNewApiTokenByOneTimeToken
parameters:
- name: oneTimeToken
description: A one time token the user has got by a previous mail from SecHub server
in: path
required: true
schema:
type: string
responses:
"200":
description: "Answer containing the new api token or error message if request could not be fulfilled"
security: [ ]
tags:
- Sign Up

/api/anonymous/refresh/apitoken/{emailAddress}:
post:
summary: User requests new API token
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
@Retention(RetentionPolicy.RUNTIME)
@UseCaseDefinition(
id=UC_USER_CLICKS_LINK_TO_GET_NEW_API_TOKEN,
group=UseCaseGroup.USER_SELF_SERVICE,
group=UseCaseGroup.SIGN_UP,
apiName="userClicksLinkToGetNewAPIToken",
title="User clicks link to get new api token",
description="user/clicks_link_to_get_new_api_token.adoc")
Expand Down
2 changes: 1 addition & 1 deletion sechub-web-ui/src/components.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// SPDX-License-Identifier: MIT
/* eslint-disable */
// @ts-nocheck
// Generated by unplugin-vue-components
Expand All @@ -19,5 +18,6 @@ declare module 'vue' {
ScanCreate: typeof import('./components/ScanCreate.vue')['default']
ScanFileUpload: typeof import('./components/ScanFileUpload.vue')['default']
ScanTypeSelect: typeof import('./components/ScanTypeSelect.vue')['default']
UserDetailInformation: typeof import('./components/UserDetailInformation.vue')['default']
}
}
9 changes: 8 additions & 1 deletion sechub-web-ui/src/components/AppHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
-->

<template #append>
<v-btn icon="mdi-account" />
<v-btn icon="mdi-account" @click="goToUserPage()" />

<v-btn icon="mdi-logout-variant" />

Expand All @@ -54,7 +54,14 @@
</template>

<script setup lang="ts">
import { useRouter } from 'vue-router'
const router = useRouter()
const username = 'SecHub User'

function goToUserPage () {
router.push('/user')
}

</script>

<style scoped>
Expand Down
8 changes: 4 additions & 4 deletions sechub-web-ui/src/components/ProjectJobList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@
import {
SecHubJobInfoForUser,
SecHubJobInfoForUserListPage,
UserListJobsForProjectRequest,
UserListsJobsForProjectRequest,
} from '@/generated-sources/openapi'

export default {
Expand All @@ -118,7 +118,7 @@
const baseDelay = 1000 // Initial delay in milliseconds
let timeOutId: number | undefined

const currentRequestParameters: UserListJobsForProjectRequest = {
const currentRequestParameters: UserListsJobsForProjectRequest = {
projectId: projectId.value,
size: '10',
page: '0',
Expand All @@ -130,9 +130,9 @@
const error = ref<string | undefined>(undefined)
const showProjectsDetails = ref(true)

async function fetchProjectJobs (requestParameters: UserListJobsForProjectRequest) {
async function fetchProjectJobs (requestParameters: UserListsJobsForProjectRequest) {
try {
jobsObject.value = await defaultClient.withOtherApi.userListJobsForProject(requestParameters)
jobsObject.value = await defaultClient.withOtherApi.userListsJobsForProject(requestParameters)
jobs.value = jobsObject.value.content
} catch (err) {
error.value = 'ProjectAPI error fetching jobs for project.'
Expand Down
163 changes: 163 additions & 0 deletions sechub-web-ui/src/components/UserDetailInformation.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
<!-- SPDX-License-Identifier: MIT -->
<template>
<v-card>
<v-card-item>
<v-card-title>{{ $t('USER_TITLE') }}</v-card-title>
</v-card-item>
<v-list lines="one">
<v-list-item>
<template #prepend>
<v-icon class="v-list-item-icon" size="40">mdi-account-circle</v-icon>
</template>
<v-container>
<v-list-item-title>{{ $t('USER_ID') }}</v-list-item-title>
<v-list-item-subtitle>{{ userId }}</v-list-item-subtitle>
</v-container>
</v-list-item>
<v-list-item>
<template #prepend>
<v-icon class="v-list-item-icon" size="40">mdi-email</v-icon>
</template>
<v-container>
<v-list-item-title>{{ $t('USER_EMAIL') }}</v-list-item-title>
<v-list-item-subtitle>{{ email }}</v-list-item-subtitle>
</v-container>
</v-list-item>
</v-list>
</v-card>

<v-card>
<v-card-item>
<v-card-title>{{ $t('USER_SETTINGS') }}</v-card-title>
</v-card-item>
<v-list lines="one">
<v-list-item v-if="false">
<v-container>
<v-btn variant="tonal">
{{ $t('USER_SETTINGS_CHANGE_PASSWORD') }}
</v-btn>
</v-container>
</v-list-item>
<v-list-item>
<v-container>
<v-btn :loading="isRefreshingApiToken" variant="tonal" @click="refreshApiToken()">
{{ $t('USER_SETTINGS_REQUEST_NEW_API_TOKEN') }}
</v-btn>

<v-dialog v-model="refreshApiTokenDialog" max-width="500">
<v-card>
<v-card-title>{{ $t('USER_SETTINGS_REQUEST_NEW_API_TOKEN_DIALOG_TITLE') }}</v-card-title>
<v-card-text>{{ $t('USER_SETTINGS_REQUEST_NEW_API_TOKEN_DIALOG_TEXT') }}</v-card-text>
<v-card-actions>
<v-btn color="primary" @click="refreshApiTokenDialog = false">{{ $t('USER_SETTINGS_REQUEST_NEW_API_TOKEN_DIALOG_CLOSE') }}</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-container>
</v-list-item>
</v-list>
</v-card>

<v-card>
<v-card-item>
<v-card-title>{{ $t('USER_SUPPORT_TITLE') }}</v-card-title>
</v-card-item>
<v-list lines="one">
<v-list-item>
<template #prepend>
<v-icon class="v-list-item-icon" size="40">mdi-web</v-icon>
</template>
<v-container>
<v-list-item-title>{{ $t('USER_SUPPORT_WEBSITE') }}</v-list-item-title>
<v-list-item-subtitle><a href="https://www.sechub.com" target="_blank">www.sechub.com</a></v-list-item-subtitle>
</v-container>
</v-list-item>
<v-list-item>
<template #prepend>
<v-icon class="v-list-item-icon" size="40">mdi-git</v-icon>
</template>
<v-container>
<v-list-item-title>{{ $t('USER_SUPPORT_GITHUB') }}</v-list-item-title>
<v-list-item-subtitle><a href="https://github.com/mercedes-benz/sechub" target="_blank">https://github.com/mercedes-benz/sechub</a></v-list-item-subtitle>
</v-container>
</v-list-item>
<v-list-item>
<template #prepend>
<v-icon class="v-list-item-icon" size="40">mdi-email</v-icon>
</template>
<v-container>
<v-list-item-title>{{ $t('USER_SUPPORT_EMAIL') }}</v-list-item-title>
<v-list-item-subtitle><a href="mailto:[email protected]">[email protected]</a></v-list-item-subtitle>
</v-container>
</v-list-item>
</v-list>
</v-card>
</template>

<script lang="ts">
import defaultClient from '@/services/defaultClient'
import { defineComponent } from 'vue'
import type { UserDetailInformation } from '@/generated-sources/openapi'

export default defineComponent({
name: 'UserDetailInformation',

setup () {
const userId = ref('')
const email = ref('')
const isRefreshingApiToken = ref(false)
const refreshApiTokenDialog = ref(false)

onMounted(async () => {
try {
const userDetailInformation: UserDetailInformation = await defaultClient.withUserSelfServiceApi.userFetchUserDetailInformation()
userId.value = userDetailInformation.userId!
email.value = userDetailInformation.email!
} catch (error) {
console.error(error)
}
})

async function refreshApiToken (): Promise<void> {
isRefreshingApiToken.value = true

try {
const emailValue = email.value
if (emailValue) {
await defaultClient.withSignUpApi.anonymousRefreshApiTokenByEmailAddress({
emailAddress: emailValue,
})
refreshApiTokenDialog.value = true
}
} catch (error) {
console.error('Failed to refresh API token:', error)
} finally {
isRefreshingApiToken.value = false
}
}

return {
userId,
email,
refreshApiToken,
isRefreshingApiToken,
refreshApiTokenDialog,
}
},
})
</script>

<style scoped>
.v-list-item__spacer {
display: none !important;
width: 0;
}

.v-card {
margin-top: 25px;

.v-btn {
width: 300px;
}
}
</style>
13 changes: 13 additions & 0 deletions sechub-web-ui/src/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,19 @@
"JOB_TABLE_DOWNLOAD_HTML_REPORT": "HTML Report",
"JOB_TABLE_DOWNLOAD_JSON_REPORT": "JSON Report",
"JOB_TABLE_DOWNLOAD_JOBUUID": "Job UUID",
"USER_TITLE": "User Profile",
"USER_ID": "User ID",
"USER_EMAIL": "Email",
"USER_SETTINGS": "Settings",
"USER_SETTINGS_CHANGE_PASSWORD": "Change Password (disabled)",
"USER_SETTINGS_REQUEST_NEW_API_TOKEN": "Request New API Token",
"USER_SETTINGS_REQUEST_NEW_API_TOKEN_DIALOG_TITLE": "Request Successful",
"USER_SETTINGS_REQUEST_NEW_API_TOKEN_DIALOG_TEXT": "Your new API token has been successfully created and sent to your configured email.",
"USER_SETTINGS_REQUEST_NEW_API_TOKEN_DIALOG_CLOSE": "Close",
"USER_SUPPORT_TITLE": "Support",
"USER_SUPPORT_WEBSITE": "SecHub Website",
"USER_SUPPORT_GITHUB": "SecHub GitHub Repository",
"USER_SUPPORT_EMAIL": "Support Email",
"PROJECT_DETAILS_TITLE": "Project",
"PROJECT_DETAILS_OWNER": "Owner",
"PROJECT_DETAILS_MEMBERS": "Members",
Expand Down
4 changes: 4 additions & 0 deletions sechub-web-ui/src/pages/user/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<!-- SPDX-License-Identifier: MIT -->
<template>
<UserDetailInformation />
</template>
4 changes: 4 additions & 0 deletions sechub-web-ui/src/services/defaultClient.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// SPDX-License-Identifier: MIT
import configurationApi from './configurationService'
import userSelfServiceApi from './userSelfServiceApi'
import signUpApi from './signUpApi'
import projectApi from './productAdministrationService'
import systemApi from './systemApiService'
import otherApi from './otherService'
Expand All @@ -8,6 +10,8 @@ import scanService from './executionService/ScanService'

const defaultClient = {
withProjectApi: projectApi,
withSignUpApi: signUpApi,
withUserSelfServiceApi: userSelfServiceApi,
withSystemApi: systemApi,
withConfigurationApi: configurationApi,
withOtherApi: otherApi,
Expand Down
7 changes: 7 additions & 0 deletions sechub-web-ui/src/services/signUpApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// SPDX-License-Identifier: MIT
import { SignUpApi } from '@/generated-sources/openapi'
import apiConfig from './configuration'

const signUpApi = new SignUpApi(apiConfig)

export default signUpApi
7 changes: 7 additions & 0 deletions sechub-web-ui/src/services/userSelfServiceApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// SPDX-License-Identifier: MIT
import { UserSelfServiceApi } from '@/generated-sources/openapi'
import apiConfig from './configuration'

const userSelfServiceApi = new UserSelfServiceApi(apiConfig)

export default userSelfServiceApi
18 changes: 18 additions & 0 deletions sechub-web-ui/src/styles/settings.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,21 @@
// @use 'vuetify/settings' with (
// $color-pack: false
// );

.v-list-item__spacer {
width: 0 !important;
}

.v-list-item .v-list-item__prepend {
padding-top: 0 !important;
}

.v-container v-locale--is-ltr {
padding-left: 0 !important;
}

.v-list-item__content {
.v-locale--is-ltr {
margin-left: 0 !important;
}
}
2 changes: 1 addition & 1 deletion sechub-web-ui/src/typed-router.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// SPDX-License-Identifier: MIT
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
Expand All @@ -22,5 +21,6 @@ declare module 'vue-router/auto-routes' {
'/': RouteRecordInfo<'/', '/', Record<never, never>, Record<never, never>>,
'/[id]/': RouteRecordInfo<'/[id]/', '/:id', { id: ParamValue<true> }, { id: ParamValue<false> }>,
'/[id]/scan': RouteRecordInfo<'/[id]/scan', '/:id/scan', { id: ParamValue<true> }, { id: ParamValue<false> }>,
'/user/': RouteRecordInfo<'/user/', '/user', Record<never, never>, Record<never, never>>,
}
}

0 comments on commit edd834d

Please sign in to comment.