mirror of
https://github.com/sasjs/server.git
synced 2025-12-10 19:34:34 +00:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
afff27fd21 | ||
|
|
a8ba378fd1 | ||
|
|
73c81a45dc | ||
|
|
12d424acce | ||
|
|
414fb19de3 | ||
|
|
cfddf1fb0c | ||
|
|
1f483b1afc | ||
|
|
0470239ef1 | ||
|
|
2c259fe1de | ||
|
|
b066734398 | ||
|
|
3b698fce5f | ||
|
|
5ad6ee5e0f | ||
|
|
7d11cc7916 |
29
CHANGELOG.md
29
CHANGELOG.md
@@ -1,3 +1,32 @@
|
|||||||
|
## [0.3.4](https://github.com/sasjs/server/compare/v0.3.3...v0.3.4) (2022-05-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **web:** system username for DESKTOP mode ([a8ba378](https://github.com/sasjs/server/commit/a8ba378fd1ff374ba025a96fdfae5c6c36954465))
|
||||||
|
|
||||||
|
## [0.3.3](https://github.com/sasjs/server/compare/v0.3.2...v0.3.3) (2022-05-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* usage of autoexec API in DESKTOP mode ([12d424a](https://github.com/sasjs/server/commit/12d424acce8108a6f53aefbac01fddcdc5efb48f))
|
||||||
|
|
||||||
|
## [0.3.2](https://github.com/sasjs/server/compare/v0.3.1...v0.3.2) (2022-05-27)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **web:** ability to use get/patch User API in desktop mode. ([2c259fe](https://github.com/sasjs/server/commit/2c259fe1de95d84e6929e311aaa6b895e66b42a3))
|
||||||
|
|
||||||
|
## [0.3.1](https://github.com/sasjs/server/compare/v0.3.0...v0.3.1) (2022-05-26)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **api:** username should be lowercase ([5ad6ee5](https://github.com/sasjs/server/commit/5ad6ee5e0f5d7d6faa45b72215f1d9d55cfc37db))
|
||||||
|
* **web:** reduced width for autoexec input ([7d11cc7](https://github.com/sasjs/server/commit/7d11cc79161e5a07f6c5392d742ef6b9d8658071))
|
||||||
|
|
||||||
# [0.3.0](https://github.com/sasjs/server/compare/v0.2.0...v0.3.0) (2022-05-25)
|
# [0.3.0](https://github.com/sasjs/server/compare/v0.2.0...v0.3.0) (2022-05-25)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -96,7 +96,7 @@
|
|||||||
},
|
},
|
||||||
"nodemonConfig": {
|
"nodemonConfig": {
|
||||||
"ignore": [
|
"ignore": [
|
||||||
"tmp/**/*"
|
"sasjs_root/**/*"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,12 +3,11 @@ import { Request, Security, Route, Tags, Post, Body } from 'tsoa'
|
|||||||
import { ExecuteReturnJson, ExecutionController } from './internal'
|
import { ExecuteReturnJson, ExecutionController } from './internal'
|
||||||
import { ExecuteReturnJsonResponse } from '.'
|
import { ExecuteReturnJsonResponse } from '.'
|
||||||
import {
|
import {
|
||||||
getDesktopUserAutoExecPath,
|
|
||||||
getPreProgramVariables,
|
getPreProgramVariables,
|
||||||
|
getUserAutoExec,
|
||||||
ModeType,
|
ModeType,
|
||||||
parseLogToArray
|
parseLogToArray
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
import { readFile } from '@sasjs/utils'
|
|
||||||
|
|
||||||
interface ExecuteSASCodePayload {
|
interface ExecuteSASCodePayload {
|
||||||
/**
|
/**
|
||||||
@@ -43,7 +42,7 @@ const executeSASCode = async (
|
|||||||
const userAutoExec =
|
const userAutoExec =
|
||||||
process.env.MODE === ModeType.Server
|
process.env.MODE === ModeType.Server
|
||||||
? user?.autoExec
|
? user?.autoExec
|
||||||
: await readFile(getDesktopUserAutoExecPath())
|
: await getUserAutoExec()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { webout, log, httpHeaders } =
|
const { webout, log, httpHeaders } =
|
||||||
|
|||||||
@@ -14,8 +14,10 @@ import {
|
|||||||
Hidden,
|
Hidden,
|
||||||
Request
|
Request
|
||||||
} from 'tsoa'
|
} from 'tsoa'
|
||||||
|
import { desktopUser } from '../middlewares'
|
||||||
|
|
||||||
import User, { UserPayload } from '../model/User'
|
import User, { UserPayload } from '../model/User'
|
||||||
|
import { getUserAutoExec, updateUserAutoExec, ModeType } from '../utils'
|
||||||
|
|
||||||
export interface UserResponse {
|
export interface UserResponse {
|
||||||
id: number
|
id: number
|
||||||
@@ -86,6 +88,10 @@ export class UserController {
|
|||||||
@Request() req: express.Request,
|
@Request() req: express.Request,
|
||||||
@Path() userId: number
|
@Path() userId: number
|
||||||
): Promise<UserDetailsResponse> {
|
): Promise<UserDetailsResponse> {
|
||||||
|
const { MODE } = process.env
|
||||||
|
|
||||||
|
if (MODE === ModeType.Desktop) return getDesktopAutoExec()
|
||||||
|
|
||||||
const { user } = req
|
const { user } = req
|
||||||
const getAutoExec = user!.isAdmin || user!.userId == userId
|
const getAutoExec = user!.isAdmin || user!.userId == userId
|
||||||
return getUser(userId, getAutoExec)
|
return getUser(userId, getAutoExec)
|
||||||
@@ -108,6 +114,11 @@ export class UserController {
|
|||||||
@Path() userId: number,
|
@Path() userId: number,
|
||||||
@Body() body: UserPayload
|
@Body() body: UserPayload
|
||||||
): Promise<UserDetailsResponse> {
|
): Promise<UserDetailsResponse> {
|
||||||
|
const { MODE } = process.env
|
||||||
|
|
||||||
|
if (MODE === ModeType.Desktop)
|
||||||
|
return updateDesktopAutoExec(body.autoExec ?? '')
|
||||||
|
|
||||||
return updateUser(userId, body)
|
return updateUser(userId, body)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,6 +192,14 @@ const getUser = async (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getDesktopAutoExec = async () => {
|
||||||
|
return {
|
||||||
|
...desktopUser,
|
||||||
|
id: desktopUser.userId,
|
||||||
|
autoExec: await getUserAutoExec()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const updateUser = async (
|
const updateUser = async (
|
||||||
id: number,
|
id: number,
|
||||||
data: Partial<UserPayload>
|
data: Partial<UserPayload>
|
||||||
@@ -216,6 +235,15 @@ const updateUser = async (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const updateDesktopAutoExec = async (autoExec: string) => {
|
||||||
|
await updateUserAutoExec(autoExec)
|
||||||
|
return {
|
||||||
|
...desktopUser,
|
||||||
|
id: desktopUser.userId,
|
||||||
|
autoExec
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const deleteUser = async (
|
const deleteUser = async (
|
||||||
id: number,
|
id: number,
|
||||||
isAdmin: boolean,
|
isAdmin: boolean,
|
||||||
|
|||||||
@@ -1,15 +1,22 @@
|
|||||||
import { RequestHandler, Request, Response, NextFunction } from 'express'
|
import { RequestHandler, Request, Response, NextFunction } from 'express'
|
||||||
import jwt from 'jsonwebtoken'
|
import jwt from 'jsonwebtoken'
|
||||||
import { csrfProtection } from '../app'
|
import { csrfProtection } from '../app'
|
||||||
import { fetchLatestAutoExec, verifyTokenInDB } from '../utils'
|
import { fetchLatestAutoExec, ModeType, verifyTokenInDB } from '../utils'
|
||||||
|
import { desktopUser } from './desktop'
|
||||||
|
|
||||||
export const authenticateAccessToken: RequestHandler = async (
|
export const authenticateAccessToken: RequestHandler = async (
|
||||||
req,
|
req,
|
||||||
res,
|
res,
|
||||||
next
|
next
|
||||||
) => {
|
) => {
|
||||||
|
const { MODE } = process.env
|
||||||
|
if (MODE === ModeType.Desktop) {
|
||||||
|
req.user = desktopUser
|
||||||
|
return next()
|
||||||
|
}
|
||||||
|
|
||||||
// if request is coming from web and has valid session
|
// if request is coming from web and has valid session
|
||||||
// we can validate the request and check for CSRF Token
|
// it can be validated.
|
||||||
if (req.session?.loggedIn) {
|
if (req.session?.loggedIn) {
|
||||||
if (req.session.user) {
|
if (req.session.user) {
|
||||||
const user = await fetchLatestAutoExec(req.session.user)
|
const user = await fetchLatestAutoExec(req.session.user)
|
||||||
|
|||||||
@@ -1,20 +1,37 @@
|
|||||||
import { RequestHandler } from 'express'
|
import { RequestHandler, Request } from 'express'
|
||||||
|
import { userInfo } from 'os'
|
||||||
|
import { RequestUser } from '../types'
|
||||||
|
import { ModeType } from '../utils'
|
||||||
|
|
||||||
|
const regexUser = /^\/SASjsApi\/user\/[0-9]*$/ // /SASjsApi/user/1
|
||||||
|
|
||||||
|
const allowedInDesktopMode: { [key: string]: RegExp[] } = {
|
||||||
|
GET: [regexUser],
|
||||||
|
PATCH: [regexUser]
|
||||||
|
}
|
||||||
|
|
||||||
|
const reqAllowedInDesktopMode = (request: Request): boolean => {
|
||||||
|
const { method, originalUrl: url } = request
|
||||||
|
|
||||||
|
return !!allowedInDesktopMode[method]?.find((urlRegex) => urlRegex.test(url))
|
||||||
|
}
|
||||||
|
|
||||||
export const desktopRestrict: RequestHandler = (req, res, next) => {
|
export const desktopRestrict: RequestHandler = (req, res, next) => {
|
||||||
const { MODE } = process.env
|
const { MODE } = process.env
|
||||||
if (MODE?.trim() !== 'server')
|
|
||||||
return res.status(403).send('Not Allowed while in Desktop Mode.')
|
if (MODE === ModeType.Desktop) {
|
||||||
|
if (!reqAllowedInDesktopMode(req))
|
||||||
|
return res.status(403).send('Not Allowed while in Desktop Mode.')
|
||||||
|
}
|
||||||
|
|
||||||
next()
|
next()
|
||||||
}
|
}
|
||||||
export const desktopUsername: RequestHandler = (req, res, next) => {
|
|
||||||
const { MODE } = process.env
|
|
||||||
if (MODE?.trim() !== 'server')
|
|
||||||
return res.status(200).send({
|
|
||||||
userId: 12345,
|
|
||||||
username: 'DESKTOPusername',
|
|
||||||
displayName: 'DESKTOP User'
|
|
||||||
})
|
|
||||||
|
|
||||||
next()
|
export const desktopUser: RequestUser = {
|
||||||
|
userId: 12345,
|
||||||
|
clientId: 'desktop_app',
|
||||||
|
username: userInfo().username,
|
||||||
|
displayName: userInfo().username,
|
||||||
|
isAdmin: true,
|
||||||
|
isActive: true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import swaggerUi from 'swagger-ui-express'
|
|||||||
import {
|
import {
|
||||||
authenticateAccessToken,
|
authenticateAccessToken,
|
||||||
desktopRestrict,
|
desktopRestrict,
|
||||||
desktopUsername,
|
|
||||||
verifyAdmin
|
verifyAdmin
|
||||||
} from '../../middlewares'
|
} from '../../middlewares'
|
||||||
|
|
||||||
@@ -22,7 +21,7 @@ import sessionRouter from './session'
|
|||||||
const router = express.Router()
|
const router = express.Router()
|
||||||
|
|
||||||
router.use('/info', infoRouter)
|
router.use('/info', infoRouter)
|
||||||
router.use('/session', desktopUsername, authenticateAccessToken, sessionRouter)
|
router.use('/session', authenticateAccessToken, sessionRouter)
|
||||||
router.use('/auth', desktopRestrict, authRouter)
|
router.use('/auth', desktopRestrict, authRouter)
|
||||||
router.use(
|
router.use(
|
||||||
'/client',
|
'/client',
|
||||||
|
|||||||
@@ -9,14 +9,14 @@ import { generateAccessToken, saveTokensInDB } from '../../../utils'
|
|||||||
const clientId = 'someclientID'
|
const clientId = 'someclientID'
|
||||||
const adminUser = {
|
const adminUser = {
|
||||||
displayName: 'Test Admin',
|
displayName: 'Test Admin',
|
||||||
username: 'testAdminUsername',
|
username: 'testadminusername',
|
||||||
password: '12345678',
|
password: '12345678',
|
||||||
isAdmin: true,
|
isAdmin: true,
|
||||||
isActive: true
|
isActive: true
|
||||||
}
|
}
|
||||||
const user = {
|
const user = {
|
||||||
displayName: 'Test User',
|
displayName: 'Test User',
|
||||||
username: 'testUsername',
|
username: 'testusername',
|
||||||
password: '87654321',
|
password: '87654321',
|
||||||
isAdmin: false,
|
isAdmin: false,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
@@ -68,6 +68,20 @@ describe('user', () => {
|
|||||||
expect(res.body.autoExec).toEqual(user.autoExec)
|
expect(res.body.autoExec).toEqual(user.autoExec)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should respond with new user having username as lowercase', async () => {
|
||||||
|
const res = await request(app)
|
||||||
|
.post('/SASjsApi/user')
|
||||||
|
.auth(adminAccessToken, { type: 'bearer' })
|
||||||
|
.send({ ...user, username: user.username.toUpperCase() })
|
||||||
|
.expect(200)
|
||||||
|
|
||||||
|
expect(res.body.username).toEqual(user.username)
|
||||||
|
expect(res.body.displayName).toEqual(user.displayName)
|
||||||
|
expect(res.body.isAdmin).toEqual(user.isAdmin)
|
||||||
|
expect(res.body.isActive).toEqual(user.isActive)
|
||||||
|
expect(res.body.autoExec).toEqual(user.autoExec)
|
||||||
|
})
|
||||||
|
|
||||||
it('should respond with Unauthorized if access token is not present', async () => {
|
it('should respond with Unauthorized if access token is not present', async () => {
|
||||||
const res = await request(app)
|
const res = await request(app)
|
||||||
.post('/SASjsApi/user')
|
.post('/SASjsApi/user')
|
||||||
@@ -244,7 +258,7 @@ describe('user', () => {
|
|||||||
const dbUser1 = await controller.createUser(user)
|
const dbUser1 = await controller.createUser(user)
|
||||||
const dbUser2 = await controller.createUser({
|
const dbUser2 = await controller.createUser({
|
||||||
...user,
|
...user,
|
||||||
username: 'randomUser'
|
username: 'randomuser'
|
||||||
})
|
})
|
||||||
|
|
||||||
const res = await request(app)
|
const res = await request(app)
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ const clientSecret = 'someclientSecret'
|
|||||||
const user = {
|
const user = {
|
||||||
id: 1234,
|
id: 1234,
|
||||||
displayName: 'Test User',
|
displayName: 'Test User',
|
||||||
username: 'testUsername',
|
username: 'testusername',
|
||||||
password: '87654321',
|
password: '87654321',
|
||||||
isAdmin: false,
|
isAdmin: false,
|
||||||
isActive: true
|
isActive: true
|
||||||
@@ -77,6 +77,7 @@ describe('web', () => {
|
|||||||
|
|
||||||
expect(res.body.loggedIn).toBeTruthy()
|
expect(res.body.loggedIn).toBeTruthy()
|
||||||
expect(res.body.user).toEqual({
|
expect(res.body.user).toEqual({
|
||||||
|
id: expect.any(Number),
|
||||||
username: user.username,
|
username: user.username,
|
||||||
displayName: user.displayName
|
displayName: user.displayName
|
||||||
})
|
})
|
||||||
@@ -155,7 +156,6 @@ const getCSRF = async (app: Express) => {
|
|||||||
const { header } = await request(app).get('/')
|
const { header } = await request(app).get('/')
|
||||||
const cookies = header['set-cookie'].join()
|
const cookies = header['set-cookie'].join()
|
||||||
|
|
||||||
console.log('cookies', cookies)
|
|
||||||
const csrfToken = extractCSRF(cookies)
|
const csrfToken = extractCSRF(cookies)
|
||||||
return { csrfToken, cookies }
|
return { csrfToken, cookies }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,10 +47,11 @@ stpRouter.post(
|
|||||||
query?._program
|
query?._program
|
||||||
)
|
)
|
||||||
|
|
||||||
if (response instanceof Buffer) {
|
// TODO: investigate if this code is required
|
||||||
res.writeHead(200, (req as any).sasHeaders)
|
// if (response instanceof Buffer) {
|
||||||
return res.end(response)
|
// res.writeHead(200, (req as any).sasHeaders)
|
||||||
}
|
// return res.end(response)
|
||||||
|
// }
|
||||||
|
|
||||||
res.send(response)
|
res.send(response)
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import express from 'express'
|
import express from 'express'
|
||||||
import { WebController } from '../../controllers/web'
|
import { WebController } from '../../controllers/web'
|
||||||
import { authenticateAccessToken } from '../../middlewares'
|
import { authenticateAccessToken, desktopRestrict } from '../../middlewares'
|
||||||
import { authorizeValidation, loginWebValidation } from '../../utils'
|
import { authorizeValidation, loginWebValidation } from '../../utils'
|
||||||
|
|
||||||
const webRouter = express.Router()
|
const webRouter = express.Router()
|
||||||
@@ -19,7 +19,7 @@ webRouter.get('/', async (req, res) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
webRouter.post('/SASLogon/login', async (req, res) => {
|
webRouter.post('/SASLogon/login', desktopRestrict, async (req, res) => {
|
||||||
const { error, value: body } = loginWebValidation(req.body)
|
const { error, value: body } = loginWebValidation(req.body)
|
||||||
if (error) return res.status(400).send(error.details[0].message)
|
if (error) return res.status(400).send(error.details[0].message)
|
||||||
|
|
||||||
@@ -33,6 +33,7 @@ webRouter.post('/SASLogon/login', async (req, res) => {
|
|||||||
|
|
||||||
webRouter.post(
|
webRouter.post(
|
||||||
'/SASLogon/authorize',
|
'/SASLogon/authorize',
|
||||||
|
desktopRestrict,
|
||||||
authenticateAccessToken,
|
authenticateAccessToken,
|
||||||
async (req, res) => {
|
async (req, res) => {
|
||||||
const { error, value: body } = authorizeValidation(req.body)
|
const { error, value: body } = authorizeValidation(req.body)
|
||||||
@@ -47,7 +48,7 @@ webRouter.post(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
webRouter.get('/logout', async (req, res) => {
|
webRouter.get('/logout', desktopRestrict, async (req, res) => {
|
||||||
try {
|
try {
|
||||||
await controller.logout(req)
|
await controller.logout(req)
|
||||||
res.status(200).send('OK!')
|
res.status(200).send('OK!')
|
||||||
|
|||||||
8
api/src/utils/desktopAutoExec.ts
Normal file
8
api/src/utils/desktopAutoExec.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { createFile, readFile } from '@sasjs/utils'
|
||||||
|
import { getDesktopUserAutoExecPath } from './file'
|
||||||
|
|
||||||
|
export const getUserAutoExec = async (): Promise<string> =>
|
||||||
|
readFile(getDesktopUserAutoExecPath())
|
||||||
|
|
||||||
|
export const updateUserAutoExec = async (autoExecContent: string) =>
|
||||||
|
createFile(getDesktopUserAutoExecPath(), autoExecContent)
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
export * from './appStreamConfig'
|
export * from './appStreamConfig'
|
||||||
export * from './connectDB'
|
export * from './connectDB'
|
||||||
export * from './copySASjsCore'
|
export * from './copySASjsCore'
|
||||||
|
export * from './desktopAutoExec'
|
||||||
export * from './extractHeaders'
|
export * from './extractHeaders'
|
||||||
export * from './file'
|
export * from './file'
|
||||||
export * from './generateAccessToken'
|
export * from './generateAccessToken'
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Joi from 'joi'
|
import Joi from 'joi'
|
||||||
|
|
||||||
const usernameSchema = Joi.string().alphanum().min(3).max(16)
|
const usernameSchema = Joi.string().lowercase().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
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ const Header = (props: any) => {
|
|||||||
color="primary"
|
color="primary"
|
||||||
startIcon={<SettingsIcon />}
|
startIcon={<SettingsIcon />}
|
||||||
>
|
>
|
||||||
Setting
|
Settings
|
||||||
</Button>
|
</Button>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem onClick={handleLogout} sx={{ justifyContent: 'center' }}>
|
<MenuItem onClick={handleLogout} sx={{ justifyContent: 'center' }}>
|
||||||
|
|||||||
@@ -14,10 +14,10 @@ import {
|
|||||||
FormControlLabel,
|
FormControlLabel,
|
||||||
Checkbox
|
Checkbox
|
||||||
} from '@mui/material'
|
} from '@mui/material'
|
||||||
|
|
||||||
import { AppContext } from '../../context/appContext'
|
|
||||||
import { toast } from 'react-toastify'
|
import { toast } from 'react-toastify'
|
||||||
|
|
||||||
|
import { AppContext, ModeType } from '../../context/appContext'
|
||||||
|
|
||||||
const Profile = () => {
|
const Profile = () => {
|
||||||
const [isLoading, setIsLoading] = useState(false)
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
const appContext = useContext(AppContext)
|
const appContext = useContext(AppContext)
|
||||||
@@ -89,6 +89,7 @@ const Profile = () => {
|
|||||||
required
|
required
|
||||||
value={user.displayName}
|
value={user.displayName}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
|
disabled={appContext.mode === ModeType.Desktop}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
@@ -103,6 +104,20 @@ const Profile = () => {
|
|||||||
required
|
required
|
||||||
value={user.username}
|
value={user.username}
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
|
disabled={appContext.mode === ModeType.Desktop}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid item lg={6} md={8} sm={12} xs={12}>
|
||||||
|
<TextField
|
||||||
|
fullWidth
|
||||||
|
label="autoExec"
|
||||||
|
name="autoExec"
|
||||||
|
onChange={handleChange}
|
||||||
|
multiline
|
||||||
|
rows="10"
|
||||||
|
value={user.autoExec}
|
||||||
|
variant="outlined"
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
@@ -120,19 +135,6 @@ const Profile = () => {
|
|||||||
/>
|
/>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<TextField
|
|
||||||
fullWidth
|
|
||||||
label="autoExec"
|
|
||||||
name="autoExec"
|
|
||||||
onChange={handleChange}
|
|
||||||
multiline
|
|
||||||
rows="4"
|
|
||||||
value={user.autoExec}
|
|
||||||
variant="outlined"
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
<Divider />
|
<Divider />
|
||||||
|
|||||||
@@ -9,6 +9,11 @@ import React, {
|
|||||||
} from 'react'
|
} from 'react'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
|
||||||
|
export enum ModeType {
|
||||||
|
Server = 'server',
|
||||||
|
Desktop = 'desktop'
|
||||||
|
}
|
||||||
|
|
||||||
interface AppContextProps {
|
interface AppContextProps {
|
||||||
checkingSession: boolean
|
checkingSession: boolean
|
||||||
loggedIn: boolean
|
loggedIn: boolean
|
||||||
@@ -19,6 +24,7 @@ interface AppContextProps {
|
|||||||
setUsername: Dispatch<SetStateAction<string>> | null
|
setUsername: Dispatch<SetStateAction<string>> | null
|
||||||
displayName: string
|
displayName: string
|
||||||
setDisplayName: Dispatch<SetStateAction<string>> | null
|
setDisplayName: Dispatch<SetStateAction<string>> | null
|
||||||
|
mode: ModeType
|
||||||
logout: (() => void) | null
|
logout: (() => void) | null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,6 +38,7 @@ export const AppContext = createContext<AppContextProps>({
|
|||||||
setUsername: null,
|
setUsername: null,
|
||||||
displayName: '',
|
displayName: '',
|
||||||
setDisplayName: null,
|
setDisplayName: null,
|
||||||
|
mode: ModeType.Server,
|
||||||
logout: null
|
logout: null
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -42,6 +49,7 @@ const AppContextProvider = (props: { children: ReactNode }) => {
|
|||||||
const [userId, setUserId] = useState(0)
|
const [userId, setUserId] = useState(0)
|
||||||
const [username, setUsername] = useState('')
|
const [username, setUsername] = useState('')
|
||||||
const [displayName, setDisplayName] = useState('')
|
const [displayName, setDisplayName] = useState('')
|
||||||
|
const [mode, setMode] = useState(ModeType.Server)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setCheckingSession(true)
|
setCheckingSession(true)
|
||||||
@@ -60,6 +68,14 @@ const AppContextProvider = (props: { children: ReactNode }) => {
|
|||||||
setLoggedIn(false)
|
setLoggedIn(false)
|
||||||
axios.get('/') // get CSRF TOKEN
|
axios.get('/') // get CSRF TOKEN
|
||||||
})
|
})
|
||||||
|
|
||||||
|
axios
|
||||||
|
.get('/SASjsApi/info')
|
||||||
|
.then((res) => res.data)
|
||||||
|
.then((data: any) => {
|
||||||
|
setMode(data.mode)
|
||||||
|
})
|
||||||
|
.catch(() => {})
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const logout = useCallback(() => {
|
const logout = useCallback(() => {
|
||||||
@@ -82,6 +98,7 @@ const AppContextProvider = (props: { children: ReactNode }) => {
|
|||||||
setUsername,
|
setUsername,
|
||||||
displayName,
|
displayName,
|
||||||
setDisplayName,
|
setDisplayName,
|
||||||
|
mode,
|
||||||
logout
|
logout
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
Reference in New Issue
Block a user