This commit is contained in:
Kasra Bigdeli
2024-11-28 21:18:49 -08:00
parent d0bdd7ff14
commit e46687545f
6 changed files with 428 additions and 473 deletions
+367 -448
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -19,7 +19,7 @@
"body-parser": "^1.20.3",
"configstore": "^5.0.1",
"cookie-parser": "~1.4.7",
"cron": "^3.1.7",
"cron": "^3.2.1",
"debug": "~4.3.7",
"dockerode": "^4.0.2",
"ejs": "^3.1.10",
@@ -44,7 +44,7 @@
"ssh2": "^1.16.0",
"tar": "^7.4.3",
"typescript": "^5.6.3",
"uuid": "^10.0.0",
"uuid": "^11.0.3",
"validator": "^13.12.0",
"yaml": "^2.6.0"
},
+1 -1
View File
@@ -113,7 +113,7 @@ router.get('/', function (req, res, next) {
const dataStore =
InjectionExtractor.extractUserFromInjected(res).user.dataStore
dataStore
return dataStore
.getProjectsDataStore()
.getAllProjects()
.then(function (projects) {
@@ -60,7 +60,7 @@ router.post('/:appName/', function (req, res, next) {
InjectionExtractor.extractUserFromInjected(res).user.dataStore
const appName = req.params.appName
dataStore
return dataStore
.getAppsDataStore()
.getAppDefinition(appName)
.then(function (app) {
@@ -94,7 +94,7 @@ router.post(
return
}
Promise.resolve().then(function () {
return Promise.resolve().then(function () {
const promiseToDeployNewVer =
serviceManager.scheduleDeployNewVersion(appName, {
uploadedTarPathSource: tarballSourceFilePath
@@ -20,7 +20,7 @@ const DEFAULT_APP_CAPTAIN_DEFINITION = JSON.stringify({
// unused images
router.get('/unusedImages', function (req, res, next) {
Promise.resolve()
return Promise.resolve()
.then(function () {
const mostRecentLimit = Number(req.query.mostRecentLimit || '0')
return CaptainManager.get()
@@ -44,7 +44,7 @@ router.get('/unusedImages', function (req, res, next) {
router.post('/deleteImages', function (req, res, next) {
const imageIds = req.body.imageIds || []
Promise.resolve()
return Promise.resolve()
.then(function () {
return CaptainManager.get()
.getDiskCleanupManager()
@@ -68,7 +68,7 @@ router.get('/', function (req, res, next) {
InjectionExtractor.extractUserFromInjected(res).user.serviceManager
const appsArray: IAppDef[] = []
dataStore
return dataStore
.getAppsDataStore()
.getAppDefinitions()
.then(function (apps) {
@@ -268,7 +268,7 @@ router.post('/delete/', function (req, res, next) {
Logger.d(`Deleting app started: ${appName}`)
Promise.resolve()
return Promise.resolve()
.then(function () {
if (appNames.length > 0 && appName) {
throw ApiStatusCodes.createError(
@@ -316,7 +316,7 @@ router.post('/rename/', function (req, res, next) {
Logger.d(`Renaming app started: From ${oldAppName} To ${newAppName} `)
Promise.resolve()
return Promise.resolve()
.then(function () {
return serviceManager.renameApp(oldAppName, newAppName)
})
@@ -430,7 +430,7 @@ router.post('/update/', function (req, res, next) {
Logger.d(`Updating app started: ${appName}`)
serviceManager
return serviceManager
.updateAppDefinition(
appName,
projectId,
+50 -14
View File
@@ -1,19 +1,41 @@
import jwt = require('jsonwebtoken')
import { v4 as uuid } from 'uuid'
import { randomBytes } from 'crypto'
import ApiStatusCodes from '../api/ApiStatusCodes'
import { IHashMapGeneric } from '../models/ICacheGeneric'
import { UserJwt } from '../models/UserJwt'
import CaptainConstants from '../utils/CaptainConstants'
import EnvVar from '../utils/EnvVars'
import Logger from '../utils/Logger'
import bcrypt = require('bcryptjs')
import { IHashMapGeneric } from '../models/ICacheGeneric'
const captainDefaultPassword = EnvVar.DEFAULT_PASSWORD || 'captain42'
const captainDefaultPassword = EnvVar.DEFAULT_PASSWORD ?? 'captain42'
const COOKIE_AUTH_SUFFIX = 'cookie-'
const WEBHOOK_APP_PUSH_SUFFIX = '-webhook-app-push'
const DOWNLOAD_TOKEN = '-download-token'
function generateSecureRandomString(length: number): string {
if (length <= 0) {
throw new Error('Length must be a positive integer.')
}
const charset =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
const charsetLength = charset.length
// Generate random bytes
const randomValues = randomBytes(length)
// Map the random bytes to characters in the charset
let result = ''
for (let i = 0; i < length; i++) {
const randomIndex = randomValues[i] % charsetLength
result += charset[randomIndex]
}
return result
}
export interface OtpConfig {
otpToken: string
otpAuthenticator: {
@@ -30,14 +52,16 @@ class Authenticator {
constructor(secret: string, namespace: string) {
this.encryptionKey = secret + namespace // making encryption key unique per namespace!
this.namespace = namespace
this.tokenVersion = CaptainConstants.isDebug ? 'test' : uuid()
this.tokenVersion = CaptainConstants.isDebug
? 'test'
: generateSecureRandomString(64)
}
changepass(oldPass: string, newPass: string, savedHashedPassword: string) {
const self = this
oldPass = oldPass || ''
newPass = newPass || ''
oldPass = oldPass ?? ''
newPass = newPass ?? ''
return Promise.resolve()
.then(function () {
@@ -58,7 +82,7 @@ class Authenticator {
)
}
self.tokenVersion = uuid()
self.tokenVersion = generateSecureRandomString(64)
const hashed = bcrypt.hashSync(
self.encryptionKey + newPass,
@@ -73,12 +97,16 @@ class Authenticator {
const self = this
return Promise.resolve().then(function () {
password = password || ''
password = `${password ?? ''}`
if (!savedHashedPassword) {
return captainDefaultPassword === password
}
if (!self.encryptionKey) {
throw new Error('Encryption key is not set!')
}
return bcrypt.compareSync(
self.encryptionKey + password,
savedHashedPassword
@@ -157,7 +185,7 @@ class Authenticator {
return new Promise<UserJwt>(function (resolve, reject) {
jwt.verify(
token,
`${token}`,
self.encryptionKey + (keySuffix ? keySuffix : ''),
function (err, rawDecoded: { data: UserJwt }) {
if (err) {
@@ -258,10 +286,10 @@ class Authenticator {
{
data: obj,
},
self.encryptionKey + (keySuffix ? keySuffix : ''),
self.encryptionKey + (keySuffix ?? ''),
expiresIn
? {
expiresIn: expiresIn,
expiresIn: `${expiresIn || ''}`,
}
: undefined
)
@@ -273,8 +301,8 @@ class Authenticator {
return new Promise<any>(function (resolve, reject) {
jwt.verify(
token,
self.encryptionKey + (keySuffix ? keySuffix : ''),
`${token}`,
self.encryptionKey + (keySuffix ?? ''),
function (err, rawDecoded: { data: any }) {
if (err) {
Logger.e(err)
@@ -311,7 +339,8 @@ class Authenticator {
static setMainSalt(salt: string) {
if (Authenticator.mainSalt) throw new Error('Salt is already set!!')
Authenticator.mainSalt = salt
if (!salt) throw new Error('Empty salt!!')
Authenticator.mainSalt = `${salt}`
}
static getAuthenticator(namespace: string): Authenticator {
@@ -323,6 +352,13 @@ class Authenticator {
)
}
if (namespace !== CaptainConstants.rootNameSpace) {
throw ApiStatusCodes.createError(
ApiStatusCodes.STATUS_ERROR_NOT_AUTHORIZED,
'Invalid namespace'
)
}
if (!authenticatorCache[namespace]) {
const captainSalt = Authenticator.mainSalt
if (captainSalt) {