1
0
mirror of https://github.com/sasjs/server.git synced 2025-12-10 19:34:34 +00:00

chore: docs finalized for stp and others

This commit is contained in:
Saad Jutt
2021-11-11 03:20:19 +05:00
parent 45fbf2df46
commit 7a8123eb52
14 changed files with 319 additions and 920 deletions

View File

@@ -151,6 +151,28 @@ components:
- tree
type: object
additionalProperties: false
ExecuteReturnJsonResponse:
properties:
status:
type: string
log:
type: string
result:
type: string
message:
type: string
required:
- status
type: object
additionalProperties: false
ExecuteReturnJsonPayload:
properties:
_program:
type: string
description: 'Location of SAS program'
example: /Public/somefolder/some.file
type: object
additionalProperties: false
UserResponse:
properties:
id:
@@ -402,7 +424,7 @@ paths:
examples:
'Example 1':
value: {status: failure, message: 'Deployment failed!'}
description: 'Creates/updates files within SASjs Drive using provided payload.'
summary: 'Creates/updates files within SASjs Drive using provided payload.'
tags:
- Drive
security:
@@ -437,7 +459,7 @@ paths:
examples:
'Example 1':
value: {status: failure, message: 'File request failed.'}
description: 'Get file from SASjs Drive'
summary: 'Get file from SASjs Drive'
tags:
- Drive
security:
@@ -450,6 +472,7 @@ paths:
required: true
schema:
type: string
example: /Public/somefolder/some.file
patch:
operationId: UpdateFile
responses:
@@ -471,7 +494,7 @@ paths:
examples:
'Example 1':
value: {status: failure, message: 'File request failed.'}
description: 'Modify a file in SASjs Drive'
summary: 'Modify a file in SASjs Drive'
tags:
- Drive
security:
@@ -494,13 +517,68 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/GetFileTreeResponse'
description: 'Fetch file tree within SASjs Drive.'
summary: 'Fetch file tree within SASjs Drive.'
tags:
- Drive
security:
-
bearerAuth: []
parameters: []
/SASjsApi/client/execute:
get:
operationId: ExecuteReturnRaw
responses:
'200':
description: Ok
content:
application/json:
schema:
type: string
description: "Trigger a SAS program using it's location in the _program parameter.\nEnable debugging using the _debug parameter.\nAdditional URL parameters are turned into SAS macro variables.\nAny files provided are placed into the session and\ncorresponding _WEBIN_XXX variables are created."
summary: 'Execute Stored Program, return raw content'
tags:
- STP
security:
-
bearerAuth: []
parameters:
-
in: query
name: _program
required: true
schema:
type: string
example: /Public/somefolder/some.file
post:
operationId: ExecuteReturnJson
responses:
'200':
description: Ok
content:
application/json:
schema:
$ref: '#/components/schemas/ExecuteReturnJsonResponse'
description: "Trigger a SAS program using it's location in the _program parameter.\nEnable debugging using the _debug parameter.\nAdditional URL parameters are turned into SAS macro variables.\nAny files provided are placed into the session and\ncorresponding _WEBIN_XXX variables are created."
summary: 'Execute Stored Program, return JSON'
tags:
- STP
security:
-
bearerAuth: []
parameters:
-
in: query
name: _program
required: false
schema:
type: string
example: /Public/somefolder/some.file
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ExecuteReturnJsonPayload'
/SASjsApi/user:
get:
operationId: GetAllUsers
@@ -516,7 +594,7 @@ paths:
examples:
'Example 1':
value: [{id: 123, username: johnusername, displayName: John}, {id: 456, username: starkusername, displayName: Stark}]
description: 'Get list of all users (username, displayname). All users can request this.'
summary: 'Get list of all users (username, displayname). All users can request this.'
tags:
- User
security:
@@ -535,7 +613,7 @@ paths:
examples:
'Example 1':
value: {id: 1234, displayName: 'John Snow', username: johnSnow01, isAdmin: false, isActive: true}
description: 'Create user with the following attributes: UserId, UserName, Password, isAdmin, isActive. Admin only task.'
summary: 'Create user with the following attributes: UserId, UserName, Password, isAdmin, isActive. Admin only task.'
tags:
- User
security:
@@ -558,7 +636,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UserDetailsResponse'
description: 'Get user properties - such as group memberships, userName, displayName.'
summary: 'Get user properties - such as group memberships, userName, displayName.'
tags:
- User
security:
@@ -586,7 +664,7 @@ paths:
examples:
'Example 1':
value: {id: 1234, displayName: 'John Snow', username: johnSnow01, isAdmin: false, isActive: true}
description: 'Update user properties - such as displayName. Can be performed either by admins, or the user in question.'
summary: 'Update user properties - such as displayName. Can be performed either by admins, or the user in question.'
tags:
- User
security:
@@ -613,7 +691,7 @@ paths:
responses:
'204':
description: 'No content'
description: 'Delete a user. Can be performed either by admins, or the user in question.'
summary: 'Delete a user. Can be performed either by admins, or the user in question.'
tags:
- User
security:
@@ -653,7 +731,7 @@ paths:
examples:
'Example 1':
value: [{groupId: 123, name: DCGroup, description: 'This group represents Data Controller Users'}]
description: 'Get list of all groups (groupName and groupDescription). All users can request this.'
summary: 'Get list of all groups (groupName and groupDescription). All users can request this.'
tags:
- Group
security:
@@ -672,7 +750,7 @@ paths:
examples:
'Example 1':
value: {groupId: 123, name: DCGroup, description: 'This group represents Data Controller Users', isActive: true, users: []}
description: 'Create a new group. Admin only.'
summary: 'Create a new group. Admin only.'
tags:
- Group
security:
@@ -695,7 +773,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/GroupDetailsResponse'
description: 'Get list of members of a group (userName). All users can request this.'
summary: 'Get list of members of a group (userName). All users can request this.'
tags:
- Group
security:
@@ -716,7 +794,7 @@ paths:
responses:
'204':
description: 'No content'
description: 'Delete a group. Admin task only.'
summary: 'Delete a group. Admin task only.'
tags:
- Group
security:
@@ -745,7 +823,7 @@ paths:
examples:
'Example 1':
value: {groupId: 123, name: DCGroup, description: 'This group represents Data Controller Users', isActive: true, users: []}
description: 'Add a user to a group. Admin task only.'
summary: 'Add a user to a group. Admin task only.'
tags:
- Group
security:
@@ -782,7 +860,7 @@ paths:
examples:
'Example 1':
value: {groupId: 123, name: DCGroup, description: 'This group represents Data Controller Users', isActive: true, users: []}
description: 'Remove a user to a group. Admin task only.'
summary: 'Remove a user to a group. Admin task only.'
tags:
- Group
security:
@@ -820,7 +898,7 @@ paths:
examples:
'Example 1':
value: {clientId: someFormattedClientID1234, clientSecret: someRandomCryptoString}
description: 'Create client with the following attributes: ClientId, ClientSecret. Admin only task.'
summary: 'Create client with the following attributes: ClientId, ClientSecret. Admin only task.'
tags:
- Client
security:
@@ -846,7 +924,7 @@ paths:
examples:
'Example 1':
value: {code: someRandomCryptoString}
description: 'Accept a valid username/password, plus a CLIENT_ID, and return an AUTH_CODE'
summary: 'Accept a valid username/password, plus a CLIENT_ID, and return an AUTH_CODE'
tags:
- Auth
security: []
@@ -870,7 +948,7 @@ paths:
examples:
'Example 1':
value: {accessToken: someRandomCryptoString, refreshToken: someRandomCryptoString}
description: 'Accepts client/auth code and returns access/refresh tokens'
summary: 'Accepts client/auth code and returns access/refresh tokens'
tags:
- Auth
security: []
@@ -894,7 +972,7 @@ paths:
examples:
'Example 1':
value: {accessToken: someRandomCryptoString, refreshToken: someRandomCryptoString}
description: 'Returns new access/refresh tokens'
summary: 'Returns new access/refresh tokens'
tags:
- Auth
security:
@@ -907,7 +985,7 @@ paths:
responses:
'204':
description: 'No content'
description: 'Logout terminate access/refresh tokens and returns nothing'
summary: 'Logout terminate access/refresh tokens and returns nothing'
tags:
- Auth
security:
@@ -933,3 +1011,6 @@ tags:
-
name: Group
description: 'Operations about group'
-
name: STP
description: 'Operations about STP'

