mirror of
https://github.com/caprover/caprover
synced 2026-05-03 18:20:32 +00:00
Added project router
This commit is contained in:
@@ -3,6 +3,24 @@ import ApiStatusCodes from '../api/ApiStatusCodes'
|
||||
import AppsDataStore from './AppsDataStore'
|
||||
|
||||
const PROJECTS_DEFINITIONS = 'projectsDefinitions'
|
||||
|
||||
function isNameAllowed(name: string) {
|
||||
const isNameFormattingOk =
|
||||
!!name &&
|
||||
name.length < 50 &&
|
||||
/^[a-z]/.test(name) &&
|
||||
/[a-z0-9]$/.test(name) &&
|
||||
/^[a-z0-9\-]+$/.test(name) &&
|
||||
name.indexOf('--') < 0
|
||||
return isNameFormattingOk && ['captain', 'root'].indexOf(name) < 0
|
||||
}
|
||||
|
||||
function isValidUUID(uuid: string): boolean {
|
||||
const uuidRegex =
|
||||
/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
|
||||
return uuidRegex.test(uuid)
|
||||
}
|
||||
|
||||
class ProjectsDataStore {
|
||||
constructor(
|
||||
private data: configstore,
|
||||
@@ -11,26 +29,86 @@ class ProjectsDataStore {
|
||||
|
||||
saveProject(projectId: string, project: ProjectDefinition) {
|
||||
const self = this
|
||||
projectId = `${projectId || ''}`.trim()
|
||||
|
||||
return Promise.resolve().then(function () {
|
||||
project.name = `${project.name || ''}`.trim()
|
||||
project.id = `${project.id || ''}`.trim()
|
||||
project.description = `${project.description || ''}`.trim()
|
||||
|
||||
if (!isNameAllowed(project.name)) {
|
||||
throw ApiStatusCodes.createError(
|
||||
ApiStatusCodes.ILLEGAL_OPERATION,
|
||||
'Project name is not allowed'
|
||||
)
|
||||
}
|
||||
|
||||
if (project.id !== projectId) {
|
||||
throw ApiStatusCodes.createError(
|
||||
ApiStatusCodes.ILLEGAL_OPERATION,
|
||||
'Project ID does not match'
|
||||
)
|
||||
}
|
||||
|
||||
if (!isValidUUID(project.id)) {
|
||||
throw ApiStatusCodes.createError(
|
||||
ApiStatusCodes.ILLEGAL_OPERATION,
|
||||
'Project ID is not a valid UUID'
|
||||
)
|
||||
}
|
||||
|
||||
const projectToSave: ProjectDefinition = {
|
||||
id: project.id,
|
||||
name: project.name,
|
||||
description: project.description,
|
||||
}
|
||||
|
||||
return self.data.set(
|
||||
`${PROJECTS_DEFINITIONS}.${projectId}`,
|
||||
project
|
||||
projectToSave
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
getProject(projectName: string) {
|
||||
getAllProjects(): Promise<ProjectDefinition[]> {
|
||||
const self = this
|
||||
return Promise.resolve()
|
||||
.then(function () {
|
||||
return self.data.get(PROJECTS_DEFINITIONS)
|
||||
})
|
||||
.then(function (projects) {
|
||||
projects = projects || {}
|
||||
return Object.keys(projects).map((key) => projects[key]) || []
|
||||
})
|
||||
}
|
||||
|
||||
getProject(projectId: string) {
|
||||
const self = this
|
||||
projectId = `${projectId || ''}`.trim()
|
||||
return Promise.resolve().then(function () {
|
||||
return self.data.get(
|
||||
`${PROJECTS_DEFINITIONS}.${projectName}`
|
||||
`${PROJECTS_DEFINITIONS}.${projectId}`
|
||||
) as ProjectDefinition | undefined
|
||||
})
|
||||
}
|
||||
|
||||
deleteProject(projectId: string) {
|
||||
const self = this
|
||||
|
||||
projectId = `${projectId || ''}`.trim()
|
||||
|
||||
return Promise.resolve()
|
||||
.then(function () {
|
||||
return self.getProject(projectId)
|
||||
})
|
||||
.then(function (project) {
|
||||
if (!project) {
|
||||
throw ApiStatusCodes.createError(
|
||||
ApiStatusCodes.ILLEGAL_OPERATION,
|
||||
'Project not found'
|
||||
)
|
||||
}
|
||||
})
|
||||
.then(function () {
|
||||
return self.appsDataStore.getAppDefinitions()
|
||||
})
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
import express = require('express')
|
||||
import { v4 as uuid } from 'uuid'
|
||||
import ApiStatusCodes from '../../api/ApiStatusCodes'
|
||||
import BaseApi from '../../api/BaseApi'
|
||||
import InjectionExtractor from '../../injection/InjectionExtractor'
|
||||
import Logger from '../../utils/Logger'
|
||||
|
||||
const router = express.Router()
|
||||
|
||||
router.post('/register/', function (req, res, next) {
|
||||
const dataStore =
|
||||
InjectionExtractor.extractUserFromInjected(res).user.dataStore
|
||||
|
||||
const projectName = req.body.projectName as string
|
||||
|
||||
Promise.resolve()
|
||||
.then(function () {
|
||||
const projectId = uuid()
|
||||
return dataStore.getProjectsDataStore().saveProject(projectId, {
|
||||
id: projectId,
|
||||
name: projectName,
|
||||
description: '',
|
||||
})
|
||||
})
|
||||
.then(function () {
|
||||
Logger.d(`Project is saved: ${projectName}`)
|
||||
res.send(
|
||||
new BaseApi(ApiStatusCodes.STATUS_OK, 'App Definition Saved')
|
||||
)
|
||||
})
|
||||
.catch(ApiStatusCodes.createCatcher(res))
|
||||
})
|
||||
|
||||
router.post('/delete/', function (req, res, next) {
|
||||
const dataStore =
|
||||
InjectionExtractor.extractUserFromInjected(res).user.dataStore
|
||||
|
||||
const projectId = req.body.projectId
|
||||
|
||||
Promise.resolve()
|
||||
.then(function () {
|
||||
return dataStore //
|
||||
.getProjectsDataStore()
|
||||
.deleteProject(projectId)
|
||||
})
|
||||
.then(function () {
|
||||
Logger.d(`Project is deleted: ${projectId}`)
|
||||
res.send(new BaseApi(ApiStatusCodes.STATUS_OK, 'Project deleted'))
|
||||
})
|
||||
.catch(ApiStatusCodes.createCatcher(res))
|
||||
})
|
||||
|
||||
router.post('/update/', function (req, res, next) {
|
||||
const dataStore =
|
||||
InjectionExtractor.extractUserFromInjected(res).user.dataStore
|
||||
|
||||
const projectDefinition = req.body.projectDefinition as
|
||||
| ProjectDefinition
|
||||
| undefined
|
||||
|
||||
Promise.resolve()
|
||||
.then(function () {
|
||||
if (!projectDefinition) {
|
||||
throw ApiStatusCodes.createError(
|
||||
ApiStatusCodes.ILLEGAL_OPERATION,
|
||||
'Project Definition is not provided'
|
||||
)
|
||||
}
|
||||
|
||||
if (!projectDefinition.id) {
|
||||
throw ApiStatusCodes.createError(
|
||||
ApiStatusCodes.ILLEGAL_OPERATION,
|
||||
'Project ID is not provided'
|
||||
)
|
||||
}
|
||||
|
||||
return dataStore
|
||||
.getProjectsDataStore()
|
||||
.saveProject(projectDefinition.id, {
|
||||
id: projectDefinition.id,
|
||||
name: `${projectDefinition.name || ''}`,
|
||||
description: `${projectDefinition.description || ''}`,
|
||||
})
|
||||
})
|
||||
.then(function () {
|
||||
Logger.d(`Project is saved: ${projectDefinition?.name}`)
|
||||
res.send(new BaseApi(ApiStatusCodes.STATUS_OK, 'Project Saved'))
|
||||
})
|
||||
.catch(ApiStatusCodes.createCatcher(res))
|
||||
})
|
||||
|
||||
// Get All Projects
|
||||
router.get('/', function (req, res, next) {
|
||||
const dataStore =
|
||||
InjectionExtractor.extractUserFromInjected(res).user.dataStore
|
||||
|
||||
dataStore
|
||||
.getProjectsDataStore()
|
||||
.getAllProjects()
|
||||
.then(function (projects) {
|
||||
const baseApi = new BaseApi(
|
||||
ApiStatusCodes.STATUS_OK,
|
||||
'Projects are retrieved.'
|
||||
)
|
||||
baseApi.data = {
|
||||
projects: projects,
|
||||
}
|
||||
|
||||
res.send(baseApi)
|
||||
})
|
||||
.catch(ApiStatusCodes.createCatcher(res))
|
||||
})
|
||||
|
||||
export default router
|
||||
@@ -9,6 +9,7 @@ import Utils from '../../utils/Utils'
|
||||
import AppsRouter from './apps/AppsRouter'
|
||||
import OneClickAppRouter from './oneclick/OneClickAppRouter'
|
||||
import ProRouter from './pro/ProRouter'
|
||||
import ProjectsRouter from './ProjectsRouter'
|
||||
import RegistriesRouter from './registeries/RegistriesRouter'
|
||||
import SystemRouter from './system/SystemRouter'
|
||||
import onFinished = require('on-finished')
|
||||
@@ -124,6 +125,8 @@ router.post('/changepassword/', function (req, res, next) {
|
||||
|
||||
router.use('/apps/', AppsRouter)
|
||||
|
||||
router.use('/projects/', ProjectsRouter)
|
||||
|
||||
router.use('/oneclick/', OneClickAppRouter)
|
||||
|
||||
router.use('/registries/', RegistriesRouter)
|
||||
|
||||
Reference in New Issue
Block a user