feat: add register, checkUsername, update swagger

This commit is contained in:
wancat committed 2023-09-12 23:01:49 +08:00
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()
}
+10 -12
View File
@@ -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
+1 -1
View File
@@ -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
View File
@@ -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}`)
}) })
+5 -1
View File
@@ -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
View File
@@ -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