Skip to content

Commit

Permalink
added all secret CLI commands
Browse files Browse the repository at this point in the history
  • Loading branch information
anudeeps352 authored and rajdip-b committed Oct 24, 2024
1 parent e26cf51 commit 1f17945
Show file tree
Hide file tree
Showing 9 changed files with 369 additions and 31 deletions.
24 changes: 15 additions & 9 deletions apps/cli/src/commands/secret.command.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import BaseCommand from '@/commands/base.command'
import CreateSecret from '@/commands/secret/create.secret'
import DeleteSecret from '@/commands/secret/delete.secret'
import ListSecret from '@/commands/secret/list.secret'
import FetchSecretRevisions from '@/commands/secret/revisions.secret'
import UpdateSecret from '@/commands/secret/update.secret'
import RollbackSecret from '@/commands/secret/rollback.secret'
import GetSecret from '@/commands/secret/get.secret'

export default class WorkspaceCommand extends BaseCommand {
export default class SecretCommand extends BaseCommand {
getName(): string {
return 'secret'
}
Expand All @@ -11,14 +18,13 @@ export default class WorkspaceCommand extends BaseCommand {

getSubCommands(): BaseCommand[] {
return [
new CreateWorkspace(), //change these
new DeleteWorkspace(),
new ExportWorkspace(),
new GetWorkspace(),
new ListWorkspace(),
new SearchWorkspace(),
new UpdateWorkspace(),
new WorkspaceRoleCommand()
new CreateSecret(),
new DeleteSecret(),
new GetSecret(),
new ListSecret(),
new FetchSecretRevisions(),
new UpdateSecret(),
new RollbackSecret()
]
}
}
56 changes: 35 additions & 21 deletions apps/cli/src/commands/secret/create.secret.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import BaseCommand from '../base.command'
import BaseCommand from '@/commands/base.command'
import { text } from '@clack/prompts'
import ControllerInstance from '@/util/controller-instance'
import { Logger } from '@/util/logger'
import {
CommandActionData,
CommandArgument,
CommandOption
type CommandActionData,
type CommandArgument,
type CommandOption
} from '@/types/command/command.types'

export default class CreateSecret extends BaseCommand {
Expand All @@ -25,28 +25,30 @@ export default class CreateSecret extends BaseCommand {
}
]
}

getOptions(): CommandOption[] {
return [
{
short: 'n',
short: '-n',
long: '--name <string>',
description: 'Name of the secret. Must be unique across the project'
},
{
short: 'd',
short: '-d',
long: '--note <string>',
description: 'A note describing the usage of the secret.'
},
{
short: 'r',
short: '-r',
long: '--rotate-after <string>',
description:
' The duration in days after which the value of the secret should be rotated. Accepted values are `24`, `168`, `720`, `8769` and `never`. Defaults to `never`.'
},
{
short: 'e',
short: '-e',
long: '--entries [entries...]',
description: 'An array of values for the secret.'
description:
'An array of key-value pair (value and environmentSlug) for the secret.'
}
]
}
Expand All @@ -63,10 +65,11 @@ export default class CreateSecret extends BaseCommand {
const { data, error, success } =
await ControllerInstance.getInstance().secretController.createSecret(
{
name, //doubtful as to whether to change it to since there
note, //are optional values present
name,
note,
rotateAfter,
entries
entries,
projectSlug
},
this.headers
)
Expand All @@ -84,15 +87,10 @@ export default class CreateSecret extends BaseCommand {
name: string
note?: string
rotateAfter?: '24' | '168' | '720' | '8760' | 'never'
entries: [
{
value: string
environmentSlug: string
}
]
entries: Array<{ value: string; environmentSlug: string }>
}> {
let { name, note } = options
const { rotateAfter, entries } = options // check what fields can be updated
let { name, note, rotateAfter } = options
const { entries } = options

if (!name) {
name = await text({
Expand All @@ -101,15 +99,31 @@ export default class CreateSecret extends BaseCommand {
})
}

if (!entries) {
throw new Error('Entries is required')
}

if (!note) {
note = name
}

const parsedEntries = entries.map((entry) => {
const entryObj: { value: string; environmentSlug: string } = {
value: '',
environmentSlug: ''
}
entry.split(' ').forEach((pair) => {
const [key, value] = pair.split('=')
entryObj[key] = value
})
return entryObj
})

return {
name,
note,
rotateAfter,
entries
entries: parsedEntries
}
}
}
44 changes: 44 additions & 0 deletions apps/cli/src/commands/secret/delete.secret.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import type {
CommandActionData,
CommandArgument
} from '@/types/command/command.types'
import BaseCommand from '@/commands/base.command'
import { Logger } from '@/util/logger'
import ControllerInstance from '@/util/controller-instance'

export default class DeleteSecret extends BaseCommand {
getName(): string {
return 'delete'
}

getDescription(): string {
return 'Deletes a secret'
}

getArguments(): CommandArgument[] {
return [
{
name: '<Secret Slug>',
description: 'Slug of the secret that you want to delete.'
}
]
}

async action({ args }: CommandActionData): Promise<void> {
const [secretSlug] = args

const { error, success } =
await ControllerInstance.getInstance().secretController.deleteSecret(
{
secretSlug
},
this.headers
)

if (success) {
Logger.info(`Secret ${secretSlug} deleted successfully!`)
} else {
Logger.error(`Failed to delete secret: ${error.message}`)
}
}
}
75 changes: 75 additions & 0 deletions apps/cli/src/commands/secret/get.secret.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import type {
CommandActionData,
CommandArgument,
CommandOption
} from '@/types/command/command.types'
import BaseCommand from '@/commands/base.command'
import ControllerInstance from '@/util/controller-instance'
import { Logger } from '@/util/logger'

export default class GetSecret extends BaseCommand {
getName(): string {
return 'get'
}

getDescription(): string {
return 'Get all secrets under a project'
}

getArguments(): CommandArgument[] {
return [
{
name: '<Project Slug>',
description: 'Slug of the project whose secrets you want.'
}
]
}

getOptions(): CommandOption[] {
return [
{
short: '-d',
long: '--decrypt-value',
description:
'Set this to true if the project contains the private key. If set to true, the values of the secret will be in plaintext format'
}
]
}

async action({ args, options }: CommandActionData): Promise<void> {
const [projectSlug] = args
const { decryptValue } = await this.parseInput(options)
const { data, error, success } =
await ControllerInstance.getInstance().secretController.getAllSecretsOfProject(
{
projectSlug,
decryptValue
},
this.headers
)

if (success) {
const secrets = data.items

if (secrets.length > 0) {
data.items.forEach((item: any) => {
const secret = item.secret
Logger.info(`- ${secret.name} (${secret.slug})`)
})
} else {
Logger.info('No secrets found')
}
} else {
Logger.error(`Failed fetching secrets: ${error.message}`)
}
}

private async parseInput(options: CommandActionData['options']): Promise<{
decryptValue: boolean
}> {
const { decryptValue = false } = options // defaults to false
return {
decryptValue
}
}
}
56 changes: 56 additions & 0 deletions apps/cli/src/commands/secret/list.secret.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import type {
CommandActionData,
CommandArgument
} from '@/types/command/command.types'
import BaseCommand from '@/commands/base.command'
import ControllerInstance from '@/util/controller-instance'
import { Logger } from '@/util/logger'

export default class ListSecret extends BaseCommand {
getName(): string {
return 'list'
}

getDescription(): string {
return 'List all secrets under a project and environment'
}

getArguments(): CommandArgument[] {
return [
{
name: '<Project Slug>',
description: 'Slug of the project whose secrets you want.'
},
{
name: '<Environment Slug>',
description: 'Slug of the environment whose secrets you want.'
}
]
}

async action({ args }: CommandActionData): Promise<void> {
const [projectSlug, environmentSlug] = args
const { data, error, success } =
await ControllerInstance.getInstance().secretController.getAllSecretsOfEnvironment(
{
projectSlug,
environmentSlug
},
this.headers
)

if (success) {
console.log(data)
const secrets = data
if (secrets.length > 0) {
data.forEach((secret: any) => {
Logger.info(`- ${secret.name} (${secret.value})`)
})
} else {
Logger.info('No secrets found')
}
} else {
Logger.error(`Failed fetching secrets: ${error.message}`)
}
}
}
62 changes: 62 additions & 0 deletions apps/cli/src/commands/secret/revisions.secret.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import type {
CommandActionData,
CommandArgument
} from '@/types/command/command.types'
import BaseCommand from '@/commands/base.command'
import ControllerInstance from '@/util/controller-instance'
import { Logger } from '@/util/logger'

export default class FetchSecretRevisions extends BaseCommand {
getName(): string {
return 'revisions'
}

getDescription(): string {
return 'Fetch all revisions of a secret'
}

getArguments(): CommandArgument[] {
return [
{
name: '<Secret Slug>',
description: 'Slug of the secret whose revisions you want.'
},
{
name: '<Environment Slug>',
description: 'Environment slug of the secret whose revisions you want.'
}
]
}

async action({ args }: CommandActionData): Promise<void> {
const [secretSlug, environmentSlug] = args

const { data, error, success } =
await ControllerInstance.getInstance().secretController.getRevisionsOfSecret(
{
secretSlug,
environmentSlug
},
this.headers
)

if (success) {
const revisions = data.items
if (revisions.length > 0) {
data.items.forEach((revision: any) => {
Logger.info(`Id ${revision.id}`)
Logger.info(`value ${revision.value}`)
Logger.info(`version ${revision.version}`)
Logger.info(`secretID ${revision.secretId}`)
Logger.info(`Created On ${revision.createdOn}`)
Logger.info(`Created By Id ${revision.createdById}`)
Logger.info(`environmentId ${revision.environmentId}`)
})
} else {
Logger.info('No revisions found')
}
} else {
Logger.error(`Failed fetching revisions: ${error.message}`)
}
}
}
Loading

0 comments on commit 1f17945

Please sign in to comment.