feat: add secret for function (#881)

This commit is contained in:
2022-11-25 21:36:55 +08:00
committed by GitHub
parent 3a62759e0e
commit 432e7471aa
3 changed files with 83 additions and 9 deletions

View File

@@ -1,10 +1,12 @@
import { isURL } from 'class-validator'
import fs, { mkdir, stat } from 'fs/promises'
import { isPlainObject } from 'lodash'
import LRUCache from 'lru-cache'
import { createRequire } from 'module'
import { mongo } from 'mongoose'
import path, { resolve } from 'path'
import { nextTick } from 'process'
import qs from 'qs'
import { TransformOptions, parseAsync, transformAsync } from '@babel/core'
import BabelPluginTransformCommonJS from '@babel/plugin-transform-modules-commonjs'
@@ -235,6 +237,14 @@ export class ServerlessService {
const { raw: functionString } = model
const logger = new Logger(`fx:${model.reference}/${model.name}`)
const document = await this.model.findById(model.id)
const secretObj = model.secret ? qs.parse(model.secret) : {}
if (!isPlainObject(secretObj)) {
throw new InternalServerErrorException(
`secret parsing error, must be object, got ${typeof secretObj}`,
)
}
// eslint-disable-next-line @typescript-eslint/no-this-alias
const self = this
const globalContext = {
@@ -257,6 +267,8 @@ export class ServerlessService {
},
},
secret: secretObj,
model,
document,
name: model.name,

View File

@@ -8,7 +8,9 @@ import {
Matches,
MaxLength,
} from 'class-validator'
import { isNil } from 'lodash'
import aggregatePaginate from 'mongoose-aggregate-paginate-v2'
import { stringify } from 'qs'
import { index, modelOptions, plugin, prop } from '@typegoose/typegoose'
@@ -84,12 +86,20 @@ export class SnippetModel extends BaseModel {
@IsOptional()
schema?: string
// for function
// for function start
@prop()
@IsEnum(['GET', 'POST', 'PUT', 'DELETE', 'PATCH'])
@IsOptional()
method?: string
@prop()
@IsString()
@IsOptional()
@Transform(({ value }) => (isNil(value) ? value : stringify(value)))
// username=123&password=123
secret?: string
// for function end
@prop()
@IsBoolean()
@IsOptional()

View File

@@ -1,6 +1,7 @@
import { load } from 'js-yaml'
import JSON5 from 'json5'
import { AggregatePaginateModel, Document } from 'mongoose'
import qs from 'qs'
import {
BadRequestException,
@@ -52,9 +53,9 @@ export class SnippetService {
return await this.model.create({ ...model, created: new Date() })
}
async update(id: string, model: SnippetModel) {
await this.validateTypeAndCleanup(model)
delete model.created
async update(id: string, newModel: SnippetModel) {
await this.validateTypeAndCleanup(newModel)
delete newModel.created
const old = await this.model.findById(id).lean()
if (!old) {
@@ -63,19 +64,48 @@ export class SnippetService {
if (
old.type === SnippetType.Function &&
model.type !== SnippetType.Function
newModel.type !== SnippetType.Function
) {
throw new BadRequestException(
'`type` is not allowed to change if this snippet set to Function type.',
)
}
// merge secret
if (old.secret && newModel.secret) {
const oldSecret = qs.parse(old.secret)
const newSecret = qs.parse(newModel.secret)
// first delete key if newer secret not provide
for (const key in oldSecret) {
if (!(key in newSecret)) {
delete oldSecret[key]
}
}
for (const key in newSecret) {
// if newSecret has same key, but value is empty, remove it
if (newSecret[key] === '' && oldSecret[key] !== '') {
delete newSecret[key]
}
}
newModel.secret = qs.stringify({ ...oldSecret, ...newSecret })
}
await this.deleteCachedSnippet(old.reference, old.name)
return await this.model.findByIdAndUpdate(
const newerDoc = await this.model.findByIdAndUpdate(
id,
{ ...model, modified: new Date() },
{ ...newModel, modified: new Date() },
{ new: true },
)
if (newerDoc) {
const nextSnippet = this.transformLeanSnippetModel(newerDoc.toObject())
return nextSnippet
}
return newerDoc
}
async delete(id: string) {
@@ -134,7 +164,7 @@ export class SnippetService {
// TODO refactor
// cleanup
if (model.type !== SnippetType.Function) {
const deleteKeys: (keyof SnippetModel)[] = ['enable', 'method']
const deleteKeys: (keyof SnippetModel)[] = ['enable', 'method', 'secret']
deleteKeys.forEach((key) => {
Reflect.deleteProperty(model, key)
})
@@ -146,7 +176,29 @@ export class SnippetService {
if (!doc) {
throw new NotFoundException()
}
return doc
// transform sth.
const nextSnippet = this.transformLeanSnippetModel(doc)
return nextSnippet
}
private transformLeanSnippetModel(snippet: SnippetModel) {
const nextSnippet = { ...snippet }
// transform sth.
if (snippet.type === SnippetType.Function) {
if (snippet.secret) {
const secretObj = qs.parse(snippet.secret)
for (const key in secretObj) {
// remove secret value, only keep key
secretObj[key] = ''
}
nextSnippet.secret = secretObj as any
}
}
return nextSnippet
}
/**