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 passport from 'passport'
|
||||
|
||||
import { genJWT } from '../../utils/auth.js'
|
||||
import {
|
||||
issueToken,
|
||||
register,
|
||||
checkUsername,
|
||||
} from '../controllers/authController.js'
|
||||
|
||||
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(
|
||||
'/login/password',
|
||||
'/login',
|
||||
passport.authenticate('local', { session: false }),
|
||||
issueToken
|
||||
)
|
||||
|
||||
router.post('/register', register, issueToken)
|
||||
|
||||
router.get('/check', checkUsername)
|
||||
|
||||
export default router
|
||||
@@ -11,7 +11,7 @@ router.get('/', (req, res) => {
|
||||
res.send('Hello API!')
|
||||
})
|
||||
|
||||
router.use(authRouter)
|
||||
router.use('/auth', authRouter)
|
||||
router.use('/quests', quests)
|
||||
router.use(
|
||||
'/sessions',
|
||||
|
||||
+1
-2
@@ -27,6 +27,7 @@ async function main() {
|
||||
|
||||
const file = await fs.readFile('./swagger.yaml', 'utf8')
|
||||
const swaggerDocument = YAML.parse(file)
|
||||
app.use(errorHandler)
|
||||
app.use('/api-docs', swaggerUI.serve, swaggerUI.setup(swaggerDocument))
|
||||
app.use(express.json())
|
||||
|
||||
@@ -36,8 +37,6 @@ async function main() {
|
||||
|
||||
app.use('/api/v1', apiRouter)
|
||||
|
||||
app.use(errorHandler)
|
||||
|
||||
server.listen(config.port, config.host, () => {
|
||||
console.log(`Server listening at http://${config.host}:${config.port}`)
|
||||
})
|
||||
|
||||
@@ -3,6 +3,10 @@ import bcrypt from 'bcrypt'
|
||||
import config from '../config.js'
|
||||
import User from '../models/user.js'
|
||||
|
||||
export function hashPassword(password) {
|
||||
return bcrypt.hash(password, 10)
|
||||
}
|
||||
|
||||
export async function createTestUser() {
|
||||
let user = await User.findOne({ username: 'testUser' })
|
||||
if (!user) {
|
||||
@@ -10,7 +14,7 @@ export async function createTestUser() {
|
||||
username: 'testUser',
|
||||
email: 'test@example.com',
|
||||
})
|
||||
user.hashedPassword = await bcrypt.hash('testPassword', 10)
|
||||
user.hashedPassword = await hashPassword('testPassword')
|
||||
await user.save()
|
||||
}
|
||||
}
|
||||
|
||||
+50
-7
@@ -150,7 +150,7 @@ paths:
|
||||
type: string
|
||||
example: 'Unauthorized.'
|
||||
|
||||
/register:
|
||||
/auth/register:
|
||||
post:
|
||||
summary: Register a new user
|
||||
requestBody:
|
||||
@@ -162,10 +162,16 @@ paths:
|
||||
properties:
|
||||
username:
|
||||
type: string
|
||||
format: username
|
||||
example: alex
|
||||
email:
|
||||
type: string
|
||||
format: email
|
||||
example: alex@example.com
|
||||
password:
|
||||
type: string
|
||||
format: password
|
||||
example: 123456
|
||||
responses:
|
||||
'201':
|
||||
description: User created
|
||||
@@ -174,9 +180,10 @@ paths:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
message:
|
||||
token:
|
||||
type: string
|
||||
example: User created successfully
|
||||
description: Access token
|
||||
example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
'400':
|
||||
description: Bad Request
|
||||
content:
|
||||
@@ -198,7 +205,7 @@ paths:
|
||||
type: string
|
||||
example: User already exists
|
||||
|
||||
/login/password:
|
||||
/auth/login:
|
||||
post:
|
||||
summary: Log in a user
|
||||
requestBody:
|
||||
@@ -210,8 +217,12 @@ paths:
|
||||
properties:
|
||||
username:
|
||||
type: string
|
||||
format: username
|
||||
example: alex
|
||||
password:
|
||||
type: string
|
||||
format: password
|
||||
example: 123456
|
||||
responses:
|
||||
'200':
|
||||
description: User logged in
|
||||
@@ -220,12 +231,10 @@ paths:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
example: Login successful
|
||||
token:
|
||||
type: string
|
||||
description: Access token
|
||||
example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
'400':
|
||||
description: Bad Request
|
||||
content:
|
||||
@@ -247,6 +256,40 @@ paths:
|
||||
type: string
|
||||
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:
|
||||
get:
|
||||
summary: Get the profile of current logged-in user
|
||||
|
||||
Reference in new issue
Block a user