mirror of
https://github.com/sasjs/server.git
synced 2025-12-10 19:34:34 +00:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e251747302 | ||
|
|
7e7558d4cf | ||
|
|
f02996facf | ||
|
|
803c51f400 | ||
|
|
c35b2b3f59 | ||
|
|
fe0866ace7 | ||
|
|
1513c3623d | ||
|
|
7fe43ae0b7 | ||
|
|
c4cea4a12b | ||
|
|
9fc7a132ba | ||
|
|
d55a619d64 | ||
|
|
737d2a24c2 | ||
|
|
2e63831b90 |
22
CHANGELOG.md
22
CHANGELOG.md
@@ -2,6 +2,28 @@
|
|||||||
|
|
||||||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
||||||
|
|
||||||
|
### [0.0.56](https://github.com/sasjs/server/compare/v0.0.55...v0.0.56) (2022-04-20)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* shortening min length of username. Closes [#61](https://github.com/sasjs/server/issues/61) ([f02996f](https://github.com/sasjs/server/commit/f02996facf1019ec4022ccfbc99c1d0137074e1b))
|
||||||
|
|
||||||
|
### [0.0.55](https://github.com/sasjs/server/compare/v0.0.53...v0.0.55) (2022-04-20)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* added db seed at server startup ([2e63831](https://github.com/sasjs/server/commit/2e63831b90c7457e0e322719ebb1193fd6181cc3))
|
||||||
|
* drive path in server mode ([c4cea4a](https://github.com/sasjs/server/commit/c4cea4a12b7eda4daeed995f41c0b10bcea79871))
|
||||||
|
|
||||||
|
### [0.0.54](https://github.com/sasjs/server/compare/v0.0.53...v0.0.54) (2022-04-19)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* added db seed at server startup ([2e63831](https://github.com/sasjs/server/commit/2e63831b90c7457e0e322719ebb1193fd6181cc3))
|
||||||
|
|
||||||
### [0.0.53](https://github.com/sasjs/server/compare/v0.0.49...v0.0.53) (2022-04-19)
|
### [0.0.53](https://github.com/sasjs/server/compare/v0.0.49...v0.0.53) (2022-04-19)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -22,11 +22,13 @@ const { MODE, CORS, WHITELIST } = process.env
|
|||||||
|
|
||||||
if (MODE?.trim() !== 'server' || CORS?.trim() === 'enable') {
|
if (MODE?.trim() !== 'server' || CORS?.trim() === 'enable') {
|
||||||
const whiteList: string[] = []
|
const whiteList: string[] = []
|
||||||
WHITELIST?.split(' ')?.forEach((url) => {
|
WHITELIST?.split(' ')
|
||||||
if (url.startsWith('http'))
|
?.filter((url) => !!url)
|
||||||
// removing trailing slash of URLs listing for CORS
|
.forEach((url) => {
|
||||||
whiteList.push(url.replace(/\/$/, ''))
|
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)
|
console.log('All CORS Requests are enabled for:', whiteList)
|
||||||
app.use(cors({ credentials: true, origin: whiteList }))
|
app.use(cors({ credentials: true, origin: whiteList }))
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import express from 'express'
|
import { Route, Tags, Example, Get } from 'tsoa'
|
||||||
import { Request, Security, Route, Tags, Example, Get } from 'tsoa'
|
|
||||||
|
|
||||||
export interface InfoResponse {
|
export interface InfoResponse {
|
||||||
mode: string
|
mode: string
|
||||||
@@ -29,7 +28,8 @@ export class InfoController {
|
|||||||
process.env.CORS ?? process.env.MODE === 'server'
|
process.env.CORS ?? process.env.MODE === 'server'
|
||||||
? 'disable'
|
? 'disable'
|
||||||
: 'enable',
|
: 'enable',
|
||||||
whiteList: process.env.WHITELIST?.split(' ') ?? [],
|
whiteList:
|
||||||
|
process.env.WHITELIST?.split(' ')?.filter((url) => !!url) ?? [],
|
||||||
protocol: process.env.PROTOCOL ?? 'http'
|
protocol: process.env.PROTOCOL ?? 'http'
|
||||||
}
|
}
|
||||||
return response
|
return response
|
||||||
|
|||||||
@@ -18,11 +18,6 @@ import {
|
|||||||
verifyTokenInDB
|
verifyTokenInDB
|
||||||
} from '../../../utils'
|
} from '../../../utils'
|
||||||
|
|
||||||
let app: Express
|
|
||||||
appPromise.then((_app) => {
|
|
||||||
app = _app
|
|
||||||
})
|
|
||||||
|
|
||||||
const clientId = 'someclientID'
|
const clientId = 'someclientID'
|
||||||
const clientSecret = 'someclientSecret'
|
const clientSecret = 'someclientSecret'
|
||||||
const user = {
|
const user = {
|
||||||
@@ -35,12 +30,15 @@ const user = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe('auth', () => {
|
describe('auth', () => {
|
||||||
|
let app: Express
|
||||||
let con: Mongoose
|
let con: Mongoose
|
||||||
let mongoServer: MongoMemoryServer
|
let mongoServer: MongoMemoryServer
|
||||||
const userController = new UserController()
|
const userController = new UserController()
|
||||||
const clientController = new ClientController()
|
const clientController = new ClientController()
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
|
app = await appPromise
|
||||||
|
|
||||||
mongoServer = await MongoMemoryServer.create()
|
mongoServer = await MongoMemoryServer.create()
|
||||||
con = await mongoose.connect(mongoServer.getUri())
|
con = await mongoose.connect(mongoServer.getUri())
|
||||||
await clientController.createClient({ clientId, clientSecret })
|
await clientController.createClient({ clientId, clientSecret })
|
||||||
|
|||||||
@@ -6,11 +6,6 @@ import appPromise from '../../../app'
|
|||||||
import { UserController, ClientController } from '../../../controllers/'
|
import { UserController, ClientController } from '../../../controllers/'
|
||||||
import { generateAccessToken, saveTokensInDB } from '../../../utils'
|
import { generateAccessToken, saveTokensInDB } from '../../../utils'
|
||||||
|
|
||||||
let app: Express
|
|
||||||
appPromise.then((_app) => {
|
|
||||||
app = _app
|
|
||||||
})
|
|
||||||
|
|
||||||
const client = {
|
const client = {
|
||||||
clientId: 'someclientID',
|
clientId: 'someclientID',
|
||||||
clientSecret: 'someclientSecret'
|
clientSecret: 'someclientSecret'
|
||||||
@@ -28,12 +23,15 @@ const newClient = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe('client', () => {
|
describe('client', () => {
|
||||||
|
let app: Express
|
||||||
let con: Mongoose
|
let con: Mongoose
|
||||||
let mongoServer: MongoMemoryServer
|
let mongoServer: MongoMemoryServer
|
||||||
const userController = new UserController()
|
const userController = new UserController()
|
||||||
const clientController = new ClientController()
|
const clientController = new ClientController()
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
|
app = await appPromise
|
||||||
|
|
||||||
mongoServer = await MongoMemoryServer.create()
|
mongoServer = await MongoMemoryServer.create()
|
||||||
con = await mongoose.connect(mongoServer.getUri())
|
con = await mongoose.connect(mongoServer.getUri())
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -33,11 +33,6 @@ import { getTreeExample } from '../../../controllers/internal'
|
|||||||
import { generateAccessToken, saveTokensInDB } from '../../../utils/'
|
import { generateAccessToken, saveTokensInDB } from '../../../utils/'
|
||||||
const { getTmpFilesFolderPath } = fileUtilModules
|
const { getTmpFilesFolderPath } = fileUtilModules
|
||||||
|
|
||||||
let app: Express
|
|
||||||
appPromise.then((_app) => {
|
|
||||||
app = _app
|
|
||||||
})
|
|
||||||
|
|
||||||
const clientId = 'someclientID'
|
const clientId = 'someclientID'
|
||||||
const user = {
|
const user = {
|
||||||
displayName: 'Test User',
|
displayName: 'Test User',
|
||||||
@@ -48,6 +43,7 @@ const user = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe('drive', () => {
|
describe('drive', () => {
|
||||||
|
let app: Express
|
||||||
let con: Mongoose
|
let con: Mongoose
|
||||||
let mongoServer: MongoMemoryServer
|
let mongoServer: MongoMemoryServer
|
||||||
const controller = new UserController()
|
const controller = new UserController()
|
||||||
@@ -55,6 +51,8 @@ describe('drive', () => {
|
|||||||
let accessToken: string
|
let accessToken: string
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
|
app = await appPromise
|
||||||
|
|
||||||
mongoServer = await MongoMemoryServer.create()
|
mongoServer = await MongoMemoryServer.create()
|
||||||
con = await mongoose.connect(mongoServer.getUri())
|
con = await mongoose.connect(mongoServer.getUri())
|
||||||
|
|
||||||
|
|||||||
@@ -6,11 +6,6 @@ import appPromise from '../../../app'
|
|||||||
import { UserController, GroupController } from '../../../controllers/'
|
import { UserController, GroupController } from '../../../controllers/'
|
||||||
import { generateAccessToken, saveTokensInDB } from '../../../utils'
|
import { generateAccessToken, saveTokensInDB } from '../../../utils'
|
||||||
|
|
||||||
let app: Express
|
|
||||||
appPromise.then((_app) => {
|
|
||||||
app = _app
|
|
||||||
})
|
|
||||||
|
|
||||||
const clientId = 'someclientID'
|
const clientId = 'someclientID'
|
||||||
const adminUser = {
|
const adminUser = {
|
||||||
displayName: 'Test Admin',
|
displayName: 'Test Admin',
|
||||||
@@ -36,11 +31,14 @@ const userController = new UserController()
|
|||||||
const groupController = new GroupController()
|
const groupController = new GroupController()
|
||||||
|
|
||||||
describe('group', () => {
|
describe('group', () => {
|
||||||
|
let app: Express
|
||||||
let con: Mongoose
|
let con: Mongoose
|
||||||
let mongoServer: MongoMemoryServer
|
let mongoServer: MongoMemoryServer
|
||||||
let adminAccessToken: string
|
let adminAccessToken: string
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
|
app = await appPromise
|
||||||
|
|
||||||
mongoServer = await MongoMemoryServer.create()
|
mongoServer = await MongoMemoryServer.create()
|
||||||
con = await mongoose.connect(mongoServer.getUri())
|
con = await mongoose.connect(mongoServer.getUri())
|
||||||
|
|
||||||
|
|||||||
@@ -2,13 +2,19 @@ import { Express } from 'express'
|
|||||||
import request from 'supertest'
|
import request from 'supertest'
|
||||||
import appPromise from '../../../app'
|
import appPromise from '../../../app'
|
||||||
|
|
||||||
let app: Express
|
|
||||||
|
|
||||||
describe('Info', () => {
|
describe('Info', () => {
|
||||||
|
let app: Express
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
app = await appPromise
|
||||||
|
})
|
||||||
|
|
||||||
it('should should return configured information of the server instance', async () => {
|
it('should should return configured information of the server instance', async () => {
|
||||||
await appPromise.then((_app) => {
|
const res = await request(app).get('/SASjsApi/info').expect(200)
|
||||||
app = _app
|
|
||||||
})
|
expect(res.body.mode).toEqual('server')
|
||||||
request(app).get('/SASjsApi/info').expect(200)
|
expect(res.body.cors).toEqual('disable')
|
||||||
|
expect(res.body.whiteList).toEqual([])
|
||||||
|
expect(res.body.protocol).toEqual('http')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -6,11 +6,6 @@ import appPromise from '../../../app'
|
|||||||
import { UserController } from '../../../controllers/'
|
import { UserController } from '../../../controllers/'
|
||||||
import { generateAccessToken, saveTokensInDB } from '../../../utils'
|
import { generateAccessToken, saveTokensInDB } from '../../../utils'
|
||||||
|
|
||||||
let app: Express
|
|
||||||
appPromise.then((_app) => {
|
|
||||||
app = _app
|
|
||||||
})
|
|
||||||
|
|
||||||
const clientId = 'someclientID'
|
const clientId = 'someclientID'
|
||||||
const adminUser = {
|
const adminUser = {
|
||||||
displayName: 'Test Admin',
|
displayName: 'Test Admin',
|
||||||
@@ -30,10 +25,13 @@ const user = {
|
|||||||
const controller = new UserController()
|
const controller = new UserController()
|
||||||
|
|
||||||
describe('user', () => {
|
describe('user', () => {
|
||||||
|
let app: Express
|
||||||
let con: Mongoose
|
let con: Mongoose
|
||||||
let mongoServer: MongoMemoryServer
|
let mongoServer: MongoMemoryServer
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
|
app = await appPromise
|
||||||
|
|
||||||
mongoServer = await MongoMemoryServer.create()
|
mongoServer = await MongoMemoryServer.create()
|
||||||
con = await mongoose.connect(mongoServer.getUri())
|
con = await mongoose.connect(mongoServer.getUri())
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,25 +1,28 @@
|
|||||||
import mongoose from 'mongoose'
|
import mongoose from 'mongoose'
|
||||||
import { populateClients } from '../routes/api/auth'
|
import { populateClients } from '../routes/api/auth'
|
||||||
|
import { seedDB } from './seedDB'
|
||||||
|
|
||||||
export const connectDB = async () => {
|
export const connectDB = async () => {
|
||||||
// NOTE: when exporting app.js as agent for supertest
|
// NOTE: when exporting app.js as agent for supertest
|
||||||
// we should exclude connecting to the real database
|
// we should exclude connecting to the real database
|
||||||
if (process.env.NODE_ENV === 'test') {
|
if (process.env.NODE_ENV === 'test') {
|
||||||
return
|
return
|
||||||
} else {
|
|
||||||
const { MODE } = process.env
|
|
||||||
|
|
||||||
if (MODE?.trim() !== 'server') {
|
|
||||||
console.log('Running in Destop Mode, no DB to connect.')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
mongoose.connect(process.env.DB_CONNECT as string, async (err) => {
|
|
||||||
if (err) throw err
|
|
||||||
|
|
||||||
console.log('Connected to db!')
|
|
||||||
|
|
||||||
await populateClients()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { MODE } = process.env
|
||||||
|
|
||||||
|
if (MODE?.trim() !== 'server') {
|
||||||
|
console.log('Running in Destop Mode, no DB to connect.')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
mongoose.connect(process.env.DB_CONNECT as string, async (err) => {
|
||||||
|
if (err) throw err
|
||||||
|
|
||||||
|
console.log('Connected to db!')
|
||||||
|
|
||||||
|
await seedDB()
|
||||||
|
|
||||||
|
await populateClients()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export const sysInitCompiledPath = path.join(
|
|||||||
)
|
)
|
||||||
|
|
||||||
export const sasJSCoreMacros = path.join(apiRoot, 'sasjscore')
|
export const sasJSCoreMacros = path.join(apiRoot, 'sasjscore')
|
||||||
export const sasJSCoreMacrosInfo = path.join(apiRoot, 'sasjscore', '.macrolist')
|
export const sasJSCoreMacrosInfo = path.join(sasJSCoreMacros, '.macrolist')
|
||||||
|
|
||||||
export const getWebBuildFolderPath = () =>
|
export const getWebBuildFolderPath = () =>
|
||||||
path.join(codebaseRoot, 'web', 'build')
|
path.join(codebaseRoot, 'web', 'build')
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export * from './isDebugOn'
|
|||||||
export * from './parseLogToArray'
|
export * from './parseLogToArray'
|
||||||
export * from './removeTokensInDB'
|
export * from './removeTokensInDB'
|
||||||
export * from './saveTokensInDB'
|
export * from './saveTokensInDB'
|
||||||
|
export * from './seedDB'
|
||||||
export * from './setProcessVariables'
|
export * from './setProcessVariables'
|
||||||
export * from './setupFolders'
|
export * from './setupFolders'
|
||||||
export * from './upload'
|
export * from './upload'
|
||||||
|
|||||||
35
api/src/utils/seedDB.ts
Normal file
35
api/src/utils/seedDB.ts
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import Client from '../model/Client'
|
||||||
|
import User from '../model/User'
|
||||||
|
|
||||||
|
const CLIENT = {
|
||||||
|
clientId: 'clientID1',
|
||||||
|
clientSecret: 'clientSecret'
|
||||||
|
}
|
||||||
|
const ADMIN_USER = {
|
||||||
|
id: 1,
|
||||||
|
displayName: 'Super Admin',
|
||||||
|
username: 'secretuser',
|
||||||
|
password: '$2a$10$hKvcVEZdhEQZCcxt6npazO6mY4jJkrzWvfQ5stdBZi8VTTwVMCVXO',
|
||||||
|
isAdmin: true,
|
||||||
|
isActive: true
|
||||||
|
}
|
||||||
|
|
||||||
|
export const seedDB = async () => {
|
||||||
|
// Checking if client is already in the database
|
||||||
|
const clientExist = await Client.findOne({ clientId: CLIENT.clientId })
|
||||||
|
if (!clientExist) {
|
||||||
|
const client = new Client(CLIENT)
|
||||||
|
await client.save()
|
||||||
|
|
||||||
|
console.log(`DB Seed - client created: ${CLIENT.clientId}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checking if user is already in the database
|
||||||
|
const usernameExist = await User.findOne({ username: ADMIN_USER.username })
|
||||||
|
if (!usernameExist) {
|
||||||
|
const user = new User(ADMIN_USER)
|
||||||
|
await user.save()
|
||||||
|
|
||||||
|
console.log(`DB Seed - admin account created: ${ADMIN_USER.username}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { getRealPath } from '@sasjs/utils'
|
import { getAbsolutePath, getRealPath } from '@sasjs/utils'
|
||||||
|
|
||||||
import { configuration } from '../../package.json'
|
import { configuration } from '../../package.json'
|
||||||
import { getDesktopFields } from '.'
|
import { getDesktopFields } from '.'
|
||||||
@@ -12,18 +12,17 @@ export const setProcessVariables = async () => {
|
|||||||
|
|
||||||
const { MODE } = process.env
|
const { MODE } = process.env
|
||||||
|
|
||||||
if (MODE?.trim() !== 'server') {
|
if (MODE?.trim() === 'server') {
|
||||||
|
const { SAS_PATH, DRIVE_PATH } = process.env
|
||||||
|
|
||||||
|
process.sasLoc = SAS_PATH ?? configuration.sasPath
|
||||||
|
const absPath = getAbsolutePath(DRIVE_PATH ?? 'tmp', process.cwd())
|
||||||
|
process.driveLoc = getRealPath(absPath)
|
||||||
|
} else {
|
||||||
const { sasLoc, driveLoc } = await getDesktopFields()
|
const { sasLoc, driveLoc } = await getDesktopFields()
|
||||||
|
|
||||||
process.sasLoc = sasLoc
|
process.sasLoc = sasLoc
|
||||||
process.driveLoc = driveLoc
|
process.driveLoc = driveLoc
|
||||||
} else {
|
|
||||||
const { SAS_PATH, DRIVE_PATH } = process.env
|
|
||||||
|
|
||||||
process.sasLoc = SAS_PATH ?? configuration.sasPath
|
|
||||||
process.driveLoc = getRealPath(
|
|
||||||
path.join(process.cwd(), DRIVE_PATH ?? 'tmp')
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('sasLoc: ', process.sasLoc)
|
console.log('sasLoc: ', process.sasLoc)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Joi from 'joi'
|
import Joi from 'joi'
|
||||||
|
|
||||||
const usernameSchema = Joi.string().alphanum().min(6).max(20)
|
const usernameSchema = Joi.string().alphanum().min(3).max(16)
|
||||||
const passwordSchema = Joi.string().min(6).max(1024)
|
const passwordSchema = Joi.string().min(6).max(1024)
|
||||||
|
|
||||||
export const blockFileRegex = /\.(exe|sh|htaccess)$/i
|
export const blockFileRegex = /\.(exe|sh|htaccess)$/i
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "server",
|
"name": "server",
|
||||||
"version": "0.0.53",
|
"version": "0.0.56",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "server",
|
"name": "server",
|
||||||
"version": "0.0.53",
|
"version": "0.0.56",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"prettier": "^2.3.1",
|
"prettier": "^2.3.1",
|
||||||
"standard-version": "^9.3.2"
|
"standard-version": "^9.3.2"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "server",
|
"name": "server",
|
||||||
"version": "0.0.53",
|
"version": "0.0.56",
|
||||||
"description": "NodeJS wrapper for calling the SAS binary executable",
|
"description": "NodeJS wrapper for calling the SAS binary executable",
|
||||||
"repository": "https://github.com/sasjs/server",
|
"repository": "https://github.com/sasjs/server",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
Reference in New Issue
Block a user