mirror of
https://github.com/linux-odyssey/linux-odyssey.git
synced 2026-11-05 19:20:12 +08:00
change to use session for auth
+ replace BearerAuth to cookieAuth in swagger + add swagger.yaml to nodemon watch list
This commit is contained in:
1 parent
a6d02f2616
commit
be5cd152a9
13 files changed
+216
-71
No files matched your search
@@ -6,6 +6,8 @@ COPY server/package.json ./server/package.json
|
||||
COPY packages/file-graph/package.json ./packages/file-graph/package.json
|
||||
RUN yarn install --frozen-lockfile
|
||||
|
||||
COPY server/nodemon.json ./server/nodemon.json
|
||||
|
||||
ENV NODE_ENV=development
|
||||
ENV HOST=0.0.0.0
|
||||
ENV PORT=3000
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"watch": ["src", "swagger.yaml"],
|
||||
"ext": "js,yaml"
|
||||
}
|
||||
@@ -13,8 +13,10 @@
|
||||
"@linux-odyssey/file-graph": "*",
|
||||
"bcrypt": "^5.1.1",
|
||||
"commander": "^11.0.0",
|
||||
"connect-mongo": "^5.0.0",
|
||||
"dockerode": "^3.3.5",
|
||||
"express": "^4.18.2",
|
||||
"express-session": "^1.17.3",
|
||||
"jsonwebtoken": "^9.0.1",
|
||||
"minimist": "^1.2.8",
|
||||
"mongoose": "^7.4.0",
|
||||
|
||||
@@ -92,8 +92,15 @@ export async function register(req, res, next) {
|
||||
user.hashedPassword = await hashPassword(password)
|
||||
await user.save()
|
||||
req.user = user
|
||||
res.status(201)
|
||||
next()
|
||||
req.login(user, (err) => {
|
||||
if (err) {
|
||||
next(err)
|
||||
return
|
||||
}
|
||||
res.status(201).json({
|
||||
message: 'user created',
|
||||
})
|
||||
})
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
res.status(500).json({
|
||||
@@ -101,3 +108,16 @@ export async function register(req, res, next) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export function logout(req, res) {
|
||||
req.logout((err) => {
|
||||
if (err) {
|
||||
console.error(err)
|
||||
res.status(500).json({
|
||||
message: 'error logging out',
|
||||
})
|
||||
return
|
||||
}
|
||||
res.json({ message: 'success' })
|
||||
})
|
||||
}
|
||||
@@ -2,20 +2,24 @@ import { Router } from 'express'
|
||||
import passport from 'passport'
|
||||
|
||||
import {
|
||||
issueToken,
|
||||
register,
|
||||
checkUsername,
|
||||
logout,
|
||||
} from '../controllers/authController.js'
|
||||
|
||||
const router = Router()
|
||||
|
||||
router.post(
|
||||
'/login',
|
||||
passport.authenticate('local', { session: false, failWithError: true }),
|
||||
issueToken
|
||||
passport.authenticate('local', { failureMessage: true }),
|
||||
(req, res) => {
|
||||
res.json({ message: 'success' })
|
||||
}
|
||||
)
|
||||
|
||||
router.post('/register', register, issueToken)
|
||||
router.post('/register', register)
|
||||
|
||||
router.post('/logout', logout)
|
||||
|
||||
router.get('/check', checkUsername)
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import commands from './commands.js'
|
||||
import authRouter from './auth.js'
|
||||
|
||||
const router = Router()
|
||||
router.use(passport.authenticate('session'))
|
||||
|
||||
router.get('/', (req, res) => {
|
||||
res.send('Hello API!')
|
||||
@@ -13,15 +14,11 @@ router.get('/', (req, res) => {
|
||||
|
||||
router.use('/auth', authRouter)
|
||||
router.use('/quests', quests)
|
||||
router.use(
|
||||
'/sessions',
|
||||
passport.authenticate('jwt', { session: false, failWithError: true }),
|
||||
sessions
|
||||
)
|
||||
router.use(
|
||||
'/commands',
|
||||
passport.authenticate('jwt', { session: false, failWithError: true }),
|
||||
commands
|
||||
)
|
||||
|
||||
const authZone = Router()
|
||||
authZone.use('/sessions', sessions)
|
||||
authZone.use('/commands', commands)
|
||||
|
||||
router.use(authZone)
|
||||
|
||||
export default router
|
||||
@@ -1,13 +0,0 @@
|
||||
import { Strategy as JwtStrategy, ExtractJwt } from 'passport-jwt'
|
||||
import config from '../config.js'
|
||||
|
||||
const jwtOptions = {
|
||||
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
|
||||
secretOrKey: config.jwtSecret,
|
||||
}
|
||||
|
||||
function verifyJwt(jwtPayload, done) {
|
||||
return done(null, jwtPayload)
|
||||
}
|
||||
|
||||
export default new JwtStrategy(jwtOptions, verifyJwt)
|
||||
@@ -1,6 +1,20 @@
|
||||
import passport from 'passport'
|
||||
import PasswordStrategy from './passwordStrategy.js'
|
||||
import JwtStrategy from './jwtStrategy.js'
|
||||
|
||||
passport.use(PasswordStrategy)
|
||||
passport.use(JwtStrategy)
|
||||
|
||||
passport.serializeUser((user, done) => {
|
||||
process.nextTick(() => {
|
||||
done(null, {
|
||||
_id: user._id,
|
||||
username: user.username,
|
||||
email: user.email,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
passport.deserializeUser((user, done) => {
|
||||
process.nextTick(() => {
|
||||
done(null, user)
|
||||
})
|
||||
})
|
||||
+6
-1
@@ -3,10 +3,15 @@ import config from './config.js'
|
||||
|
||||
export default async function connectDB() {
|
||||
try {
|
||||
await mongoose.connect(config.db)
|
||||
const db = await mongoose.connect(config.db, {
|
||||
useNewUrlParser: true,
|
||||
useUnifiedTopology: true,
|
||||
})
|
||||
console.log('Connected to MongoDB')
|
||||
return db.connection.getClient()
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
process.exit(1)
|
||||
return null
|
||||
}
|
||||
}
|
||||
+14
-5
@@ -11,14 +11,12 @@ import apiRouter from './api/routes/index.js'
|
||||
import loadAndUpdateQuests from './utils/quest.js'
|
||||
import config from './config.js'
|
||||
import errorHandler from './middleware/error.js'
|
||||
import sessionMiddleware from './middleware/session.js'
|
||||
import expiryRemovalScheduler from './containers/expiryChecker.js'
|
||||
import { createTestUser } from './utils/auth.js'
|
||||
|
||||
async function main() {
|
||||
const app = express()
|
||||
const server = http.createServer(app)
|
||||
socketServer(server)
|
||||
await connectDB()
|
||||
const db = await connectDB()
|
||||
|
||||
await createTestUser()
|
||||
|
||||
@@ -27,8 +25,19 @@ async function main() {
|
||||
|
||||
const file = await fs.readFile('./swagger.yaml', 'utf8')
|
||||
const swaggerDocument = YAML.parse(file)
|
||||
|
||||
const app = express()
|
||||
const server = http.createServer(app)
|
||||
socketServer(server)
|
||||
app.use(errorHandler)
|
||||
app.use('/api-docs', swaggerUI.serve, swaggerUI.setup(swaggerDocument))
|
||||
app.use(sessionMiddleware(db))
|
||||
app.use(
|
||||
'/api-docs',
|
||||
swaggerUI.serve,
|
||||
swaggerUI.setup(swaggerDocument, {
|
||||
withCredentials: true,
|
||||
})
|
||||
)
|
||||
app.use(express.json())
|
||||
|
||||
app.get('/', (req, res) => {
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import session from 'express-session'
|
||||
import MongoStore from 'connect-mongo'
|
||||
|
||||
import config from '../config.js'
|
||||
|
||||
export default (db) => {
|
||||
console.log(db.constructor.name)
|
||||
return session({
|
||||
secret: config.jwtSecret,
|
||||
resave: false,
|
||||
saveUninitialized: false,
|
||||
cookie: {
|
||||
httpOnly: true,
|
||||
},
|
||||
store: MongoStore.create({
|
||||
mongoUrl: config.db,
|
||||
collectionName: 'loginSessions',
|
||||
}),
|
||||
})
|
||||
}
|
||||
+40
-25
@@ -24,7 +24,7 @@ paths:
|
||||
- signed-in
|
||||
summary: list existing sessions of current user
|
||||
security:
|
||||
- BearerAuth: []
|
||||
- cookieAuth: []
|
||||
parameters:
|
||||
- in: query
|
||||
name: quest_id
|
||||
@@ -52,7 +52,7 @@ paths:
|
||||
tags:
|
||||
- signed-in
|
||||
security:
|
||||
- BearerAuth: []
|
||||
- cookieAuth: []
|
||||
requestBody:
|
||||
description: session data
|
||||
content:
|
||||
@@ -86,7 +86,7 @@ paths:
|
||||
- signed-in
|
||||
summary: get a specific session of current user by ID
|
||||
security:
|
||||
- BearerAuth: []
|
||||
- cookieAuth: []
|
||||
parameters:
|
||||
- in: path
|
||||
name: session_id
|
||||
@@ -117,7 +117,7 @@ paths:
|
||||
- signed-in
|
||||
summary: delete a specific session by ID
|
||||
security:
|
||||
- BearerAuth: []
|
||||
- cookieAuth: []
|
||||
parameters:
|
||||
- in: path
|
||||
name: session_id
|
||||
@@ -176,6 +176,11 @@ paths:
|
||||
responses:
|
||||
'201':
|
||||
description: User created
|
||||
headers:
|
||||
Set-Cookie:
|
||||
schema:
|
||||
type: string
|
||||
example: connect.sid=s%3Aq1Z; Path=/; HttpOnly; SameSite=Strict; Secure
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
@@ -227,15 +232,19 @@ paths:
|
||||
responses:
|
||||
'200':
|
||||
description: User logged in
|
||||
headers:
|
||||
Set-Cookie:
|
||||
schema:
|
||||
type: string
|
||||
example: connect.sid=s%3Aq1Z; Path=/; HttpOnly; SameSite=Strict; Secure
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
token:
|
||||
message:
|
||||
type: string
|
||||
description: Access token
|
||||
example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
example: Logged in successfully
|
||||
'400':
|
||||
description: Bad Request
|
||||
content:
|
||||
@@ -257,6 +266,25 @@ paths:
|
||||
type: string
|
||||
example: Incorrect username or password
|
||||
|
||||
/auth/logout:
|
||||
post:
|
||||
summary: Log out a user
|
||||
tags:
|
||||
- signed-in
|
||||
security:
|
||||
- cookieAuth: []
|
||||
responses:
|
||||
'200':
|
||||
description: User logged out
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
example: Logged out successfully
|
||||
|
||||
/auth/check:
|
||||
get:
|
||||
summary: Check if the username is already taken
|
||||
@@ -291,19 +319,6 @@ paths:
|
||||
type: string
|
||||
example: Username is already taken
|
||||
|
||||
/profile:
|
||||
get:
|
||||
summary: Get the profile of current logged-in user
|
||||
security:
|
||||
- BearerAuth: []
|
||||
responses:
|
||||
'200':
|
||||
description: Get user's profile
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/User'
|
||||
|
||||
/quests:
|
||||
get:
|
||||
summary: Get quests list
|
||||
@@ -350,7 +365,7 @@ paths:
|
||||
tags:
|
||||
- signed-in
|
||||
security:
|
||||
- BearerAuth: []
|
||||
- cookieAuth: []
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
@@ -537,7 +552,7 @@ components:
|
||||
example: 'Unix Spirit'
|
||||
|
||||
securitySchemes:
|
||||
BearerAuth:
|
||||
type: http
|
||||
scheme: bearer
|
||||
bearerFormat: JWT
|
||||
cookieAuth:
|
||||
type: apiKey
|
||||
in: cookie
|
||||
name: connect.sid
|
||||
Reference in new issue
Block a user