View File

@@ -19,7 +19,7 @@ export default class AuthController {
delete AuthController.authCodes[userId][clientId]
/**
* Accept a valid username/password, plus a CLIENT_ID, and return an AUTH_CODE
* @summary Accept a valid username/password, plus a CLIENT_ID, and return an AUTH_CODE
*
*/
@Example<AuthorizeResponse>({
@@ -33,7 +33,7 @@ export default class AuthController {
}
/**
* Accepts client/auth code and returns access/refresh tokens
* @summary Accepts client/auth code and returns access/refresh tokens
*
*/
@Example<TokenResponse>({
@@ -46,7 +46,7 @@ export default class AuthController {
}
/**
* Returns new access/refresh tokens
* @summary Returns new access/refresh tokens
*
*/
@Example<TokenResponse>({
@@ -62,7 +62,7 @@ export default class AuthController {
}
/**
* Logout terminate access/refresh tokens and returns nothing
* @summary Logout terminate access/refresh tokens and returns nothing
*
*/
@Security('bearerAuth')

View File

@@ -7,7 +7,7 @@ import Client, { ClientPayload } from '../model/Client'
@Tags('Client')
export default class ClientController {
/**
* Create client with the following attributes: ClientId, ClientSecret. Admin only task.
* @summary Create client with the following attributes: ClientId, ClientSecret. Admin only task.
*
*/
@Example<ClientPayload>({

View File

@@ -13,7 +13,7 @@ import {
import { fileExists, readFile, createFile } from '@sasjs/utils'
import { createFileTree, ExecutionController, getTreeExample } from '.'
import { FileTree, isFileQuery, isFileTree, TreeNode } from '../types'
import { FileTree, isFileTree, TreeNode } from '../types'
import path from 'path'
import { getTmpFilesFolderPath } from '../utils'
@@ -77,7 +77,7 @@ const execDeployErrorResponse: DeployResponse = {
@Tags('Drive')
export class DriveController {
/**
* Creates/updates files within SASjs Drive using provided payload.
* @summary Creates/updates files within SASjs Drive using provided payload.
*
*/
@Example<DeployResponse>(successDeployResponse)
@@ -89,8 +89,9 @@ export class DriveController {
}
/**
* Get file from SASjs Drive
*
* @summary Get file from SASjs Drive
* @query filePath Location of SAS program
* @example filePath "/Public/somefolder/some.file"
*/
@Example<GetFileResponse>({
status: 'success',
@@ -106,7 +107,7 @@ export class DriveController {
}
/**
* Modify a file in SASjs Drive
* @summary Modify a file in SASjs Drive
*
*/
@Example<UpdateFileResponse>({
@@ -124,7 +125,7 @@ export class DriveController {
}
/**
* Fetch file tree within SASjs Drive.
* @summary Fetch file tree within SASjs Drive.
*
*/
@Get('/filetree')

View File

@@ -33,7 +33,7 @@ interface GroupDetailsResponse {
@Tags('Group')
export default class GroupController {
/**
* Get list of all groups (groupName and groupDescription). All users can request this.
* @summary Get list of all groups (groupName and groupDescription). All users can request this.
*
*/
@Example<GroupResponse[]>([
@@ -49,7 +49,7 @@ export default class GroupController {
}
/**
* Create a new group. Admin only.
* @summary Create a new group. Admin only.
*
*/
@Example<GroupDetailsResponse>({
@@ -67,7 +67,7 @@ export default class GroupController {
}
/**
* Get list of members of a group (userName). All users can request this.
* @summary Get list of members of a group (userName). All users can request this.
* @param groupId The group's identifier
* @example groupId 1234
*/
@@ -79,7 +79,7 @@ export default class GroupController {
}
/**
* Add a user to a group. Admin task only.
* @summary Add a user to a group. Admin task only.
* @param groupId The group's identifier
* @example groupId "1234"
* @param userId The user's identifier
@@ -101,7 +101,7 @@ export default class GroupController {
}
/**
* Remove a user to a group. Admin task only.
* @summary Remove a user to a group. Admin task only.
* @param groupId The group's identifier
* @example groupId "1234"
* @param userId The user's identifier
@@ -123,7 +123,7 @@ export default class GroupController {
}
/**
* Delete a group. Admin task only.
* @summary Delete a group. Admin task only.
* @param groupId The group's identifier
* @example groupId 1234
*/

151
api/src/controllers/stp.ts Normal file
View File

@@ -0,0 +1,151 @@
import express from 'express'
import path from 'path'
import {
Request,
Security,
Route,
Tags,
Example,
Post,
Body,
Get,
Query
} from 'tsoa'
import { ExecutionController } from '.'
import { PreProgramVars } from '../types'
import { getTmpFilesFolderPath, makeFilesNamesMap } from '../utils'
interface ExecuteReturnJsonPayload {
/**
* Location of SAS program
* @example "/Public/somefolder/some.file"
*/
_program?: string
}
interface ExecuteReturnJsonResponse {
status: string
log?: string
result?: string
message?: string
}
@Security('bearerAuth')
@Route('SASjsApi/client')
@Tags('STP')
export default class STPController {
/**
* Trigger a SAS program using it's location in the _program parameter.
* Enable debugging using the _debug parameter.
* Additional URL parameters are turned into SAS macro variables.
* Any files provided are placed into the session and
* corresponding _WEBIN_XXX variables are created.
* @summary Execute Stored Program, return raw content
* @query _program Location of SAS program
* @example _program "/Public/somefolder/some.file"
*/
@Get('/execute')
public async executeReturnRaw(
@Request() request: express.Request,
@Query() _program: string
): Promise<string> {
return executeReturnRaw(request, _program)
}
/**
* Trigger a SAS program using it's location in the _program parameter.
* Enable debugging using the _debug parameter.
* Additional URL parameters are turned into SAS macro variables.
* Any files provided are placed into the session and
* corresponding _WEBIN_XXX variables are created.
* @summary Execute Stored Program, return JSON
* @query _program Location of SAS program
* @example _program "/Public/somefolder/some.file"
*/
@Post('/execute')
public async executeReturnJson(
@Request() request: express.Request,
@Body() body: ExecuteReturnJsonPayload,
@Query() _program?: string
): Promise<ExecuteReturnJsonResponse> {
const program = _program ?? body._program
return executeReturnJson(request, program!)
}
}
const executeReturnRaw = async (
req: express.Request,
_program: string
): Promise<string> => {
const sasCodePath =
path
.join(getTmpFilesFolderPath(), _program)
.replace(new RegExp('/', 'g'), path.sep) + '.sas'
try {
const result = await new ExecutionController().execute(
sasCodePath,
getPreProgramVariables(req),
undefined,
undefined,
{
...req.query
}
)
return result as string
} catch (err) {
throw {
code: 400,
status: 'failure',
message: 'Job execution failed.',
...(typeof err === 'object' ? err : { details: err })
}
}
}
const executeReturnJson = async (
req: any,
_program: string
): Promise<ExecuteReturnJsonResponse> => {
const sasCodePath =
path
.join(getTmpFilesFolderPath(), _program)
.replace(new RegExp('/', 'g'), path.sep) + '.sas'
const filesNamesMap = req.files?.length ? makeFilesNamesMap(req.files) : null
try {
const jsonResult: any = await new ExecutionController().execute(
sasCodePath,
getPreProgramVariables(req),
undefined,
req.sasSession,
{ ...req.query, ...req.body },
{ filesNamesMap: filesNamesMap },
true
)
return {
status: 'success',
result: jsonResult.result,
log: jsonResult.log
}
} catch (err) {
throw {
status: 'failure',
message: 'Job execution failed.',
...(typeof err === 'object' ? err : { details: err })
}
}
}
const getPreProgramVariables = (req: any): PreProgramVars => {
const host = req.get('host')
const protocol = req.protocol + '://'
const { user, accessToken } = req
return {
username: user.username,
userId: user.userId,
displayName: user.displayName,
serverUrl: protocol + host,
accessToken
}
}

View File

@@ -34,7 +34,7 @@ interface UserDetailsResponse {
@Tags('User')
export default class UserController {
/**
* Get list of all users (username, displayname). All users can request this.
* @summary Get list of all users (username, displayname). All users can request this.
*
*/
@Example<UserResponse[]>([
@@ -55,7 +55,7 @@ export default class UserController {
}
/**
* Create user with the following attributes: UserId, UserName, Password, isAdmin, isActive. Admin only task.
* @summary Create user with the following attributes: UserId, UserName, Password, isAdmin, isActive. Admin only task.
*
*/
@Example<UserDetailsResponse>({
@@ -73,7 +73,7 @@ export default class UserController {
}
/**
* Get user properties - such as group memberships, userName, displayName.
* @summary Get user properties - such as group memberships, userName, displayName.
* @param userId The user's identifier
* @example userId 1234
*/
@@ -83,7 +83,7 @@ export default class UserController {
}
/**
* Update user properties - such as displayName. Can be performed either by admins, or the user in question.
* @summary Update user properties - such as displayName. Can be performed either by admins, or the user in question.
* @param userId The user's identifier
* @example userId "1234"
*/
@@ -103,7 +103,7 @@ export default class UserController {
}
/**
* Delete a user. Can be performed either by admins, or the user in question.
* @summary Delete a user. Can be performed either by admins, or the user in question.
* @param userId The user's identifier
* @example userId 1234
*/

View File

@@ -1,13 +1,6 @@
import express from 'express'
import path from 'path'
import { ExecutionController } from '../../controllers'
import { DriveController } from '../../controllers/drive'
import { isFileQuery } from '../../types'
import {
getFileDriveValidation,
getTmpFilesFolderPath,
updateFileDriveValidation
} from '../../utils'
import { getFileDriveValidation, updateFileDriveValidation } from '../../utils'
const driveRouter = express.Router()

View File

@@ -1,39 +1,26 @@
import express from 'express'
import { isExecutionQuery, PreProgramVars } from '../../types'
import path from 'path'
import { getTmpFilesFolderPath, makeFilesNamesMap } from '../../utils'
import { ExecutionController, FileUploadController } from '../../controllers'
import { executeProgramRawValidation } from '../../utils'
import STPController from '../../controllers/stp'
import { FileUploadController } from '../../controllers'
const stpRouter = express.Router()
const fileUploadController = new FileUploadController()
const controller = new STPController()
stpRouter.get('/execute', async (req, res) => {
if (isExecutionQuery(req.query)) {
let sasCodePath =
path
.join(getTmpFilesFolderPath(), req.query._program)
.replace(new RegExp('/', 'g'), path.sep) + '.sas'
const { error, value: query } = executeProgramRawValidation(req.query)
if (error) return res.status(400).send(error.details[0].message)
await new ExecutionController()
.execute(sasCodePath, getPreProgramVariables(req), undefined, undefined, {
...req.query
})
.then((result: {}) => {
res.status(200).send(result)
})
.catch((err: {} | string) => {
res.status(400).send({
status: 'failure',
message: 'Job execution failed.',
...(typeof err === 'object' ? err : { details: err })
})
})
} else {
res.status(400).send({
status: 'failure',
message: `Please provide the location of SAS code`
})
try {
const response = await controller.executeReturnRaw(req, query._program)
res.send(response)
} catch (err: any) {
const statusCode = err.code
delete err.code
res.status(statusCode).send(err)
}
})
@@ -42,68 +29,27 @@ stpRouter.post(
fileUploadController.preuploadMiddleware,
fileUploadController.getMulterUploadObject().any(),
async (req: any, res: any) => {
let _program
if (isExecutionQuery(req.query)) {
_program = req.query._program
} else if (isExecutionQuery(req.body)) {
_program = req.body._program
}
const { error: errQ, value: query } = executeProgramRawValidation(req.query)
if (errQ) return res.status(400).send(errQ.details[0].message)
if (_program) {
let sasCodePath =
path
.join(getTmpFilesFolderPath(), _program)
.replace(new RegExp('/', 'g'), path.sep) + '.sas'
const { error: errB, value: body } = executeProgramRawValidation(req.body)
if (errB) return res.status(400).send(errB.details[0].message)
let filesNamesMap = null
try {
const response = await controller.executeReturnJson(
req,
query,
body?._program
)
res.send(response)
} catch (err: any) {
const statusCode = err.code
if (req.files && req.files.length > 0) {
filesNamesMap = makeFilesNamesMap(req.files)
}
delete err.code
await new ExecutionController()
.execute(
sasCodePath,
getPreProgramVariables(req),
undefined,
req.sasSession,
{ ...req.query, ...req.body },
{ filesNamesMap: filesNamesMap },
true
)
.then((result: {}) => {
res.status(200).send({
status: 'success',
...result
})
})
.catch((err: {} | string) => {
res.status(400).send({
status: 'failure',
message: 'Job execution failed.',
...(typeof err === 'object' ? err : { details: err })
})
})
} else {
res.status(400).send({
status: 'failure',
message: `Please provide the location of SAS code`
})
res.status(statusCode).send(err)
}
}
)
const getPreProgramVariables = (req: any): PreProgramVars => {
const host = req.get('host')
const protocol = req.protocol + '://'
const { user, accessToken } = req
return {
username: user.username,
userId: user.userId,
displayName: user.displayName,
serverUrl: protocol + host,
accessToken
}
}
export default stpRouter

View File

@@ -1,8 +1,6 @@
import express from 'express'
import { isExecutionQuery } from '../../types'
import path from 'path'
import { getTmpFilesFolderPath, getWebBuildFolderPath } from '../../utils'
import { ExecutionController } from '../../controllers'
import { getWebBuildFolderPath } from '../../utils'
const webRouter = express.Router()

View File

@@ -76,3 +76,10 @@ export const updateFileDriveValidation = (data: any): Joi.ValidationResult =>
filePath: Joi.string().required(),
fileContent: Joi.string().required()
}).validate(data)
export const executeProgramRawValidation = (data: any): Joi.ValidationResult =>
Joi.object({
_program: Joi.string().required
})
.pattern(/\w\d/, Joi.string())
.validate(data)

View File

@@ -30,6 +30,10 @@
{
"name": "Group",
"description": "Operations about group"
},
{
"name": "STP",
"description": "Operations about STP"
}
],
"yaml": true,

View File

@@ -1,782 +0,0 @@
components:
examples: {}
headers: {}
parameters: {}
requestBodies: {}
responses: {}
schemas:
MemberType.folder:
enum:
- folder
type: string
FolderMember:
properties:
name:
type: string
type:
$ref: '#/components/schemas/MemberType.folder'
members:
items:
anyOf:
-
$ref: '#/components/schemas/FolderMember'
-
$ref: '#/components/schemas/ServiceMember'
type: array
required:
- name
- type
- members
type: object
additionalProperties: false
MemberType.service:
enum:
- service
type: string
ServiceMember:
properties:
name:
type: string
type:
$ref: '#/components/schemas/MemberType.service'
code:
type: string
required:
- name
- type
- code
type: object
additionalProperties: false
FileTree:
properties:
members:
items:
anyOf:
-
$ref: '#/components/schemas/FolderMember'
-
$ref: '#/components/schemas/ServiceMember'
type: array
required:
- members
type: object
additionalProperties: false
DeployResponse:
properties:
status:
type: string
message:
type: string
example:
$ref: '#/components/schemas/FileTree'
required:
- status
- message
type: object
additionalProperties: false
DeployPayload:
properties:
appLoc:
type: string
fileTree:
$ref: '#/components/schemas/FileTree'
required:
- fileTree
type: object
additionalProperties: false
UserResponse:
properties:
id:
type: number
format: double
username:
type: string
displayName:
type: string
required:
- id
- username
- displayName
type: object
additionalProperties: false
UserDetailsResponse:
properties:
id:
type: number
format: double
displayName:
type: string
username:
type: string
isActive:
type: boolean
isAdmin:
type: boolean
required:
- id
- displayName
- username
- isActive
- isAdmin
type: object
additionalProperties: false
UserPayload:
properties:
displayName:
type: string
description: 'Display name for user'
example: 'John Snow'
username:
type: string
description: 'Username for user'
example: johnSnow01
password:
type: string
description: 'Password for user'
isAdmin:
type: boolean
description: 'Account should be admin or not, defaults to false'
example: 'false'
isActive:
type: boolean
description: 'Account should be active or not, defaults to true'
example: 'true'
required:
- displayName
- username
- password
type: object
additionalProperties: false
GroupResponse:
properties:
groupId:
type: number
format: double
name:
type: string
description:
type: string
required:
- groupId
- name
- description
type: object
additionalProperties: false
GroupDetailsResponse:
properties:
groupId:
type: number
format: double
name:
type: string
description:
type: string
isActive:
type: boolean
users:
items:
$ref: '#/components/schemas/UserResponse'
type: array
required:
- groupId
- name
- description
- isActive
- users
type: object
additionalProperties: false
GroupPayload:
properties:
name:
type: string
description: 'Name of the group'
example: DCGroup
description:
type: string
description: 'Description of the group'
example: 'This group represents Data Controller Users'
isActive:
type: boolean
description: 'Group should be active or not, defaults to true'
example: 'true'
required:
- name
- description
type: object
additionalProperties: false
ClientPayload:
properties:
clientId:
type: string
description: 'Client ID'
example: someFormattedClientID1234
clientSecret:
type: string
description: 'Client Secret'
example: someRandomCryptoString
required:
- clientId
- clientSecret
type: object
additionalProperties: false
AuthorizeResponse:
properties:
code:
type: string
description: 'Authorization code'
example: someRandomCryptoString
required:
- code
type: object
additionalProperties: false
AuthorizePayload:
properties:
username:
type: string
description: 'Username for user'
example: secretuser
password:
type: string
description: 'Password for user'
example: secretpassword
clientId:
type: string
description: 'Client ID'
example: clientID1
required:
- username
- password
- clientId
type: object
additionalProperties: false
TokenResponse:
properties:
accessToken:
type: string
description: 'Access Token'
example: someRandomCryptoString
refreshToken:
type: string
description: 'Refresh Token'
example: someRandomCryptoString
required:
- accessToken
- refreshToken
type: object
additionalProperties: false
TokenPayload:
properties:
clientId:
type: string
description: 'Client ID'
example: clientID1
code:
type: string
description: 'Authorization code'
example: someRandomCryptoString
required:
- clientId
- code
type: object
additionalProperties: false
InfoJWT:
properties:
clientId:
type: string
userId:
type: number
format: double
required:
- clientId
- userId
type: object
additionalProperties: false
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
info:
title: server
version: 0.0.1
description: 'SASjs server'
contact:
name: 'Analytium Ltd'
openapi: 3.0.0
paths:
/SASjsApi/drive/deploy:
post:
operationId: Deploy
responses:
'200':
description: Ok
content:
application/json:
schema:
$ref: '#/components/schemas/DeployResponse'
examples:
'Example 1':
value: {status: success, message: 'Files deployed successfully to @sasjs/server.'}
'400':
description: 'Invalid Format'
content:
application/json:
schema:
$ref: '#/components/schemas/DeployResponse'
examples:
'Example 1':
value: {status: failure, message: 'Provided not supported data format.'}
'500':
description: 'Execution Error'
content:
application/json:
schema:
$ref: '#/components/schemas/DeployResponse'
examples:
'Example 1':
value: {status: failure, message: 'Deployment failed!'}
description: 'Creates/updates files within SASjs Drive using provided payload.'
tags:
- Drive
security:
-
bearerAuth: []
parameters: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/DeployPayload'
/SASjsApi/user:
get:
operationId: GetAllUsers
responses:
'200':
description: Ok
content:
application/json:
schema:
items:
$ref: '#/components/schemas/UserResponse'
type: array
examples:
'Example 1':
value: [{id: 123, username: johnusername, displayName: John}, {id: 456, username: starkusername, displayName: Stark}]
description: 'Get list of all users (username, displayname). All users can request this.'
tags:
- User
security:
-
bearerAuth: []
parameters: []
post:
operationId: CreateUser
responses:
'200':
description: Ok
content:
application/json:
schema:
$ref: '#/components/schemas/UserDetailsResponse'
examples:
'Example 1':
value: {id: 1234, displayName: 'John Snow', username: johnSnow01, isAdmin: false, isActive: true}
description: 'Create user with the following attributes: UserId, UserName, Password, isAdmin, isActive. Admin only task.'
tags:
- User
security:
-
bearerAuth: []
parameters: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UserPayload'
'/SASjsApi/user/{userId}':
get:
operationId: GetUser
responses:
'200':
description: Ok
content:
application/json:
schema:
$ref: '#/components/schemas/UserDetailsResponse'
description: 'Get user properties - such as group memberships, userName, displayName.'
tags:
- User
security:
-
bearerAuth: []
parameters:
-
description: 'The user''s identifier'
in: path
name: userId
required: true
schema:
format: double
type: number
example: 1234
patch:
operationId: UpdateUser
responses:
'200':
description: Ok
content:
application/json:
schema:
$ref: '#/components/schemas/UserDetailsResponse'
examples:
'Example 1':
value: {id: 1234, displayName: 'John Snow', username: johnSnow01, isAdmin: false, isActive: true}
description: 'Update user properties - such as displayName. Can be performed either by admins, or the user in question.'
tags:
- User
security:
-
bearerAuth: []
parameters:
-
description: 'The user''s identifier'
in: path
name: userId
required: true
schema:
format: double
type: number
example: '1234'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UserPayload'
delete:
operationId: DeleteUser
responses:
'204':
description: 'No content'
description: 'Delete a user. Can be performed either by admins, or the user in question.'
tags:
- User
security:
-
bearerAuth: []
parameters:
-
description: 'The user''s identifier'
in: path
name: userId
required: true
schema:
format: double
type: number
example: 1234
requestBody:
required: true
content:
application/json:
schema:
properties:
password:
type: string
type: object
/SASjsApi/group:
get:
operationId: GetAllGroups
responses:
'200':
description: Ok
content:
application/json:
schema:
items:
$ref: '#/components/schemas/GroupResponse'
type: array
examples:
'Example 1':
value: [{groupId: 123, name: DCGroup, description: 'This group represents Data Controller Users'}]
description: 'Get list of all groups (groupName and groupDescription). All users can request this.'
tags:
- Group
security:
-
bearerAuth: []
parameters: []
post:
operationId: CreateGroup
responses:
'200':
description: Ok
content:
application/json:
schema:
$ref: '#/components/schemas/GroupDetailsResponse'
examples:
'Example 1':
value: {groupId: 123, name: DCGroup, description: 'This group represents Data Controller Users', isActive: true, users: []}
description: 'Create a new group. Admin only.'
tags:
- Group
security:
-
bearerAuth: []
parameters: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GroupPayload'
'/SASjsApi/group/{groupId}':
get:
operationId: GetGroup
responses:
'200':
description: Ok
content:
application/json:
schema:
$ref: '#/components/schemas/GroupDetailsResponse'
description: 'Get list of members of a group (userName). All users can request this.'
tags:
- Group
security:
-
bearerAuth: []
parameters:
-
description: 'The group''s identifier'
in: path
name: groupId
required: true
schema:
format: double
type: number
example: 1234
delete:
operationId: DeleteGroup
responses:
'204':
description: 'No content'
description: 'Delete a group. Admin task only.'
tags:
- Group
security:
-
bearerAuth: []
parameters:
-
description: 'The group''s identifier'
in: path
name: groupId
required: true
schema:
format: double
type: number
example: 1234
'/SASjsApi/group/{groupId}/{userId}':
post:
operationId: AddUserToGroup
responses:
'200':
description: Ok
content:
application/json:
schema:
$ref: '#/components/schemas/GroupDetailsResponse'
examples:
'Example 1':
value: {groupId: 123, name: DCGroup, description: 'This group represents Data Controller Users', isActive: true, users: []}
description: 'Add a user to a group. Admin task only.'
tags:
- Group
security:
-
bearerAuth: []
parameters:
-
description: 'The group''s identifier'
in: path
name: groupId
required: true
schema:
format: double
type: number
example: '1234'
-
description: 'The user''s identifier'
in: path
name: userId
required: true
schema:
format: double
type: number
example: '6789'
delete:
operationId: RemoveUserFromGroup
responses:
'200':
description: Ok
content:
application/json:
schema:
$ref: '#/components/schemas/GroupDetailsResponse'
examples:
'Example 1':
value: {groupId: 123, name: DCGroup, description: 'This group represents Data Controller Users', isActive: true, users: []}
description: 'Remove a user to a group. Admin task only.'
tags:
- Group
security:
-
bearerAuth: []
parameters:
-
description: 'The group''s identifier'
in: path
name: groupId
required: true
schema:
format: double
type: number
example: '1234'
-
description: 'The user''s identifier'
in: path
name: userId
required: true
schema:
format: double
type: number
example: '6789'
/SASjsApi/client:
post:
operationId: CreateClient
responses:
'200':
description: Ok
content:
application/json:
schema:
$ref: '#/components/schemas/ClientPayload'
examples:
'Example 1':
value: {clientId: someFormattedClientID1234, clientSecret: someRandomCryptoString}
description: 'Create client with the following attributes: ClientId, ClientSecret. Admin only task.'
tags:
- Client
security:
-
bearerAuth: []
parameters: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ClientPayload'
/SASjsApi/auth/authorize:
post:
operationId: Authorize
responses:
'200':
description: Ok
content:
application/json:
schema:
$ref: '#/components/schemas/AuthorizeResponse'
examples:
'Example 1':
value: {code: someRandomCryptoString}
description: 'Accept a valid username/password, plus a CLIENT_ID, and return an AUTH_CODE'
tags:
- Auth
security: []
parameters: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AuthorizePayload'
/SASjsApi/auth/token:
post:
operationId: Token
responses:
'200':
description: Ok
content:
application/json:
schema:
$ref: '#/components/schemas/TokenResponse'
examples:
'Example 1':
value: {accessToken: someRandomCryptoString, refreshToken: someRandomCryptoString}
description: 'Accepts client/auth code and returns access/refresh tokens'
tags:
- Auth
security: []
parameters: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/TokenPayload'
/SASjsApi/auth/refresh:
post:
operationId: Refresh
responses:
'200':
description: Ok
content:
application/json:
schema:
$ref: '#/components/schemas/TokenResponse'
examples:
'Example 1':
value: {accessToken: someRandomCryptoString, refreshToken: someRandomCryptoString}
description: 'Returns new access/refresh tokens'
tags:
- Auth
security:
-
bearerAuth: []
parameters: []
/SASjsApi/auth/logout:
post:
operationId: Logout
responses:
'204':
description: 'No content'
description: 'Logout terminate access/refresh tokens and returns nothing'
tags:
- Auth
security:
-
bearerAuth: []
parameters: []
servers:
-
url: /
tags:
-
name: User
description: 'Operations about users'
-
name: Client
description: 'Operations about clients'
-
name: Auth
description: 'Operations about auth'
-
name: Drive
description: 'Operations about drive'
-
name: Group
description: 'Operations about group'

View File

@@ -1 +1 @@
CLIENT_ID=<place clientId here>
REACT_APP_CLIENT_ID=<place clientId here>