Skip to content

Commit

Permalink
Merge pull request #340 from sasjs/authenticate-target-command
Browse files Browse the repository at this point in the history
feat: add a command for authenticating target
  • Loading branch information
allanbowe authored Aug 31, 2022
2 parents 50fc1e1 + 74e5fa9 commit 512dd83
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 84 deletions.
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@
},
{
"command": "sasjs-for-vscode.createTarget",
"title": "SASjs: Create target"
"title": "SASjs: Create Target"
},
{
"command": "sasjs-for-vscode.authenticateTarget",
"title": "SASjs: Authenticate Target"
},
{
"command": "sasjs-for-vscode.selectTarget",
Expand Down
26 changes: 26 additions & 0 deletions src/commands/authenticating-target/authenticateTargetCommand.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { window, ExtensionContext, commands, OutputChannel } from 'vscode'
import { selectAndAuthenticateTarget } from '../../utils/auth'

export class AuthenticateTargetCommand {
private outputChannel: OutputChannel

constructor(private context: ExtensionContext) {
this.outputChannel = window.createOutputChannel('SASjs')
}

initialise = () => {
const authenticateTargetCommand = commands.registerCommand(
'sasjs-for-vscode.authenticateTarget',
() => this.authenticateTarget()
)
this.context.subscriptions.push(authenticateTargetCommand)
}

private authenticateTarget = async () => {
selectAndAuthenticateTarget(this.outputChannel).then((target) => {
if (target) {
window.showInformationMessage('Target authenticated!')
}
})
}
}
2 changes: 0 additions & 2 deletions src/commands/select-target/selectTargetCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ export class SelectTargetCommand {
.then((target) => {
if (target) {
window.showInformationMessage(`Selected Target: ${target.name}`)
} else {
window.showErrorMessage('No target selected!')
}
})
.catch((err) => {
Expand Down
4 changes: 4 additions & 0 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as vscode from 'vscode'
import { ExecuteCodeCommand } from './commands/execute-code/ExecuteCodeCommand'
import { ExecutingCodeCommand } from './commands/execute-code/ExecutingCodeCommand'
import { CreateTargetCommand } from './commands/creating-target/createTargetCommand'
import { AuthenticateTargetCommand } from './commands/authenticating-target/authenticateTargetCommand'
import { SelectTargetCommand } from './commands/select-target/selectTargetCommand'
import { FormatCommand } from './commands/format/FormatCommand'
import { lint, clearLintIssues } from './lint/lint'
Expand All @@ -21,6 +22,9 @@ export function activate(context: vscode.ExtensionContext) {
const createTargetCommand = new CreateTargetCommand(context)
createTargetCommand.initialise()

const authenticateTargetCommand = new AuthenticateTargetCommand(context)
authenticateTargetCommand.initialise()

const selectTargetCommand = new SelectTargetCommand(context)
selectTargetCommand.initialise()

Expand Down
95 changes: 92 additions & 3 deletions src/utils/auth.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,24 @@
import axios from 'axios'
import { OutputChannel, env, Uri, workspace } from 'vscode'
import SASjs from '@sasjs/adapter/node'
import { ServerType } from '@sasjs/utils'

import { OutputChannel } from 'vscode'
import {
Configuration,
encodeToBase64,
ServerType,
Target,
TargetJson
} from '@sasjs/utils'
import { getGlobalConfiguration, saveToGlobalConfig } from './config'
import {
getAuthCode,
getClientId,
getClientSecret,
getChoiceInput,
getCreateNewTarget,
getPassword,
getUserName
} from './input'
import { createTarget } from './createTarget'

export const getTokens = async (
sasjsInstance: SASjs,
Expand Down Expand Up @@ -34,3 +51,75 @@ export const getAuthUrl = (
serverType === ServerType.Sasjs
? `${serverUrl}/#/SASjsLogon?client_id=${clientId}&response_type=code`
: `${serverUrl}/SASLogon/oauth/authorize?client_id=${clientId}&response_type=code`

export const selectAndAuthenticateTarget = async (
outputChannel: OutputChannel
) => {
const config = (await getGlobalConfiguration(outputChannel)) as Configuration

if (config?.targets?.length) {
const targetNames = (config?.targets || []).map((t: any) => t.name)
const targetName = await getChoiceInput(
[...targetNames],
'Please select a target to authenticate'
)

if (!!targetName) {
const targetJson = config.targets.find((t: any) => t.name === targetName)
await authenticateTarget(targetJson!, outputChannel)
const target = new Target(targetJson)
await saveToGlobalConfig(target, outputChannel)
const extConfig = workspace.getConfiguration('sasjs-for-vscode')
await extConfig.update('target', target.name, true)
return target
}
} else if (await getCreateNewTarget()) {
return await createTarget(outputChannel)
}
}

export const authenticateTarget = async (
targetJson: TargetJson,
outputChannel: OutputChannel
) => {
if (targetJson.serverType === ServerType.Sasjs) {
const res = await axios.get(`${targetJson.serverUrl}/SASjsApi/info`)
// if sasjs server is not running in server mode then no need to authenticate
if (res.data?.mode !== 'server') {
return targetJson
}
}

if (targetJson.serverType === ServerType.Sas9) {
const userName = await getUserName()
const password = await getPassword()
targetJson.authConfigSas9 = { userName, password: encodeToBase64(password) }
return targetJson
}

const adapter = new SASjs({
serverUrl: targetJson.serverUrl,
serverType: targetJson.serverType
})

const clientId = await getClientId()
const clientSecret =
targetJson.serverType === ServerType.SasViya ? await getClientSecret() : ''

const authUrl = Uri.parse(
getAuthUrl(targetJson.serverType, targetJson.serverUrl, clientId)
)
env.openExternal(authUrl)

const authCode = await getAuthCode()

targetJson.authConfig = (await getTokens(
adapter,
clientId,
clientSecret,
authCode,
outputChannel
)) as any

return targetJson
}
83 changes: 5 additions & 78 deletions src/utils/createTarget.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,8 @@
import { OutputChannel, env, Uri } from 'vscode'
import axios from 'axios'
import { OutputChannel } from 'vscode'

import SASjs from '@sasjs/adapter/node'
import { encodeToBase64 } from '@sasjs/utils'
import { Target, ServerType } from '@sasjs/utils/types'
import {
getAuthCode,
getClientId,
getClientSecret,
getServerType,
getServerUrl,
getTargetName,
getUserName,
getPassword
} from './input'
import { getAuthUrl, getTokens } from './auth'
import { Target } from '@sasjs/utils/types'
import { getServerType, getServerUrl, getTargetName } from './input'
import { authenticateTarget } from './auth'
import { saveToGlobalConfig } from './config'

export const createTarget = async (outputChannel: OutputChannel) => {
Expand All @@ -27,69 +15,8 @@ export const createTarget = async (outputChannel: OutputChannel) => {
serverType,
appLoc: '/Public/app'
}
if (serverType === ServerType.SasViya) {
const clientId = await getClientId()
const clientSecret = await getClientSecret()

const authUrl = Uri.parse(getAuthUrl(serverType, serverUrl, clientId))
outputChannel.appendLine(authUrl.toString())
outputChannel.show()
env.openExternal(authUrl)

const authCode = await getAuthCode()

const adapter = new SASjs({
serverUrl: serverUrl,
serverType: serverType,
appLoc: '/Public/app',
useComputeApi: true,
debug: true
})

const authResponse = await getTokens(
adapter,
clientId,
clientSecret,
authCode,
outputChannel
)

targetJson.authConfig = authResponse
} else if (serverType === ServerType.Sas9) {
const userName = await getUserName()
const password = await getPassword()
targetJson.authConfigSas9 = { userName, password: encodeToBase64(password) }
} else if (serverType === ServerType.Sasjs) {
const res = await axios.get(`${serverUrl}/SASjsApi/info`)
if (res.data?.mode === 'server') {
const clientId = await getClientId()
const authUrl = Uri.parse(getAuthUrl(serverType, serverUrl, clientId))
outputChannel.appendLine(authUrl.toString())
outputChannel.show()
env.openExternal(authUrl)

const authCode = await getAuthCode()

const adapter = new SASjs({
serverUrl: serverUrl,
serverType: serverType,
appLoc: '/Public/app',
debug: true
})

const authResponse = await getTokens(
adapter,
clientId,
'',
authCode,
outputChannel
)

targetJson.authConfig = authResponse
} else if (res.data?.mode !== 'desktop') {
throw new Error('An unexpected error occurred while creating target.')
}
}
await authenticateTarget(targetJson, outputChannel)

const target = new Target(targetJson)

Expand Down

0 comments on commit 512dd83

Please sign in to comment.