Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23,262 changes: 7,430 additions & 15,832 deletions api/package-lock.json

Large diffs are not rendered by default.

34 changes: 17 additions & 17 deletions api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,24 +49,24 @@
"author": "4GL Ltd",
"dependencies": {
"@sasjs/core": "^4.40.1",
"@sasjs/utils": "3.2.0",
"@sasjs/utils": "^3.5.2",
"bcryptjs": "^2.4.3",
"connect-mongo": "^4.6.0",
"cookie-parser": "^1.4.6",
"connect-mongo": "^5.1.0",
"cookie-parser": "^1.4.7",
"cors": "^2.8.5",
"express": "^4.17.1",
"express-session": "^1.17.2",
"express": "^4.21.2",
"express-session": "^1.18.2",
"helmet": "^5.0.2",
"joi": "^17.4.2",
"jsonwebtoken": "^8.5.1",
"jsonwebtoken": "^9.0.2",
"ldapjs": "2.3.3",
"mongoose": "^6.0.12",
"morgan": "^1.10.0",
"mongoose": "^6.13.8",
"morgan": "^1.10.1",
"multer": "^1.4.5-lts.1",
"rate-limiter-flexible": "2.4.1",
"rotating-file-stream": "^3.0.4",
"swagger-ui-express": "4.3.0",
"unzipper": "^0.10.11",
"unzipper": "^0.12.3",
"url": "^0.10.3"
},
"devDependencies": {
Expand All @@ -76,32 +76,32 @@
"@types/cors": "^2.8.12",
"@types/express": "^4.17.12",
"@types/express-session": "^1.17.4",
"@types/jest": "^26.0.24",
"@types/jest": "^29.5.0",
"@types/jsonwebtoken": "^8.5.5",
"@types/ldapjs": "^2.2.4",
"@types/morgan": "^1.9.3",
"@types/multer": "^1.4.7",
"@types/node": "^15.12.2",
"@types/node": "^20.0.0",
"@types/supertest": "^2.0.11",
"@types/swagger-ui-express": "^4.1.3",
"@types/unzipper": "^0.10.5",
"adm-zip": "^0.5.9",
"axios": "0.27.2",
"axios": "^1.12.2",
"csrf": "^3.1.0",
"dotenv": "^16.0.1",
"http-headers-validation": "^0.0.1",
"jest": "^27.0.6",
"jest": "^29.7.0",
"mongodb-memory-server": "8.11.4",
"nodejs-file-downloader": "4.10.2",
"nodemon": "^2.0.7",
"nodemon": "^3.0.0",
"pkg": "5.6.0",
"prettier": "^2.3.1",
"prettier": "^3.0.0",
"rimraf": "^3.0.2",
"supertest": "^6.1.3",
"ts-jest": "^27.0.3",
"ts-jest": "^29.1.0",
"ts-node": "^10.0.0",
"tsoa": "3.14.1",
"typescript": "^4.3.2"
"typescript": "^5.0.0"
},
"nodemonConfig": {
"ignore": [
Expand Down
5 changes: 3 additions & 2 deletions api/src/controllers/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,9 +234,10 @@ const verifyAuthCode = async (
jwt.verify(code, process.secrets.AUTH_CODE_SECRET, (err, data) => {
if (err) return resolve(undefined)

const payload = data as InfoJWT
const clientInfo: InfoJWT = {
clientId: data?.clientId,
userId: data?.userId
clientId: payload?.clientId,
userId: payload?.userId
}
if (clientInfo.clientId === clientId) {
return resolve(clientInfo)
Expand Down
7 changes: 5 additions & 2 deletions api/src/controllers/web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,15 +106,18 @@ const login = async (
const rateLimiter = RateLimiter.getInstance()

if (!validPass) {
const retrySecs = await rateLimiter.consume(req.ip, user?.username)
const retrySecs = await rateLimiter.consume(
req.ip || 'unknown',
user?.username
)
if (retrySecs > 0) throw errors.tooManyRequests(retrySecs)
}

if (!user) throw errors.userNotFound
if (!validPass) throw errors.invalidPassword

// Reset on successful authorization
rateLimiter.resetOnSuccess(req.ip, user.username)
rateLimiter.resetOnSuccess(req.ip || 'unknown', user.username)

req.session.loggedIn = true
req.session.user = {
Expand Down
6 changes: 3 additions & 3 deletions api/src/middlewares/authenticateToken.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ export const authenticateAccessToken: RequestHandler = async (
if (user.isActive) {
req.user = user
return csrfProtection(req, res, nextFunction)
} else return res.sendStatus(401)
} else return res.status(401).send('Unauthorized')
}
}
return res.sendStatus(401)
return res.status(401).send('Unauthorized')
}

await authenticateToken(
Expand Down Expand Up @@ -118,6 +118,6 @@ const authenticateToken = async (
return next()
}

res.sendStatus(401)
res.status(401).send('Unauthorized')
}
}
2 changes: 1 addition & 1 deletion api/src/middlewares/bruteForceProtection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { convertSecondsToHms } from '@sasjs/utils'
import { RateLimiter } from '../utils'

export const bruteForceProtection: RequestHandler = async (req, res, next) => {
const ip = req.ip
const ip = req.ip || 'unknown'
const username = req.body.username

const rateLimiter = RateLimiter.getInstance()
Expand Down
2 changes: 1 addition & 1 deletion api/src/model/Group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ groupSchema.post('save', function (group: IGroup, next: Function) {
})

// pre remove hook to remove all references of group from users
groupSchema.pre('remove', async function () {
groupSchema.pre('remove', async function (this: IGroupDocument) {
const userIds = this.users
await Promise.all(
userIds.map(async (userId) => {
Expand Down
5 changes: 4 additions & 1 deletion api/src/routes/api/spec/web.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,10 @@ const performLogin = async (
.set('x-xsrf-token', csrfToken)
.send(credentials)

return { authCookies: header['set-cookie'].join() }
return {
authCookies:
(header['set-cookie'] as unknown as string[] | undefined)?.join() || ''
}
}

const extractCSRF = (text: string) =>
Expand Down
4 changes: 3 additions & 1 deletion api/src/utils/getTokensFromDB.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import jwt from 'jsonwebtoken'
import User from '../model/User'
import { InfoJWT } from '../types/InfoJWT'

const isValidToken = async (
token: string,
Expand All @@ -11,7 +12,8 @@ const isValidToken = async (
jwt.verify(token, key, (err, decoded) => {
if (err) return reject(false)

if (decoded?.userId === userId && decoded?.clientId === clientId) {
const payload = decoded as InfoJWT
if (payload?.userId === userId && payload?.clientId === clientId) {
return resolve(true)
}

Expand Down
Loading