mirror of
https://github.com/sasjs/server.git
synced 2026-01-17 19:00:05 +00:00
chore: merge main into issue-198
This commit is contained in:
3
.github/FUNDING.yml
vendored
Normal file
3
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# These are supported funding model platforms
|
||||||
|
|
||||||
|
github: [sasjs]
|
||||||
48
CHANGELOG.md
48
CHANGELOG.md
@@ -1,3 +1,51 @@
|
|||||||
|
## [0.11.5](https://github.com/sasjs/server/compare/v0.11.4...v0.11.5) (2022-07-19)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* Revert "fix(security): missing cookie flags are added" ([ce5218a](https://github.com/sasjs/server/commit/ce5218a2278cc750f2b1032024685dc6cd72f796))
|
||||||
|
|
||||||
|
## [0.11.4](https://github.com/sasjs/server/compare/v0.11.3...v0.11.4) (2022-07-19)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **security:** missing cookie flags are added ([526402f](https://github.com/sasjs/server/commit/526402fd73407ee4fa2d31092111a7e6a1741487))
|
||||||
|
|
||||||
|
## [0.11.3](https://github.com/sasjs/server/compare/v0.11.2...v0.11.3) (2022-07-19)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* filePath fix in code.js file for windows ([2995121](https://github.com/sasjs/server/commit/299512135d77c2ac9e34853cf35aee6f2e1d4da4))
|
||||||
|
|
||||||
|
## [0.11.2](https://github.com/sasjs/server/compare/v0.11.1...v0.11.2) (2022-07-18)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* apply icon option only for sas.exe ([d2ddd8a](https://github.com/sasjs/server/commit/d2ddd8aacadfdd143026881f2c6ae8c6b277610a))
|
||||||
|
|
||||||
|
## [0.11.1](https://github.com/sasjs/server/compare/v0.11.0...v0.11.1) (2022-07-18)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* bank operator ([aa02741](https://github.com/sasjs/server/commit/aa027414ed3ce51f1014ef36c4191e064b2e963d))
|
||||||
|
* ensuring nosplash option only applies for sas.exe ([65e6de9](https://github.com/sasjs/server/commit/65e6de966383fe49a919b1f901d77c7f1e402c9b)), closes [#229](https://github.com/sasjs/server/issues/229)
|
||||||
|
|
||||||
|
# [0.11.0](https://github.com/sasjs/server/compare/v0.10.0...v0.11.0) (2022-07-16)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **logs:** logs location is configurable ([e024a92](https://github.com/sasjs/server/commit/e024a92f165990e08db8aa26ee326dbcb30e2e46))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **logs:** logs to file with rotating + code split into files ([92fda18](https://github.com/sasjs/server/commit/92fda183f3f0f3956b7c791669eb8dd52c389d1b))
|
||||||
|
|
||||||
# [0.10.0](https://github.com/sasjs/server/compare/v0.9.0...v0.10.0) (2022-07-06)
|
# [0.10.0](https://github.com/sasjs/server/compare/v0.9.0...v0.10.0) (2022-07-06)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -136,6 +136,9 @@ HELMET_CSP_CONFIG_PATH=./csp.config.json
|
|||||||
# Docs: https://www.npmjs.com/package/morgan#predefined-formats
|
# Docs: https://www.npmjs.com/package/morgan#predefined-formats
|
||||||
LOG_FORMAT_MORGAN=
|
LOG_FORMAT_MORGAN=
|
||||||
|
|
||||||
|
# This location is for server logs with classical UNIX logrotate behavior
|
||||||
|
LOG_LOCATION=./sasjs_root/logs
|
||||||
|
|
||||||
# A comma separated string that defines the available runTimes.
|
# A comma separated string that defines the available runTimes.
|
||||||
# Priority is given to the runtime that comes first in the string.
|
# Priority is given to the runtime that comes first in the string.
|
||||||
# Possible options at the moment are sas and js
|
# Possible options at the moment are sas and js
|
||||||
|
|||||||
@@ -21,3 +21,4 @@ NODE_PATH=~/.nvm/versions/node/v16.14.0/bin/node
|
|||||||
SASJS_ROOT=./sasjs_root
|
SASJS_ROOT=./sasjs_root
|
||||||
|
|
||||||
LOG_FORMAT_MORGAN=common
|
LOG_FORMAT_MORGAN=common
|
||||||
|
LOG_LOCATION=./sasjs_root/logs
|
||||||
1252
api/package-lock.json
generated
1252
api/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@
|
|||||||
"initial": "npm run swagger && npm run compileSysInit && npm run copySASjsCore",
|
"initial": "npm run swagger && npm run compileSysInit && npm run copySASjsCore",
|
||||||
"prestart": "npm run initial",
|
"prestart": "npm run initial",
|
||||||
"prebuild": "npm run initial",
|
"prebuild": "npm run initial",
|
||||||
"start": "nodemon ./src/server.ts",
|
"start": "NODE_ENV=development nodemon ./src/server.ts",
|
||||||
"start:prod": "node ./build/src/server.js",
|
"start:prod": "node ./build/src/server.js",
|
||||||
"build": "rimraf build && tsc",
|
"build": "rimraf build && tsc",
|
||||||
"postbuild": "npm run copy:files",
|
"postbuild": "npm run copy:files",
|
||||||
@@ -63,6 +63,7 @@
|
|||||||
"mongoose-sequence": "^5.3.1",
|
"mongoose-sequence": "^5.3.1",
|
||||||
"morgan": "^1.10.0",
|
"morgan": "^1.10.0",
|
||||||
"multer": "^1.4.3",
|
"multer": "^1.4.3",
|
||||||
|
"rotating-file-stream": "^3.0.4",
|
||||||
"swagger-ui-express": "4.3.0",
|
"swagger-ui-express": "4.3.0",
|
||||||
"unzipper": "^0.10.11",
|
"unzipper": "^0.10.11",
|
||||||
"url": "^0.10.3"
|
"url": "^0.10.3"
|
||||||
|
|||||||
@@ -85,10 +85,8 @@ components:
|
|||||||
type: string
|
type: string
|
||||||
_webout:
|
_webout:
|
||||||
anyOf:
|
anyOf:
|
||||||
-
|
- type: string
|
||||||
type: string
|
- $ref: '#/components/schemas/IRecordOfAny'
|
||||||
-
|
|
||||||
$ref: '#/components/schemas/IRecordOfAny'
|
|
||||||
log:
|
log:
|
||||||
items:
|
items:
|
||||||
$ref: '#/components/schemas/LogLine'
|
$ref: '#/components/schemas/LogLine'
|
||||||
@@ -137,12 +135,9 @@ components:
|
|||||||
members:
|
members:
|
||||||
items:
|
items:
|
||||||
anyOf:
|
anyOf:
|
||||||
-
|
- $ref: '#/components/schemas/FolderMember'
|
||||||
$ref: '#/components/schemas/FolderMember'
|
- $ref: '#/components/schemas/ServiceMember'
|
||||||
-
|
- $ref: '#/components/schemas/FileMember'
|
||||||
$ref: '#/components/schemas/ServiceMember'
|
|
||||||
-
|
|
||||||
$ref: '#/components/schemas/FileMember'
|
|
||||||
type: array
|
type: array
|
||||||
required:
|
required:
|
||||||
- name
|
- name
|
||||||
@@ -191,12 +186,9 @@ components:
|
|||||||
members:
|
members:
|
||||||
items:
|
items:
|
||||||
anyOf:
|
anyOf:
|
||||||
-
|
- $ref: '#/components/schemas/FolderMember'
|
||||||
$ref: '#/components/schemas/FolderMember'
|
- $ref: '#/components/schemas/ServiceMember'
|
||||||
-
|
- $ref: '#/components/schemas/FileMember'
|
||||||
$ref: '#/components/schemas/ServiceMember'
|
|
||||||
-
|
|
||||||
$ref: '#/components/schemas/FileMember'
|
|
||||||
type: array
|
type: array
|
||||||
required:
|
required:
|
||||||
- members
|
- members
|
||||||
@@ -382,7 +374,7 @@ components:
|
|||||||
autoExec:
|
autoExec:
|
||||||
type: string
|
type: string
|
||||||
description: 'User-specific auto-exec code'
|
description: 'User-specific auto-exec code'
|
||||||
example: ""
|
example: ''
|
||||||
required:
|
required:
|
||||||
- displayName
|
- displayName
|
||||||
- username
|
- username
|
||||||
@@ -619,7 +611,11 @@ paths:
|
|||||||
$ref: '#/components/schemas/TokenResponse'
|
$ref: '#/components/schemas/TokenResponse'
|
||||||
examples:
|
examples:
|
||||||
'Example 1':
|
'Example 1':
|
||||||
value: {accessToken: someRandomCryptoString, refreshToken: someRandomCryptoString}
|
value:
|
||||||
|
{
|
||||||
|
accessToken: someRandomCryptoString,
|
||||||
|
refreshToken: someRandomCryptoString
|
||||||
|
}
|
||||||
summary: 'Accepts client/auth code and returns access/refresh tokens'
|
summary: 'Accepts client/auth code and returns access/refresh tokens'
|
||||||
tags:
|
tags:
|
||||||
- Auth
|
- Auth
|
||||||
@@ -643,13 +639,16 @@ paths:
|
|||||||
$ref: '#/components/schemas/TokenResponse'
|
$ref: '#/components/schemas/TokenResponse'
|
||||||
examples:
|
examples:
|
||||||
'Example 1':
|
'Example 1':
|
||||||
value: {accessToken: someRandomCryptoString, refreshToken: someRandomCryptoString}
|
value:
|
||||||
|
{
|
||||||
|
accessToken: someRandomCryptoString,
|
||||||
|
refreshToken: someRandomCryptoString
|
||||||
|
}
|
||||||
summary: 'Returns new access/refresh tokens'
|
summary: 'Returns new access/refresh tokens'
|
||||||
tags:
|
tags:
|
||||||
- Auth
|
- Auth
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters: []
|
parameters: []
|
||||||
/SASjsApi/auth/logout:
|
/SASjsApi/auth/logout:
|
||||||
post:
|
post:
|
||||||
@@ -661,8 +660,7 @@ paths:
|
|||||||
tags:
|
tags:
|
||||||
- Auth
|
- Auth
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters: []
|
parameters: []
|
||||||
/SASjsApi/client:
|
/SASjsApi/client:
|
||||||
post:
|
post:
|
||||||
@@ -676,13 +674,16 @@ paths:
|
|||||||
$ref: '#/components/schemas/ClientPayload'
|
$ref: '#/components/schemas/ClientPayload'
|
||||||
examples:
|
examples:
|
||||||
'Example 1':
|
'Example 1':
|
||||||
value: {clientId: someFormattedClientID1234, clientSecret: someRandomCryptoString}
|
value:
|
||||||
|
{
|
||||||
|
clientId: someFormattedClientID1234,
|
||||||
|
clientSecret: someRandomCryptoString
|
||||||
|
}
|
||||||
summary: 'Create client with the following attributes: ClientId, ClientSecret. Admin only task.'
|
summary: 'Create client with the following attributes: ClientId, ClientSecret. Admin only task.'
|
||||||
tags:
|
tags:
|
||||||
- Client
|
- Client
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters: []
|
parameters: []
|
||||||
requestBody:
|
requestBody:
|
||||||
required: true
|
required: true
|
||||||
@@ -705,8 +706,7 @@ paths:
|
|||||||
tags:
|
tags:
|
||||||
- CODE
|
- CODE
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters: []
|
parameters: []
|
||||||
requestBody:
|
requestBody:
|
||||||
required: true
|
required: true
|
||||||
@@ -726,7 +726,11 @@ paths:
|
|||||||
$ref: '#/components/schemas/DeployResponse'
|
$ref: '#/components/schemas/DeployResponse'
|
||||||
examples:
|
examples:
|
||||||
'Example 1':
|
'Example 1':
|
||||||
value: {status: success, message: 'Files deployed successfully to @sasjs/server.'}
|
value:
|
||||||
|
{
|
||||||
|
status: success,
|
||||||
|
message: 'Files deployed successfully to @sasjs/server.'
|
||||||
|
}
|
||||||
'400':
|
'400':
|
||||||
description: 'Invalid Format'
|
description: 'Invalid Format'
|
||||||
content:
|
content:
|
||||||
@@ -735,7 +739,11 @@ paths:
|
|||||||
$ref: '#/components/schemas/DeployResponse'
|
$ref: '#/components/schemas/DeployResponse'
|
||||||
examples:
|
examples:
|
||||||
'Example 1':
|
'Example 1':
|
||||||
value: {status: failure, message: 'Provided not supported data format.'}
|
value:
|
||||||
|
{
|
||||||
|
status: failure,
|
||||||
|
message: 'Provided not supported data format.'
|
||||||
|
}
|
||||||
'500':
|
'500':
|
||||||
description: 'Execution Error'
|
description: 'Execution Error'
|
||||||
content:
|
content:
|
||||||
@@ -744,13 +752,12 @@ paths:
|
|||||||
$ref: '#/components/schemas/DeployResponse'
|
$ref: '#/components/schemas/DeployResponse'
|
||||||
examples:
|
examples:
|
||||||
'Example 1':
|
'Example 1':
|
||||||
value: {status: failure, message: 'Deployment failed!'}
|
value: { status: failure, message: 'Deployment failed!' }
|
||||||
summary: 'Creates/updates files within SASjs Drive using provided payload.'
|
summary: 'Creates/updates files within SASjs Drive using provided payload.'
|
||||||
tags:
|
tags:
|
||||||
- Drive
|
- Drive
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters: []
|
parameters: []
|
||||||
requestBody:
|
requestBody:
|
||||||
required: true
|
required: true
|
||||||
@@ -770,7 +777,11 @@ paths:
|
|||||||
$ref: '#/components/schemas/DeployResponse'
|
$ref: '#/components/schemas/DeployResponse'
|
||||||
examples:
|
examples:
|
||||||
'Example 1':
|
'Example 1':
|
||||||
value: {status: success, message: 'Files deployed successfully to @sasjs/server.'}
|
value:
|
||||||
|
{
|
||||||
|
status: success,
|
||||||
|
message: 'Files deployed successfully to @sasjs/server.'
|
||||||
|
}
|
||||||
'400':
|
'400':
|
||||||
description: 'Invalid Format'
|
description: 'Invalid Format'
|
||||||
content:
|
content:
|
||||||
@@ -779,7 +790,11 @@ paths:
|
|||||||
$ref: '#/components/schemas/DeployResponse'
|
$ref: '#/components/schemas/DeployResponse'
|
||||||
examples:
|
examples:
|
||||||
'Example 1':
|
'Example 1':
|
||||||
value: {status: failure, message: 'Provided not supported data format.'}
|
value:
|
||||||
|
{
|
||||||
|
status: failure,
|
||||||
|
message: 'Provided not supported data format.'
|
||||||
|
}
|
||||||
'500':
|
'500':
|
||||||
description: 'Execution Error'
|
description: 'Execution Error'
|
||||||
content:
|
content:
|
||||||
@@ -788,14 +803,13 @@ paths:
|
|||||||
$ref: '#/components/schemas/DeployResponse'
|
$ref: '#/components/schemas/DeployResponse'
|
||||||
examples:
|
examples:
|
||||||
'Example 1':
|
'Example 1':
|
||||||
value: {status: failure, message: 'Deployment failed!'}
|
value: { status: failure, message: 'Deployment failed!' }
|
||||||
description: "Accepts JSON file and zipped compressed JSON file as well.\nCompressed file should only contain one JSON file and should have same name\nas of compressed file e.g. deploy.JSON should be compressed to deploy.JSON.zip\nAny other file or JSON file in zipped will be ignored!"
|
description: "Accepts JSON file and zipped compressed JSON file as well.\nCompressed file should only contain one JSON file and should have same name\nas of compressed file e.g. deploy.JSON should be compressed to deploy.JSON.zip\nAny other file or JSON file in zipped will be ignored!"
|
||||||
summary: 'Creates/updates files within SASjs Drive using uploaded JSON/compressed JSON file.'
|
summary: 'Creates/updates files within SASjs Drive using uploaded JSON/compressed JSON file.'
|
||||||
tags:
|
tags:
|
||||||
- Drive
|
- Drive
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters: []
|
parameters: []
|
||||||
requestBody:
|
requestBody:
|
||||||
required: true
|
required: true
|
||||||
@@ -819,11 +833,9 @@ paths:
|
|||||||
tags:
|
tags:
|
||||||
- Drive
|
- Drive
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters:
|
parameters:
|
||||||
-
|
- in: query
|
||||||
in: query
|
|
||||||
name: _filePath
|
name: _filePath
|
||||||
required: true
|
required: true
|
||||||
schema:
|
schema:
|
||||||
@@ -838,7 +850,7 @@ paths:
|
|||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
properties:
|
properties:
|
||||||
status: {type: string}
|
status: { type: string }
|
||||||
required:
|
required:
|
||||||
- status
|
- status
|
||||||
type: object
|
type: object
|
||||||
@@ -846,11 +858,9 @@ paths:
|
|||||||
tags:
|
tags:
|
||||||
- Drive
|
- Drive
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters:
|
parameters:
|
||||||
-
|
- in: query
|
||||||
in: query
|
|
||||||
name: _filePath
|
name: _filePath
|
||||||
required: true
|
required: true
|
||||||
schema:
|
schema:
|
||||||
@@ -867,7 +877,7 @@ paths:
|
|||||||
$ref: '#/components/schemas/FileFolderResponse'
|
$ref: '#/components/schemas/FileFolderResponse'
|
||||||
examples:
|
examples:
|
||||||
'Example 1':
|
'Example 1':
|
||||||
value: {status: success}
|
value: { status: success }
|
||||||
'403':
|
'403':
|
||||||
description: 'File already exists'
|
description: 'File already exists'
|
||||||
content:
|
content:
|
||||||
@@ -876,17 +886,15 @@ paths:
|
|||||||
$ref: '#/components/schemas/FileFolderResponse'
|
$ref: '#/components/schemas/FileFolderResponse'
|
||||||
examples:
|
examples:
|
||||||
'Example 1':
|
'Example 1':
|
||||||
value: {status: failure, message: 'File request failed.'}
|
value: { status: failure, message: 'File request failed.' }
|
||||||
description: "It's optional to either provide `_filePath` in url as query parameter\nOr provide `filePath` in body as form field.\nBut it's required to provide else API will respond with Bad Request."
|
description: "It's optional to either provide `_filePath` in url as query parameter\nOr provide `filePath` in body as form field.\nBut it's required to provide else API will respond with Bad Request."
|
||||||
summary: 'Create a file in SASjs Drive'
|
summary: 'Create a file in SASjs Drive'
|
||||||
tags:
|
tags:
|
||||||
- Drive
|
- Drive
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters:
|
parameters:
|
||||||
-
|
- description: 'Location of file'
|
||||||
description: 'Location of file'
|
|
||||||
in: query
|
in: query
|
||||||
name: _filePath
|
name: _filePath
|
||||||
required: false
|
required: false
|
||||||
@@ -918,26 +926,24 @@ paths:
|
|||||||
$ref: '#/components/schemas/FileFolderResponse'
|
$ref: '#/components/schemas/FileFolderResponse'
|
||||||
examples:
|
examples:
|
||||||
'Example 1':
|
'Example 1':
|
||||||
value: {status: success}
|
value: { status: success }
|
||||||
'403':
|
'403':
|
||||||
description: ""
|
description: ''
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/FileFolderResponse'
|
$ref: '#/components/schemas/FileFolderResponse'
|
||||||
examples:
|
examples:
|
||||||
'Example 1':
|
'Example 1':
|
||||||
value: {status: failure, message: 'File request failed.'}
|
value: { status: failure, message: 'File request failed.' }
|
||||||
description: "It's optional to either provide `_filePath` in url as query parameter\nOr provide `filePath` in body as form field.\nBut it's required to provide else API will respond with Bad Request."
|
description: "It's optional to either provide `_filePath` in url as query parameter\nOr provide `filePath` in body as form field.\nBut it's required to provide else API will respond with Bad Request."
|
||||||
summary: 'Modify a file in SASjs Drive'
|
summary: 'Modify a file in SASjs Drive'
|
||||||
tags:
|
tags:
|
||||||
- Drive
|
- Drive
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters:
|
parameters:
|
||||||
-
|
- description: 'Location of SAS program'
|
||||||
description: 'Location of SAS program'
|
|
||||||
in: query
|
in: query
|
||||||
name: _filePath
|
name: _filePath
|
||||||
required: false
|
required: false
|
||||||
@@ -968,8 +974,8 @@ paths:
|
|||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
properties:
|
properties:
|
||||||
folders: {items: {type: string}, type: array}
|
folders: { items: { type: string }, type: array }
|
||||||
files: {items: {type: string}, type: array}
|
files: { items: { type: string }, type: array }
|
||||||
required:
|
required:
|
||||||
- folders
|
- folders
|
||||||
- files
|
- files
|
||||||
@@ -978,11 +984,9 @@ paths:
|
|||||||
tags:
|
tags:
|
||||||
- Drive
|
- Drive
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters:
|
parameters:
|
||||||
-
|
- in: query
|
||||||
in: query
|
|
||||||
name: _folderPath
|
name: _folderPath
|
||||||
required: false
|
required: false
|
||||||
schema:
|
schema:
|
||||||
@@ -997,7 +1001,7 @@ paths:
|
|||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
properties:
|
properties:
|
||||||
status: {type: string}
|
status: { type: string }
|
||||||
required:
|
required:
|
||||||
- status
|
- status
|
||||||
type: object
|
type: object
|
||||||
@@ -1005,11 +1009,9 @@ paths:
|
|||||||
tags:
|
tags:
|
||||||
- Drive
|
- Drive
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters:
|
parameters:
|
||||||
-
|
- in: query
|
||||||
in: query
|
|
||||||
name: _folderPath
|
name: _folderPath
|
||||||
required: true
|
required: true
|
||||||
schema:
|
schema:
|
||||||
@@ -1026,7 +1028,7 @@ paths:
|
|||||||
$ref: '#/components/schemas/FileFolderResponse'
|
$ref: '#/components/schemas/FileFolderResponse'
|
||||||
examples:
|
examples:
|
||||||
'Example 1':
|
'Example 1':
|
||||||
value: {status: success}
|
value: { status: success }
|
||||||
'409':
|
'409':
|
||||||
description: 'Folder already exists'
|
description: 'Folder already exists'
|
||||||
content:
|
content:
|
||||||
@@ -1035,13 +1037,13 @@ paths:
|
|||||||
$ref: '#/components/schemas/FileFolderResponse'
|
$ref: '#/components/schemas/FileFolderResponse'
|
||||||
examples:
|
examples:
|
||||||
'Example 1':
|
'Example 1':
|
||||||
value: {status: failure, message: 'Add folder request failed.'}
|
value:
|
||||||
|
{ status: failure, message: 'Add folder request failed.' }
|
||||||
summary: 'Create an empty folder in SASjs Drive'
|
summary: 'Create an empty folder in SASjs Drive'
|
||||||
tags:
|
tags:
|
||||||
- Drive
|
- Drive
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters: []
|
parameters: []
|
||||||
requestBody:
|
requestBody:
|
||||||
required: true
|
required: true
|
||||||
@@ -1061,7 +1063,7 @@ paths:
|
|||||||
$ref: '#/components/schemas/FileFolderResponse'
|
$ref: '#/components/schemas/FileFolderResponse'
|
||||||
examples:
|
examples:
|
||||||
'Example 1':
|
'Example 1':
|
||||||
value: {status: success}
|
value: { status: success }
|
||||||
'409':
|
'409':
|
||||||
description: 'Folder already exists'
|
description: 'Folder already exists'
|
||||||
content:
|
content:
|
||||||
@@ -1070,13 +1072,12 @@ paths:
|
|||||||
$ref: '#/components/schemas/FileFolderResponse'
|
$ref: '#/components/schemas/FileFolderResponse'
|
||||||
examples:
|
examples:
|
||||||
'Example 1':
|
'Example 1':
|
||||||
value: {status: failure, message: 'rename request failed.'}
|
value: { status: failure, message: 'rename request failed.' }
|
||||||
summary: 'Renames a file/folder in SASjs Drive'
|
summary: 'Renames a file/folder in SASjs Drive'
|
||||||
tags:
|
tags:
|
||||||
- Drive
|
- Drive
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters: []
|
parameters: []
|
||||||
requestBody:
|
requestBody:
|
||||||
required: true
|
required: true
|
||||||
@@ -1098,8 +1099,7 @@ paths:
|
|||||||
tags:
|
tags:
|
||||||
- Drive
|
- Drive
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters: []
|
parameters: []
|
||||||
/SASjsApi/user:
|
/SASjsApi/user:
|
||||||
get:
|
get:
|
||||||
@@ -1115,13 +1115,26 @@ paths:
|
|||||||
type: array
|
type: array
|
||||||
examples:
|
examples:
|
||||||
'Example 1':
|
'Example 1':
|
||||||
value: [{id: 123, username: johnusername, displayName: John, isAdmin: false}, {id: 456, username: starkusername, displayName: Stark, isAdmin: true}]
|
value:
|
||||||
|
[
|
||||||
|
{
|
||||||
|
id: 123,
|
||||||
|
username: johnusername,
|
||||||
|
displayName: John,
|
||||||
|
isAdmin: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 456,
|
||||||
|
username: starkusername,
|
||||||
|
displayName: Stark,
|
||||||
|
isAdmin: true
|
||||||
|
}
|
||||||
|
]
|
||||||
summary: '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:
|
tags:
|
||||||
- User
|
- User
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters: []
|
parameters: []
|
||||||
post:
|
post:
|
||||||
operationId: CreateUser
|
operationId: CreateUser
|
||||||
@@ -1134,13 +1147,19 @@ paths:
|
|||||||
$ref: '#/components/schemas/UserDetailsResponse'
|
$ref: '#/components/schemas/UserDetailsResponse'
|
||||||
examples:
|
examples:
|
||||||
'Example 1':
|
'Example 1':
|
||||||
value: {id: 1234, displayName: 'John Snow', username: johnSnow01, isAdmin: false, isActive: true}
|
value:
|
||||||
|
{
|
||||||
|
id: 1234,
|
||||||
|
displayName: 'John Snow',
|
||||||
|
username: johnSnow01,
|
||||||
|
isAdmin: false,
|
||||||
|
isActive: true
|
||||||
|
}
|
||||||
summary: '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:
|
tags:
|
||||||
- User
|
- User
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters: []
|
parameters: []
|
||||||
requestBody:
|
requestBody:
|
||||||
required: true
|
required: true
|
||||||
@@ -1163,11 +1182,9 @@ paths:
|
|||||||
tags:
|
tags:
|
||||||
- User
|
- User
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters:
|
parameters:
|
||||||
-
|
- description: "The User's username"
|
||||||
description: 'The User''s username'
|
|
||||||
in: path
|
in: path
|
||||||
name: username
|
name: username
|
||||||
required: true
|
required: true
|
||||||
@@ -1185,16 +1202,21 @@ paths:
|
|||||||
$ref: '#/components/schemas/UserDetailsResponse'
|
$ref: '#/components/schemas/UserDetailsResponse'
|
||||||
examples:
|
examples:
|
||||||
'Example 1':
|
'Example 1':
|
||||||
value: {id: 1234, displayName: 'John Snow', username: johnSnow01, isAdmin: false, isActive: true}
|
value:
|
||||||
|
{
|
||||||
|
id: 1234,
|
||||||
|
displayName: 'John Snow',
|
||||||
|
username: johnSnow01,
|
||||||
|
isAdmin: false,
|
||||||
|
isActive: true
|
||||||
|
}
|
||||||
summary: '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:
|
tags:
|
||||||
- User
|
- User
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters:
|
parameters:
|
||||||
-
|
- description: "The User's username"
|
||||||
description: 'The User''s username'
|
|
||||||
in: path
|
in: path
|
||||||
name: username
|
name: username
|
||||||
required: true
|
required: true
|
||||||
@@ -1216,11 +1238,9 @@ paths:
|
|||||||
tags:
|
tags:
|
||||||
- User
|
- User
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters:
|
parameters:
|
||||||
-
|
- description: "The User's username"
|
||||||
description: 'The User''s username'
|
|
||||||
in: path
|
in: path
|
||||||
name: username
|
name: username
|
||||||
required: true
|
required: true
|
||||||
@@ -1251,11 +1271,9 @@ paths:
|
|||||||
tags:
|
tags:
|
||||||
- User
|
- User
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters:
|
parameters:
|
||||||
-
|
- description: "The user's identifier"
|
||||||
description: 'The user''s identifier'
|
|
||||||
in: path
|
in: path
|
||||||
name: userId
|
name: userId
|
||||||
required: true
|
required: true
|
||||||
@@ -1274,16 +1292,21 @@ paths:
|
|||||||
$ref: '#/components/schemas/UserDetailsResponse'
|
$ref: '#/components/schemas/UserDetailsResponse'
|
||||||
examples:
|
examples:
|
||||||
'Example 1':
|
'Example 1':
|
||||||
value: {id: 1234, displayName: 'John Snow', username: johnSnow01, isAdmin: false, isActive: true}
|
value:
|
||||||
|
{
|
||||||
|
id: 1234,
|
||||||
|
displayName: 'John Snow',
|
||||||
|
username: johnSnow01,
|
||||||
|
isAdmin: false,
|
||||||
|
isActive: true
|
||||||
|
}
|
||||||
summary: '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:
|
tags:
|
||||||
- User
|
- User
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters:
|
parameters:
|
||||||
-
|
- description: "The user's identifier"
|
||||||
description: 'The user''s identifier'
|
|
||||||
in: path
|
in: path
|
||||||
name: userId
|
name: userId
|
||||||
required: true
|
required: true
|
||||||
@@ -1306,11 +1329,9 @@ paths:
|
|||||||
tags:
|
tags:
|
||||||
- User
|
- User
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters:
|
parameters:
|
||||||
-
|
- description: "The user's identifier"
|
||||||
description: 'The user''s identifier'
|
|
||||||
in: path
|
in: path
|
||||||
name: userId
|
name: userId
|
||||||
required: true
|
required: true
|
||||||
@@ -1341,13 +1362,19 @@ paths:
|
|||||||
type: array
|
type: array
|
||||||
examples:
|
examples:
|
||||||
'Example 1':
|
'Example 1':
|
||||||
value: [{groupId: 123, name: DCGroup, description: 'This group represents Data Controller Users'}]
|
value:
|
||||||
|
[
|
||||||
|
{
|
||||||
|
groupId: 123,
|
||||||
|
name: DCGroup,
|
||||||
|
description: 'This group represents Data Controller Users'
|
||||||
|
}
|
||||||
|
]
|
||||||
summary: '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:
|
tags:
|
||||||
- Group
|
- Group
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters: []
|
parameters: []
|
||||||
post:
|
post:
|
||||||
operationId: CreateGroup
|
operationId: CreateGroup
|
||||||
@@ -1360,13 +1387,19 @@ paths:
|
|||||||
$ref: '#/components/schemas/GroupDetailsResponse'
|
$ref: '#/components/schemas/GroupDetailsResponse'
|
||||||
examples:
|
examples:
|
||||||
'Example 1':
|
'Example 1':
|
||||||
value: {groupId: 123, name: DCGroup, description: 'This group represents Data Controller Users', isActive: true, users: []}
|
value:
|
||||||
|
{
|
||||||
|
groupId: 123,
|
||||||
|
name: DCGroup,
|
||||||
|
description: 'This group represents Data Controller Users',
|
||||||
|
isActive: true,
|
||||||
|
users: []
|
||||||
|
}
|
||||||
summary: 'Create a new group. Admin only.'
|
summary: 'Create a new group. Admin only.'
|
||||||
tags:
|
tags:
|
||||||
- Group
|
- Group
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters: []
|
parameters: []
|
||||||
requestBody:
|
requestBody:
|
||||||
required: true
|
required: true
|
||||||
@@ -1388,11 +1421,9 @@ paths:
|
|||||||
tags:
|
tags:
|
||||||
- Group
|
- Group
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters:
|
parameters:
|
||||||
-
|
- description: "The group's name"
|
||||||
description: 'The group''s name'
|
|
||||||
in: path
|
in: path
|
||||||
name: name
|
name: name
|
||||||
required: true
|
required: true
|
||||||
@@ -1412,11 +1443,9 @@ paths:
|
|||||||
tags:
|
tags:
|
||||||
- Group
|
- Group
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters:
|
parameters:
|
||||||
-
|
- description: "The group's identifier"
|
||||||
description: 'The group''s identifier'
|
|
||||||
in: path
|
in: path
|
||||||
name: groupId
|
name: groupId
|
||||||
required: true
|
required: true
|
||||||
@@ -1433,17 +1462,15 @@ paths:
|
|||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
allOf:
|
allOf:
|
||||||
- {$ref: '#/components/schemas/IGroup'}
|
- { $ref: '#/components/schemas/IGroup' }
|
||||||
- {properties: {_id: {}}, required: [_id], type: object}
|
- { properties: { _id: {} }, required: [_id], type: object }
|
||||||
summary: 'Delete a group. Admin task only.'
|
summary: 'Delete a group. Admin task only.'
|
||||||
tags:
|
tags:
|
||||||
- Group
|
- Group
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters:
|
parameters:
|
||||||
-
|
- description: "The group's identifier"
|
||||||
description: 'The group''s identifier'
|
|
||||||
in: path
|
in: path
|
||||||
name: groupId
|
name: groupId
|
||||||
required: true
|
required: true
|
||||||
@@ -1463,16 +1490,21 @@ paths:
|
|||||||
$ref: '#/components/schemas/GroupDetailsResponse'
|
$ref: '#/components/schemas/GroupDetailsResponse'
|
||||||
examples:
|
examples:
|
||||||
'Example 1':
|
'Example 1':
|
||||||
value: {groupId: 123, name: DCGroup, description: 'This group represents Data Controller Users', isActive: true, users: []}
|
value:
|
||||||
|
{
|
||||||
|
groupId: 123,
|
||||||
|
name: DCGroup,
|
||||||
|
description: 'This group represents Data Controller Users',
|
||||||
|
isActive: true,
|
||||||
|
users: []
|
||||||
|
}
|
||||||
summary: 'Add a user to a group. Admin task only.'
|
summary: 'Add a user to a group. Admin task only.'
|
||||||
tags:
|
tags:
|
||||||
- Group
|
- Group
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters:
|
parameters:
|
||||||
-
|
- description: "The group's identifier"
|
||||||
description: 'The group''s identifier'
|
|
||||||
in: path
|
in: path
|
||||||
name: groupId
|
name: groupId
|
||||||
required: true
|
required: true
|
||||||
@@ -1480,8 +1512,7 @@ paths:
|
|||||||
format: double
|
format: double
|
||||||
type: number
|
type: number
|
||||||
example: '1234'
|
example: '1234'
|
||||||
-
|
- description: "The user's identifier"
|
||||||
description: 'The user''s identifier'
|
|
||||||
in: path
|
in: path
|
||||||
name: userId
|
name: userId
|
||||||
required: true
|
required: true
|
||||||
@@ -1500,16 +1531,21 @@ paths:
|
|||||||
$ref: '#/components/schemas/GroupDetailsResponse'
|
$ref: '#/components/schemas/GroupDetailsResponse'
|
||||||
examples:
|
examples:
|
||||||
'Example 1':
|
'Example 1':
|
||||||
value: {groupId: 123, name: DCGroup, description: 'This group represents Data Controller Users', isActive: true, users: []}
|
value:
|
||||||
|
{
|
||||||
|
groupId: 123,
|
||||||
|
name: DCGroup,
|
||||||
|
description: 'This group represents Data Controller Users',
|
||||||
|
isActive: true,
|
||||||
|
users: []
|
||||||
|
}
|
||||||
summary: 'Remove a user to a group. Admin task only.'
|
summary: 'Remove a user to a group. Admin task only.'
|
||||||
tags:
|
tags:
|
||||||
- Group
|
- Group
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters:
|
parameters:
|
||||||
-
|
- description: "The group's identifier"
|
||||||
description: 'The group''s identifier'
|
|
||||||
in: path
|
in: path
|
||||||
name: groupId
|
name: groupId
|
||||||
required: true
|
required: true
|
||||||
@@ -1517,8 +1553,7 @@ paths:
|
|||||||
format: double
|
format: double
|
||||||
type: number
|
type: number
|
||||||
example: '1234'
|
example: '1234'
|
||||||
-
|
- description: "The user's identifier"
|
||||||
description: 'The user''s identifier'
|
|
||||||
in: path
|
in: path
|
||||||
name: userId
|
name: userId
|
||||||
required: true
|
required: true
|
||||||
@@ -1538,7 +1573,14 @@ paths:
|
|||||||
$ref: '#/components/schemas/InfoResponse'
|
$ref: '#/components/schemas/InfoResponse'
|
||||||
examples:
|
examples:
|
||||||
'Example 1':
|
'Example 1':
|
||||||
value: {mode: desktop, cors: enable, whiteList: ['http://example.com', 'http://example2.com'], protocol: http, runTimes: [sas, js]}
|
value:
|
||||||
|
{
|
||||||
|
mode: desktop,
|
||||||
|
cors: enable,
|
||||||
|
whiteList: ['http://example.com', 'http://example2.com'],
|
||||||
|
protocol: http,
|
||||||
|
runTimes: [sas, js]
|
||||||
|
}
|
||||||
summary: 'Get server info (mode, cors, whiteList, protocol).'
|
summary: 'Get server info (mode, cors, whiteList, protocol).'
|
||||||
tags:
|
tags:
|
||||||
- Info
|
- Info
|
||||||
@@ -1556,7 +1598,7 @@ paths:
|
|||||||
$ref: '#/components/schemas/AuthorizedRoutesResponse'
|
$ref: '#/components/schemas/AuthorizedRoutesResponse'
|
||||||
examples:
|
examples:
|
||||||
'Example 1':
|
'Example 1':
|
||||||
value: {URIs: [/AppStream, /SASjsApi/stp/execute]}
|
value: { URIs: [/AppStream, /SASjsApi/stp/execute] }
|
||||||
summary: 'Get authorized routes.'
|
summary: 'Get authorized routes.'
|
||||||
tags:
|
tags:
|
||||||
- Info
|
- Info
|
||||||
@@ -1574,13 +1616,18 @@ paths:
|
|||||||
$ref: '#/components/schemas/UserResponse'
|
$ref: '#/components/schemas/UserResponse'
|
||||||
examples:
|
examples:
|
||||||
'Example 1':
|
'Example 1':
|
||||||
value: {id: 123, username: johnusername, displayName: John, isAdmin: false}
|
value:
|
||||||
|
{
|
||||||
|
id: 123,
|
||||||
|
username: johnusername,
|
||||||
|
displayName: John,
|
||||||
|
isAdmin: false
|
||||||
|
}
|
||||||
summary: 'Get session info (username).'
|
summary: 'Get session info (username).'
|
||||||
tags:
|
tags:
|
||||||
- Session
|
- Session
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters: []
|
parameters: []
|
||||||
/SASjsApi/stp/execute:
|
/SASjsApi/stp/execute:
|
||||||
get:
|
get:
|
||||||
@@ -1592,18 +1639,16 @@ paths:
|
|||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
anyOf:
|
anyOf:
|
||||||
- {type: string}
|
- { type: string }
|
||||||
- {type: string, format: byte}
|
- { type: string, format: byte }
|
||||||
description: "Trigger a SAS or JS program using the _program URL parameter.\n\nAccepts URL parameters and file uploads. For more details, see docs:\n\nhttps://server.sasjs.io/storedprograms"
|
description: "Trigger a SAS or JS program using the _program URL parameter.\n\nAccepts URL parameters and file uploads. For more details, see docs:\n\nhttps://server.sasjs.io/storedprograms"
|
||||||
summary: 'Execute a Stored Program, returns raw _webout content.'
|
summary: 'Execute a Stored Program, returns raw _webout content.'
|
||||||
tags:
|
tags:
|
||||||
- STP
|
- STP
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters:
|
parameters:
|
||||||
-
|
- description: 'Location of SAS or JS code'
|
||||||
description: 'Location of SAS or JS code'
|
|
||||||
in: query
|
in: query
|
||||||
name: _program
|
name: _program
|
||||||
required: true
|
required: true
|
||||||
@@ -1621,17 +1666,25 @@ paths:
|
|||||||
$ref: '#/components/schemas/ExecuteReturnJsonResponse'
|
$ref: '#/components/schemas/ExecuteReturnJsonResponse'
|
||||||
examples:
|
examples:
|
||||||
'Example 1':
|
'Example 1':
|
||||||
value: {status: success, _webout: 'webout content', log: [], httpHeaders: {Content-type: application/zip, Cache-Control: 'public, max-age=1000'}}
|
value:
|
||||||
|
{
|
||||||
|
status: success,
|
||||||
|
_webout: 'webout content',
|
||||||
|
log: [],
|
||||||
|
httpHeaders:
|
||||||
|
{
|
||||||
|
Content-type: application/zip,
|
||||||
|
Cache-Control: 'public, max-age=1000'
|
||||||
|
}
|
||||||
|
}
|
||||||
description: "Trigger a SAS or JS program using the _program URL parameter.\n\nAccepts URL parameters and file uploads. For more details, see docs:\n\nhttps://server.sasjs.io/storedprograms\n\nThe response will be a JSON object with the following root attributes:\nlog, webout, headers.\n\nThe webout attribute will be nested JSON ONLY if the response-header\ncontains a content-type of application/json AND it is valid JSON.\nOtherwise it will be a stringified version of the webout content."
|
description: "Trigger a SAS or JS program using the _program URL parameter.\n\nAccepts URL parameters and file uploads. For more details, see docs:\n\nhttps://server.sasjs.io/storedprograms\n\nThe response will be a JSON object with the following root attributes:\nlog, webout, headers.\n\nThe webout attribute will be nested JSON ONLY if the response-header\ncontains a content-type of application/json AND it is valid JSON.\nOtherwise it will be a stringified version of the webout content."
|
||||||
summary: 'Execute a Stored Program, return a JSON object'
|
summary: 'Execute a Stored Program, return a JSON object'
|
||||||
tags:
|
tags:
|
||||||
- STP
|
- STP
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters:
|
parameters:
|
||||||
-
|
- description: 'Location of SAS or JS code'
|
||||||
description: 'Location of SAS or JS code'
|
|
||||||
in: query
|
in: query
|
||||||
name: _program
|
name: _program
|
||||||
required: false
|
required: false
|
||||||
@@ -1669,8 +1722,19 @@ paths:
|
|||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
properties:
|
properties:
|
||||||
user: {properties: {isAdmin: {type: boolean}, displayName: {type: string}, username: {type: string}, id: {type: number, format: double}}, required: [isAdmin, displayName, username, id], type: object}
|
user:
|
||||||
loggedIn: {type: boolean}
|
{
|
||||||
|
properties:
|
||||||
|
{
|
||||||
|
isAdmin: { type: boolean },
|
||||||
|
displayName: { type: string },
|
||||||
|
username: { type: string },
|
||||||
|
id: { type: number, format: double }
|
||||||
|
},
|
||||||
|
required: [isAdmin, displayName, username, id],
|
||||||
|
type: object
|
||||||
|
}
|
||||||
|
loggedIn: { type: boolean }
|
||||||
required:
|
required:
|
||||||
- user
|
- user
|
||||||
- loggedIn
|
- loggedIn
|
||||||
@@ -1698,7 +1762,7 @@ paths:
|
|||||||
$ref: '#/components/schemas/AuthorizeResponse'
|
$ref: '#/components/schemas/AuthorizeResponse'
|
||||||
examples:
|
examples:
|
||||||
'Example 1':
|
'Example 1':
|
||||||
value: {code: someRandomCryptoString}
|
value: { code: someRandomCryptoString }
|
||||||
summary: '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:
|
tags:
|
||||||
- Web
|
- Web
|
||||||
@@ -1738,13 +1802,39 @@ paths:
|
|||||||
type: array
|
type: array
|
||||||
examples:
|
examples:
|
||||||
'Example 1':
|
'Example 1':
|
||||||
value: [{permissionId: 123, uri: /SASjsApi/code/execute, setting: Grant, user: {id: 1, username: johnSnow01, displayName: 'John Snow', isAdmin: false}}, {permissionId: 124, uri: /SASjsApi/code/execute, setting: Grant, group: {groupId: 1, name: DCGroup, description: 'This group represents Data Controller Users', isActive: true, users: []}}]
|
value:
|
||||||
|
[
|
||||||
|
{
|
||||||
|
permissionId: 123,
|
||||||
|
uri: /SASjsApi/code/execute,
|
||||||
|
setting: Grant,
|
||||||
|
user:
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
username: johnSnow01,
|
||||||
|
displayName: 'John Snow',
|
||||||
|
isAdmin: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
permissionId: 124,
|
||||||
|
uri: /SASjsApi/code/execute,
|
||||||
|
setting: Grant,
|
||||||
|
group:
|
||||||
|
{
|
||||||
|
groupId: 1,
|
||||||
|
name: DCGroup,
|
||||||
|
description: 'This group represents Data Controller Users',
|
||||||
|
isActive: true,
|
||||||
|
users: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
summary: 'Get list of all permissions (uri, setting and userDetail).'
|
summary: 'Get list of all permissions (uri, setting and userDetail).'
|
||||||
tags:
|
tags:
|
||||||
- Permission
|
- Permission
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters: []
|
parameters: []
|
||||||
post:
|
post:
|
||||||
operationId: CreatePermission
|
operationId: CreatePermission
|
||||||
@@ -1757,13 +1847,24 @@ paths:
|
|||||||
$ref: '#/components/schemas/PermissionDetailsResponse'
|
$ref: '#/components/schemas/PermissionDetailsResponse'
|
||||||
examples:
|
examples:
|
||||||
'Example 1':
|
'Example 1':
|
||||||
value: {permissionId: 123, uri: /SASjsApi/code/execute, setting: Grant, user: {id: 1, username: johnSnow01, displayName: 'John Snow', isAdmin: false}}
|
value:
|
||||||
|
{
|
||||||
|
permissionId: 123,
|
||||||
|
uri: /SASjsApi/code/execute,
|
||||||
|
setting: Grant,
|
||||||
|
user:
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
username: johnSnow01,
|
||||||
|
displayName: 'John Snow',
|
||||||
|
isAdmin: false
|
||||||
|
}
|
||||||
|
}
|
||||||
summary: 'Create a new permission. Admin only.'
|
summary: 'Create a new permission. Admin only.'
|
||||||
tags:
|
tags:
|
||||||
- Permission
|
- Permission
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters: []
|
parameters: []
|
||||||
requestBody:
|
requestBody:
|
||||||
required: true
|
required: true
|
||||||
@@ -1783,16 +1884,26 @@ paths:
|
|||||||
$ref: '#/components/schemas/PermissionDetailsResponse'
|
$ref: '#/components/schemas/PermissionDetailsResponse'
|
||||||
examples:
|
examples:
|
||||||
'Example 1':
|
'Example 1':
|
||||||
value: {permissionId: 123, uri: /SASjsApi/code/execute, setting: Grant, user: {id: 1, username: johnSnow01, displayName: 'John Snow', isAdmin: false}}
|
value:
|
||||||
|
{
|
||||||
|
permissionId: 123,
|
||||||
|
uri: /SASjsApi/code/execute,
|
||||||
|
setting: Grant,
|
||||||
|
user:
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
username: johnSnow01,
|
||||||
|
displayName: 'John Snow',
|
||||||
|
isAdmin: false
|
||||||
|
}
|
||||||
|
}
|
||||||
summary: 'Update permission setting. Admin only'
|
summary: 'Update permission setting. Admin only'
|
||||||
tags:
|
tags:
|
||||||
- Permission
|
- Permission
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters:
|
parameters:
|
||||||
-
|
- description: "The permission's identifier"
|
||||||
description: 'The permission''s identifier'
|
|
||||||
in: path
|
in: path
|
||||||
name: permissionId
|
name: permissionId
|
||||||
required: true
|
required: true
|
||||||
@@ -1815,11 +1926,9 @@ paths:
|
|||||||
tags:
|
tags:
|
||||||
- Permission
|
- Permission
|
||||||
security:
|
security:
|
||||||
-
|
- bearerAuth: []
|
||||||
bearerAuth: []
|
|
||||||
parameters:
|
parameters:
|
||||||
-
|
- description: "The user's identifier"
|
||||||
description: 'The user''s identifier'
|
|
||||||
in: path
|
in: path
|
||||||
name: permissionId
|
name: permissionId
|
||||||
required: true
|
required: true
|
||||||
@@ -1828,39 +1937,27 @@ paths:
|
|||||||
type: number
|
type: number
|
||||||
example: 1234
|
example: 1234
|
||||||
servers:
|
servers:
|
||||||
-
|
- url: /
|
||||||
url: /
|
|
||||||
tags:
|
tags:
|
||||||
-
|
- name: Auth
|
||||||
name: Auth
|
|
||||||
description: 'Operations about auth'
|
description: 'Operations about auth'
|
||||||
-
|
- name: Client
|
||||||
name: Client
|
|
||||||
description: 'Operations about clients'
|
description: 'Operations about clients'
|
||||||
-
|
- name: CODE
|
||||||
name: CODE
|
|
||||||
description: 'Execution of code (various runtimes are supported)'
|
description: 'Execution of code (various runtimes are supported)'
|
||||||
-
|
- name: Drive
|
||||||
name: Drive
|
|
||||||
description: 'Operations on SASjs Drive'
|
description: 'Operations on SASjs Drive'
|
||||||
-
|
- name: Group
|
||||||
name: Group
|
|
||||||
description: 'Operations on groups and group memberships'
|
description: 'Operations on groups and group memberships'
|
||||||
-
|
- name: Info
|
||||||
name: Info
|
|
||||||
description: 'Get Server Information'
|
description: 'Get Server Information'
|
||||||
-
|
- name: Permission
|
||||||
name: Permission
|
|
||||||
description: 'Operations about permissions'
|
description: 'Operations about permissions'
|
||||||
-
|
- name: Session
|
||||||
name: Session
|
|
||||||
description: 'Get Session information'
|
description: 'Get Session information'
|
||||||
-
|
- name: STP
|
||||||
name: STP
|
|
||||||
description: 'Execution of Stored Programs'
|
description: 'Execution of Stored Programs'
|
||||||
-
|
- name: User
|
||||||
name: User
|
|
||||||
description: 'Operations with users'
|
description: 'Operations with users'
|
||||||
-
|
- name: Web
|
||||||
name: Web
|
|
||||||
description: 'Operations on Web'
|
description: 'Operations on Web'
|
||||||
|
|||||||
21
api/src/app-modules/configureCors.ts
Normal file
21
api/src/app-modules/configureCors.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { Express } from 'express'
|
||||||
|
import cors from 'cors'
|
||||||
|
import { CorsType } from '../utils'
|
||||||
|
|
||||||
|
export const configureCors = (app: Express) => {
|
||||||
|
const { CORS, WHITELIST } = process.env
|
||||||
|
|
||||||
|
if (CORS === CorsType.ENABLED) {
|
||||||
|
const whiteList: string[] = []
|
||||||
|
WHITELIST?.split(' ')
|
||||||
|
?.filter((url) => !!url)
|
||||||
|
.forEach((url) => {
|
||||||
|
if (url.startsWith('http'))
|
||||||
|
// removing trailing slash of URLs listing for CORS
|
||||||
|
whiteList.push(url.replace(/\/$/, ''))
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log('All CORS Requests are enabled for:', whiteList)
|
||||||
|
app.use(cors({ credentials: true, origin: whiteList }))
|
||||||
|
}
|
||||||
|
}
|
||||||
32
api/src/app-modules/configureExpressSession.ts
Normal file
32
api/src/app-modules/configureExpressSession.ts
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import { Express } from 'express'
|
||||||
|
import mongoose from 'mongoose'
|
||||||
|
import session from 'express-session'
|
||||||
|
import MongoStore from 'connect-mongo'
|
||||||
|
|
||||||
|
import { ModeType } from '../utils'
|
||||||
|
import { cookieOptions } from '../app'
|
||||||
|
|
||||||
|
export const configureExpressSession = (app: Express) => {
|
||||||
|
const { MODE } = process.env
|
||||||
|
|
||||||
|
if (MODE === ModeType.Server) {
|
||||||
|
let store: MongoStore | undefined
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV !== 'test') {
|
||||||
|
store = MongoStore.create({
|
||||||
|
client: mongoose.connection!.getClient() as any,
|
||||||
|
collectionName: 'sessions'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
app.use(
|
||||||
|
session({
|
||||||
|
secret: process.secrets.SESSION_SECRET,
|
||||||
|
saveUninitialized: false, // don't create session until something stored
|
||||||
|
resave: false, //don't save session if unmodified
|
||||||
|
store,
|
||||||
|
cookie: cookieOptions
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
33
api/src/app-modules/configureLogger.ts
Normal file
33
api/src/app-modules/configureLogger.ts
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import path from 'path'
|
||||||
|
import { Express } from 'express'
|
||||||
|
import morgan from 'morgan'
|
||||||
|
import { createStream } from 'rotating-file-stream'
|
||||||
|
import { generateTimestamp } from '@sasjs/utils'
|
||||||
|
import { getLogFolder } from '../utils'
|
||||||
|
|
||||||
|
export const configureLogger = (app: Express) => {
|
||||||
|
const { LOG_FORMAT_MORGAN } = process.env
|
||||||
|
|
||||||
|
let options
|
||||||
|
if (
|
||||||
|
process.env.NODE_ENV !== 'development' &&
|
||||||
|
process.env.NODE_ENV !== 'test'
|
||||||
|
) {
|
||||||
|
const timestamp = generateTimestamp()
|
||||||
|
const filename = `${timestamp}.log`
|
||||||
|
const logsFolder = getLogFolder()
|
||||||
|
|
||||||
|
// create a rotating write stream
|
||||||
|
var accessLogStream = createStream(filename, {
|
||||||
|
interval: '1d', // rotate daily
|
||||||
|
path: logsFolder
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log('Writing Logs to :', path.join(logsFolder, filename))
|
||||||
|
|
||||||
|
options = { stream: accessLogStream }
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup the logger
|
||||||
|
app.use(morgan(LOG_FORMAT_MORGAN as string, options))
|
||||||
|
}
|
||||||
26
api/src/app-modules/configureSecurity.ts
Normal file
26
api/src/app-modules/configureSecurity.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { Express } from 'express'
|
||||||
|
import { getEnvCSPDirectives } from '../utils/parseHelmetConfig'
|
||||||
|
import { HelmetCoepType, ProtocolType } from '../utils'
|
||||||
|
import helmet from 'helmet'
|
||||||
|
|
||||||
|
export const configureSecurity = (app: Express) => {
|
||||||
|
const { PROTOCOL, HELMET_CSP_CONFIG_PATH, HELMET_COEP } = process.env
|
||||||
|
|
||||||
|
const cspConfigJson: { [key: string]: string[] | null } = getEnvCSPDirectives(
|
||||||
|
HELMET_CSP_CONFIG_PATH
|
||||||
|
)
|
||||||
|
if (PROTOCOL === ProtocolType.HTTP)
|
||||||
|
cspConfigJson['upgrade-insecure-requests'] = null
|
||||||
|
|
||||||
|
app.use(
|
||||||
|
helmet({
|
||||||
|
contentSecurityPolicy: {
|
||||||
|
directives: {
|
||||||
|
...helmet.contentSecurityPolicy.getDefaultDirectives(),
|
||||||
|
...cspConfigJson
|
||||||
|
}
|
||||||
|
},
|
||||||
|
crossOriginEmbedderPolicy: HELMET_COEP === HelmetCoepType.TRUE
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
4
api/src/app-modules/index.ts
Normal file
4
api/src/app-modules/index.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export * from './configureCors'
|
||||||
|
export * from './configureExpressSession'
|
||||||
|
export * from './configureLogger'
|
||||||
|
export * from './configureSecurity'
|
||||||
127
api/src/app.ts
127
api/src/app.ts
@@ -1,30 +1,26 @@
|
|||||||
import path from 'path'
|
import path from 'path'
|
||||||
import express, { ErrorRequestHandler } from 'express'
|
import express, { ErrorRequestHandler } from 'express'
|
||||||
import mongoose from 'mongoose'
|
|
||||||
import csrf from 'csurf'
|
import csrf from 'csurf'
|
||||||
import session from 'express-session'
|
|
||||||
import MongoStore from 'connect-mongo'
|
|
||||||
import morgan from 'morgan'
|
|
||||||
import cookieParser from 'cookie-parser'
|
import cookieParser from 'cookie-parser'
|
||||||
import dotenv from 'dotenv'
|
import dotenv from 'dotenv'
|
||||||
import cors from 'cors'
|
|
||||||
import helmet from 'helmet'
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
copySASjsCore,
|
copySASjsCore,
|
||||||
CorsType,
|
|
||||||
getWebBuildFolder,
|
getWebBuildFolder,
|
||||||
HelmetCoepType,
|
|
||||||
instantiateLogger,
|
instantiateLogger,
|
||||||
loadAppStreamConfig,
|
loadAppStreamConfig,
|
||||||
ModeType,
|
|
||||||
ProtocolType,
|
ProtocolType,
|
||||||
ReturnCode,
|
ReturnCode,
|
||||||
setProcessVariables,
|
setProcessVariables,
|
||||||
setupFolders,
|
setupFolders,
|
||||||
verifyEnvVariables
|
verifyEnvVariables
|
||||||
} from './utils'
|
} from './utils'
|
||||||
import { getEnvCSPDirectives } from './utils/parseHelmetConfig'
|
import {
|
||||||
|
configureCors,
|
||||||
|
configureExpressSession,
|
||||||
|
configureLogger,
|
||||||
|
configureSecurity
|
||||||
|
} from './app-modules'
|
||||||
|
|
||||||
dotenv.config()
|
dotenv.config()
|
||||||
|
|
||||||
@@ -34,19 +30,7 @@ if (verifyEnvVariables()) process.exit(ReturnCode.InvalidEnv)
|
|||||||
|
|
||||||
const app = express()
|
const app = express()
|
||||||
|
|
||||||
app.use(cookieParser())
|
const { PROTOCOL } = process.env
|
||||||
|
|
||||||
const {
|
|
||||||
MODE,
|
|
||||||
CORS,
|
|
||||||
WHITELIST,
|
|
||||||
PROTOCOL,
|
|
||||||
HELMET_CSP_CONFIG_PATH,
|
|
||||||
HELMET_COEP,
|
|
||||||
LOG_FORMAT_MORGAN
|
|
||||||
} = process.env
|
|
||||||
|
|
||||||
app.use(morgan(LOG_FORMAT_MORGAN as string))
|
|
||||||
|
|
||||||
export const cookieOptions = {
|
export const cookieOptions = {
|
||||||
secure: PROTOCOL === ProtocolType.HTTPS,
|
secure: PROTOCOL === ProtocolType.HTTPS,
|
||||||
@@ -54,86 +38,43 @@ export const cookieOptions = {
|
|||||||
maxAge: 24 * 60 * 60 * 1000 // 24 hours
|
maxAge: 24 * 60 * 60 * 1000 // 24 hours
|
||||||
}
|
}
|
||||||
|
|
||||||
const cspConfigJson: { [key: string]: string[] | null } = getEnvCSPDirectives(
|
|
||||||
HELMET_CSP_CONFIG_PATH
|
|
||||||
)
|
|
||||||
if (PROTOCOL === ProtocolType.HTTP)
|
|
||||||
cspConfigJson['upgrade-insecure-requests'] = null
|
|
||||||
|
|
||||||
/***********************************
|
/***********************************
|
||||||
* CSRF Protection *
|
* CSRF Protection *
|
||||||
***********************************/
|
***********************************/
|
||||||
export const csrfProtection = csrf({ cookie: cookieOptions })
|
export const csrfProtection = csrf({ cookie: cookieOptions })
|
||||||
|
|
||||||
/***********************************
|
const onError: ErrorRequestHandler = (err, req, res, next) => {
|
||||||
* Handle security and origin *
|
|
||||||
***********************************/
|
|
||||||
app.use(
|
|
||||||
helmet({
|
|
||||||
contentSecurityPolicy: {
|
|
||||||
directives: {
|
|
||||||
...helmet.contentSecurityPolicy.getDefaultDirectives(),
|
|
||||||
...cspConfigJson
|
|
||||||
}
|
|
||||||
},
|
|
||||||
crossOriginEmbedderPolicy: HELMET_COEP === HelmetCoepType.TRUE
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
/***********************************
|
|
||||||
* Enabling CORS *
|
|
||||||
***********************************/
|
|
||||||
if (CORS === CorsType.ENABLED) {
|
|
||||||
const whiteList: string[] = []
|
|
||||||
WHITELIST?.split(' ')
|
|
||||||
?.filter((url) => !!url)
|
|
||||||
.forEach((url) => {
|
|
||||||
if (url.startsWith('http'))
|
|
||||||
// removing trailing slash of URLs listing for CORS
|
|
||||||
whiteList.push(url.replace(/\/$/, ''))
|
|
||||||
})
|
|
||||||
|
|
||||||
console.log('All CORS Requests are enabled for:', whiteList)
|
|
||||||
app.use(cors({ credentials: true, origin: whiteList }))
|
|
||||||
}
|
|
||||||
|
|
||||||
export default setProcessVariables().then(async () => {
|
|
||||||
/***********************************
|
|
||||||
* DB Connection & *
|
|
||||||
* Express Sessions *
|
|
||||||
* With Mongo Store *
|
|
||||||
***********************************/
|
|
||||||
if (MODE === ModeType.Server) {
|
|
||||||
let store: MongoStore | undefined
|
|
||||||
|
|
||||||
if (process.env.NODE_ENV !== 'test') {
|
|
||||||
store = MongoStore.create({
|
|
||||||
client: mongoose.connection!.getClient() as any,
|
|
||||||
collectionName: 'sessions'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
app.use(
|
|
||||||
session({
|
|
||||||
secret: process.secrets.SESSION_SECRET,
|
|
||||||
saveUninitialized: false, // don't create session until something stored
|
|
||||||
resave: false, //don't save session if unmodified
|
|
||||||
store,
|
|
||||||
cookie: cookieOptions
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
app.use(express.json({ limit: '100mb' }))
|
|
||||||
app.use(express.static(path.join(__dirname, '../public')))
|
|
||||||
|
|
||||||
const onError: ErrorRequestHandler = (err, req, res, next) => {
|
|
||||||
if (err.code === 'EBADCSRFTOKEN')
|
if (err.code === 'EBADCSRFTOKEN')
|
||||||
return res.status(400).send('Invalid CSRF token!')
|
return res.status(400).send('Invalid CSRF token!')
|
||||||
|
|
||||||
console.error(err.stack)
|
console.error(err.stack)
|
||||||
res.status(500).send('Something broke!')
|
res.status(500).send('Something broke!')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default setProcessVariables().then(async () => {
|
||||||
|
app.use(cookieParser())
|
||||||
|
|
||||||
|
configureLogger(app)
|
||||||
|
|
||||||
|
/***********************************
|
||||||
|
* Handle security and origin *
|
||||||
|
***********************************/
|
||||||
|
configureSecurity(app)
|
||||||
|
|
||||||
|
/***********************************
|
||||||
|
* Enabling CORS *
|
||||||
|
***********************************/
|
||||||
|
configureCors(app)
|
||||||
|
|
||||||
|
/***********************************
|
||||||
|
* DB Connection & *
|
||||||
|
* Express Sessions *
|
||||||
|
* With Mongo Store *
|
||||||
|
***********************************/
|
||||||
|
configureExpressSession(app)
|
||||||
|
|
||||||
|
app.use(express.json({ limit: '100mb' }))
|
||||||
|
app.use(express.static(path.join(__dirname, '../public')))
|
||||||
|
|
||||||
await setupFolders()
|
await setupFolders()
|
||||||
await copySASjsCore()
|
await copySASjsCore()
|
||||||
|
|||||||
@@ -101,8 +101,8 @@ ${autoExecContent}`
|
|||||||
session.path,
|
session.path,
|
||||||
'-AUTOEXEC',
|
'-AUTOEXEC',
|
||||||
autoExecPath,
|
autoExecPath,
|
||||||
isWindows() ? '-nosplash' : '',
|
process.sasLoc!.endsWith('sas.exe') ? '-nosplash' : '',
|
||||||
isWindows() ? '-icon' : '',
|
process.sasLoc!.endsWith('sas.exe') ? '-icon' : '',
|
||||||
isWindows() ? '-nologo' : ''
|
isWindows() ? '-nologo' : ''
|
||||||
])
|
])
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
|||||||
@@ -23,7 +23,9 @@ let _webout = '';
|
|||||||
const weboutPath = '${
|
const weboutPath = '${
|
||||||
isWindows() ? weboutPath.replace(/\\/g, '\\\\') : weboutPath
|
isWindows() ? weboutPath.replace(/\\/g, '\\\\') : weboutPath
|
||||||
}';
|
}';
|
||||||
const _sasjs_tokenfile = '${tokenFile}';
|
const _sasjs_tokenfile = '${
|
||||||
|
isWindows() ? tokenFile.replace(/\\/g, '\\\\') : tokenFile
|
||||||
|
}';
|
||||||
const _sasjs_username = '${preProgramVariables?.username}';
|
const _sasjs_username = '${preProgramVariables?.username}';
|
||||||
const _sasjs_userid = '${preProgramVariables?.userId}';
|
const _sasjs_userid = '${preProgramVariables?.userId}';
|
||||||
const _sasjs_displayname = '${preProgramVariables?.displayName}';
|
const _sasjs_displayname = '${preProgramVariables?.displayName}';
|
||||||
|
|||||||
1
api/src/types/system/process.d.ts
vendored
1
api/src/types/system/process.d.ts
vendored
@@ -3,6 +3,7 @@ declare namespace NodeJS {
|
|||||||
sasLoc?: string
|
sasLoc?: string
|
||||||
nodeLoc?: string
|
nodeLoc?: string
|
||||||
driveLoc: string
|
driveLoc: string
|
||||||
|
logsLoc: string
|
||||||
sasSessionController?: import('../../controllers/internal').SASSessionController
|
sasSessionController?: import('../../controllers/internal').SASSessionController
|
||||||
jsSessionController?: import('../../controllers/internal').JSSessionController
|
jsSessionController?: import('../../controllers/internal').JSSessionController
|
||||||
appStreamConfig: import('../').AppStreamConfig
|
appStreamConfig: import('../').AppStreamConfig
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ export const getDesktopUserAutoExecPath = () =>
|
|||||||
|
|
||||||
export const getSasjsRootFolder = () => process.driveLoc
|
export const getSasjsRootFolder = () => process.driveLoc
|
||||||
|
|
||||||
|
export const getLogFolder = () => process.logsLoc
|
||||||
|
|
||||||
export const getAppStreamConfigPath = () =>
|
export const getAppStreamConfigPath = () =>
|
||||||
path.join(getSasjsRootFolder(), 'appStreamConfig.json')
|
path.join(getSasjsRootFolder(), 'appStreamConfig.json')
|
||||||
|
|
||||||
@@ -32,8 +34,6 @@ export const getUploadsFolder = () => path.join(getSasjsRootFolder(), 'uploads')
|
|||||||
|
|
||||||
export const getFilesFolder = () => path.join(getSasjsRootFolder(), 'files')
|
export const getFilesFolder = () => path.join(getSasjsRootFolder(), 'files')
|
||||||
|
|
||||||
export const getLogFolder = () => path.join(getSasjsRootFolder(), 'logs')
|
|
||||||
|
|
||||||
export const getWeboutFolder = () => path.join(getSasjsRootFolder(), 'webouts')
|
export const getWeboutFolder = () => path.join(getSasjsRootFolder(), 'webouts')
|
||||||
|
|
||||||
export const getSessionsFolder = () =>
|
export const getSessionsFolder = () =>
|
||||||
|
|||||||
@@ -40,7 +40,16 @@ export const setProcessVariables = async () => {
|
|||||||
await createFolder(absPath)
|
await createFolder(absPath)
|
||||||
process.driveLoc = getRealPath(absPath)
|
process.driveLoc = getRealPath(absPath)
|
||||||
|
|
||||||
|
const { LOG_LOCATION } = process.env
|
||||||
|
const absLogsPath = getAbsolutePath(
|
||||||
|
LOG_LOCATION ?? `sasjs_root${path.sep}logs`,
|
||||||
|
process.cwd()
|
||||||
|
)
|
||||||
|
await createFolder(absLogsPath)
|
||||||
|
process.logsLoc = getRealPath(absLogsPath)
|
||||||
|
|
||||||
console.log('sasLoc: ', process.sasLoc)
|
console.log('sasLoc: ', process.sasLoc)
|
||||||
console.log('sasDrive: ', process.driveLoc)
|
console.log('sasDrive: ', process.driveLoc)
|
||||||
|
console.log('sasLogs: ', process.logsLoc)
|
||||||
console.log('runTimes: ', process.runTimes)
|
console.log('runTimes: ', process.runTimes)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { MulterFile } from '../types/Upload'
|
import { MulterFile } from '../types/Upload'
|
||||||
import { listFilesInFolder, readFileBinary } from '@sasjs/utils'
|
import { listFilesInFolder, readFileBinary, isWindows } from '@sasjs/utils'
|
||||||
|
|
||||||
interface FilenameMapSingle {
|
interface FilenameMapSingle {
|
||||||
fieldName: string
|
fieldName: string
|
||||||
@@ -118,7 +118,9 @@ export const generateFileUploadJSCode = async (
|
|||||||
if (fileName.includes('req_file')) {
|
if (fileName.includes('req_file')) {
|
||||||
fileCount++
|
fileCount++
|
||||||
const filePath = path.join(sessionFolder, fileName)
|
const filePath = path.join(sessionFolder, fileName)
|
||||||
uploadCode += `\nconst _WEBIN_FILEREF${fileCount} = fs.readFileSync('${filePath}')`
|
uploadCode += `\nconst _WEBIN_FILEREF${fileCount} = fs.readFileSync('${
|
||||||
|
isWindows() ? filePath.replace(/\\/g, '\\\\') : filePath
|
||||||
|
}')`
|
||||||
uploadCode += `\nconst _WEBIN_FILENAME${fileCount} = '${filesNamesMap[fileName].originalName}'`
|
uploadCode += `\nconst _WEBIN_FILENAME${fileCount} = '${filesNamesMap[fileName].originalName}'`
|
||||||
uploadCode += `\nconst _WEBIN_NAME${fileCount} = '${filesNamesMap[fileName].fieldName}'`
|
uploadCode += `\nconst _WEBIN_NAME${fileCount} = '${filesNamesMap[fileName].fieldName}'`
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user