mirror of
https://github.com/linux-odyssey/linux-odyssey.git
synced 2026-11-05 19:20:12 +08:00
feat: add register, checkUsername, update swagger
This commit is contained in:
1 parent
04a0b21cf6
commit
b55b7aa1ec
6 files changed
+118
-23
No files matched your search
@@ -0,0 +1,51 @@
|
|||||||
|
import User from '../../models/user.js'
|
||||||
|
import { genJWT, hashPassword } from '../../utils/auth.js'
|
||||||
|
|
||||||
|
export async function issueToken(req, res) {
|
||||||
|
const { user } = req
|
||||||
|
const token = await genJWT({
|
||||||
|
_id: user.id,
|
||||||
|
username: user.username,
|
||||||
|
email: user.email,
|
||||||
|
})
|
||||||
|
res.json({ token })
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function checkUsername(req, res) {
|
||||||
|
const { username } = req.query
|
||||||
|
const exists = await User.exists({ username })
|
||||||
|
if (exists) {
|
||||||
|
res.status(409).json({
|
||||||
|
message: `"${username}" already exists`,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
res.status(200).json({
|
||||||
|
message: `"${username}" is available`,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function register(req, res, next) {
|
||||||
|
const { username, password, email } = req.body
|
||||||
|
if (!(username && password && email)) {
|
||||||
|
res.status(400).json({
|
||||||
|
message: 'username, password, and email are required',
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (await User.exists({ $or: [{ username }, { email }] })) {
|
||||||
|
res.status(409).json({
|
||||||
|
message: 'username or email already exists',
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const user = new User({
|
||||||
|
username,
|
||||||
|
email,
|
||||||
|
})
|
||||||
|
user.hashedPassword = await hashPassword(password)
|
||||||
|
await user.save()
|
||||||
|
req.user = user
|
||||||
|
res.status(201)
|
||||||
|
next()
|
||||||
|
}
|
||||||
@@ -1,24 +1,22 @@
|
|||||||
import { Router } from 'express'
|
import { Router } from 'express'
|
||||||
import passport from 'passport'
|
import passport from 'passport'
|
||||||
|
|
||||||
import { genJWT } from '../../utils/auth.js'
|
import {
|
||||||
|
issueToken,
|
||||||
|
register,
|
||||||
|
checkUsername,
|
||||||
|
} from '../controllers/authController.js'
|
||||||
|
|
||||||
const router = Router()
|
const router = Router()
|
||||||
|
|
||||||
async function issueToken(req, res) {
|
|
||||||
const { user } = req
|
|
||||||
const token = await genJWT({
|
|
||||||
_id: user.id,
|
|
||||||
username: user.username,
|
|
||||||
email: user.email,
|
|
||||||
})
|
|
||||||
res.json({ token })
|
|
||||||
}
|
|
||||||
|
|
||||||
router.post(
|
router.post(
|
||||||
'/login/password',
|
'/login',
|
||||||
passport.authenticate('local', { session: false }),
|
passport.authenticate('local', { session: false }),
|
||||||
issueToken
|
issueToken
|
||||||
)
|
)
|
||||||
|
|
||||||
|
router.post('/register', register, issueToken)
|
||||||
|
|
||||||
|
router.get('/check', checkUsername)
|
||||||
|
|
||||||
export default router
|
export default router
|
||||||
@@ -11,7 +11,7 @@ router.get('/', (req, res) => {
|
|||||||
res.send('Hello API!')
|
res.send('Hello API!')
|
||||||
})
|
})
|
||||||
|
|
||||||
router.use(authRouter)
|
router.use('/auth', authRouter)
|
||||||
router.use('/quests', quests)
|
router.use('/quests', quests)
|
||||||
router.use(
|
router.use(
|
||||||
'/sessions',
|
'/sessions',
|
||||||
|
|||||||
+1
-2
@@ -27,6 +27,7 @@ async function main() {
|
|||||||
|
|
||||||
const file = await fs.readFile('./swagger.yaml', 'utf8')
|
const file = await fs.readFile('./swagger.yaml', 'utf8')
|
||||||
const swaggerDocument = YAML.parse(file)
|
const swaggerDocument = YAML.parse(file)
|
||||||
|
app.use(errorHandler)
|
||||||
app.use('/api-docs', swaggerUI.serve, swaggerUI.setup(swaggerDocument))
|
app.use('/api-docs', swaggerUI.serve, swaggerUI.setup(swaggerDocument))
|
||||||
app.use(express.json())
|
app.use(express.json())
|
||||||
|
|
||||||
@@ -36,8 +37,6 @@ async function main() {
|
|||||||
|
|
||||||
app.use('/api/v1', apiRouter)
|
app.use('/api/v1', apiRouter)
|
||||||
|
|
||||||
app.use(errorHandler)
|
|
||||||
|
|
||||||
server.listen(config.port, config.host, () => {
|
server.listen(config.port, config.host, () => {
|
||||||
console.log(`Server listening at http://${config.host}:${config.port}`)
|
console.log(`Server listening at http://${config.host}:${config.port}`)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -3,6 +3,10 @@ import bcrypt from 'bcrypt'
|
|||||||
import config from '../config.js'
|
import config from '../config.js'
|
||||||
import User from '../models/user.js'
|
import User from '../models/user.js'
|
||||||
|
|
||||||
|
export function hashPassword(password) {
|
||||||
|
return bcrypt.hash(password, 10)
|
||||||
|
}
|
||||||
|
|
||||||
export async function createTestUser() {
|
export async function createTestUser() {
|
||||||
let user = await User.findOne({ username: 'testUser' })
|
let user = await User.findOne({ username: 'testUser' })
|
||||||
if (!user) {
|
if (!user) {
|
||||||
@@ -10,7 +14,7 @@ export async function createTestUser() {
|
|||||||
username: 'testUser',
|
username: 'testUser',
|
||||||
email: 'test@example.com',
|
email: 'test@example.com',
|
||||||
})
|
})
|
||||||
user.hashedPassword = await bcrypt.hash('testPassword', 10)
|
user.hashedPassword = await hashPassword('testPassword')
|
||||||
await user.save()
|
await user.save()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+50
-7
@@ -150,7 +150,7 @@ paths:
|
|||||||
type: string
|
type: string
|
||||||
example: 'Unauthorized.'
|
example: 'Unauthorized.'
|
||||||
|
|
||||||
/register:
|
/auth/register:
|
||||||
post:
|
post:
|
||||||
summary: Register a new user
|
summary: Register a new user
|
||||||
requestBody:
|
requestBody:
|
||||||
@@ -162,10 +162,16 @@ paths:
|
|||||||
properties:
|
properties:
|
||||||
username:
|
username:
|
||||||
type: string
|
type: string
|
||||||
|
format: username
|
||||||
|
example: alex
|
||||||
email:
|
email:
|
||||||
type: string
|
type: string
|
||||||
|
format: email
|
||||||
|
example: alex@example.com
|
||||||
password:
|
password:
|
||||||
type: string
|
type: string
|
||||||
|
format: password
|
||||||
|
example: 123456
|
||||||
responses:
|
responses:
|
||||||
'201':
|
'201':
|
||||||
description: User created
|
description: User created
|
||||||
@@ -174,9 +180,10 @@ paths:
|
|||||||
schema:
|
schema:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
message:
|
token:
|
||||||
type: string
|
type: string
|
||||||
example: User created successfully
|
description: Access token
|
||||||
|
example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||||
'400':
|
'400':
|
||||||
description: Bad Request
|
description: Bad Request
|
||||||
content:
|
content:
|
||||||
@@ -198,7 +205,7 @@ paths:
|
|||||||
type: string
|
type: string
|
||||||
example: User already exists
|
example: User already exists
|
||||||
|
|
||||||
/login/password:
|
/auth/login:
|
||||||
post:
|
post:
|
||||||
summary: Log in a user
|
summary: Log in a user
|
||||||
requestBody:
|
requestBody:
|
||||||
@@ -210,8 +217,12 @@ paths:
|
|||||||
properties:
|
properties:
|
||||||
username:
|
username:
|
||||||
type: string
|
type: string
|
||||||
|
format: username
|
||||||
|
example: alex
|
||||||
password:
|
password:
|
||||||
type: string
|
type: string
|
||||||
|
format: password
|
||||||
|
example: 123456
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: User logged in
|
description: User logged in
|
||||||
@@ -220,12 +231,10 @@ paths:
|
|||||||
schema:
|
schema:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
message:
|
|
||||||
type: string
|
|
||||||
example: Login successful
|
|
||||||
token:
|
token:
|
||||||
type: string
|
type: string
|
||||||
description: Access token
|
description: Access token
|
||||||
|
example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||||
'400':
|
'400':
|
||||||
description: Bad Request
|
description: Bad Request
|
||||||
content:
|
content:
|
||||||
@@ -247,6 +256,40 @@ paths:
|
|||||||
type: string
|
type: string
|
||||||
example: Incorrect username or password
|
example: Incorrect username or password
|
||||||
|
|
||||||
|
/auth/check:
|
||||||
|
get:
|
||||||
|
summary: Check if the username is already taken
|
||||||
|
parameters:
|
||||||
|
- in: query
|
||||||
|
name: username
|
||||||
|
description: username to check
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: username
|
||||||
|
example: alex
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: Username is available
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
message:
|
||||||
|
type: string
|
||||||
|
example: Username is available
|
||||||
|
'409':
|
||||||
|
description: Username is already taken
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
message:
|
||||||
|
type: string
|
||||||
|
example: Username is already taken
|
||||||
|
|
||||||
/profile:
|
/profile:
|
||||||
get:
|
get:
|
||||||
summary: Get the profile of current logged-in user
|
summary: Get the profile of current logged-in user
|
||||||
|
|||||||
Reference in new issue
Block a user