1
0
Fork 0

feat(backend): Added more routes

This commit is contained in:
Joost De Cock 2022-12-24 14:42:16 +01:00
parent cbe95701c5
commit 1b499effdf
6 changed files with 115 additions and 17 deletions

View file

@ -514,3 +514,52 @@ paths['/users/{username}'] = {
},
},
}
// Check whether a username is available
const checkUsername = "Little Miss Can't Be Wrong"
paths['/available/username'] = {
post: {
tags: ['Users'],
summary: `Checks whether a username is available`,
description:
'This allows a background check to see whether a username is available during signup',
requestBody: {
required: true,
content: {
'application/json': {
schema: {
type: 'object',
properties: {
username: {
type: 'string',
description: 'The username to check for availability',
example: checkUsername,
},
},
},
},
},
},
responses: {
200: {
description:
'**Success - Username is NOT available**\n\n' +
'Status code `200` indicates that the username exists.',
...jsonResponse({
result: 'success',
username: checkUsername,
available: false,
}),
},
401: response.status['401'],
403: {
...response.status['403'],
description:
response.status['403'].description +
errorExamples(['accountStatusLacking', 'insufficientAccessLevel']),
},
404: response.status['404'],
500: response.status['500'],
},
},
}

View file

@ -78,3 +78,23 @@ UsersController.prototype.updateMfa = async (req, res, tools) => {
return User.sendResponse(res)
}
/*
* Checks whether a submitted username is available
*
* See: https://freesewing.dev/reference/backend/api
*/
UsersController.prototype.isUsernameAvailable = async (req, res, tools) => {
const User = new UserModel(tools)
await User.find(req.body)
if (User.exists)
User.setResponse(200, false, {
result: 'success',
username: req.body?.username,
available: false,
})
else User.setResponse(404)
return User.sendResponse(res)
}

View file

@ -52,7 +52,7 @@ ApikeyModel.prototype.guardedRead = async function ({ params, user }) {
if (user.iss && user.status < 1) return this.setResponse(403, 'accountStatusLacking')
await this.unguardedRead({ id: params.id })
if (!this.record) return this.setResponse(404, 'apikeyNotFound')
if (!this.record) return this.setResponse(404)
if (this.record.userId !== user.uid) {
// Not own key - only admin can do that
@ -76,7 +76,7 @@ ApikeyModel.prototype.guardedDelete = async function ({ params, user }) {
if (user.iss && user.status < 1) return this.setResponse(403, 'accountStatusLacking')
await this.unguardedRead({ id: params.id })
if (!this.record) return this.setResponse(404, 'apikeyNotFound')
if (!this.record) return this.setResponse(404)
if (this.record.userId !== user.uid) {
// Not own key - only admin can do that

View file

@ -265,7 +265,7 @@ UserModel.prototype.passwordLogin = async function (req) {
* Confirms a user account
*/
UserModel.prototype.confirm = async function ({ body, params }) {
if (!params.id) return this.setResponse(404, 'confirmationIdMissing')
if (!params.id) return this.setResponse(404)
if (Object.keys(body) < 1) return this.setResponse(400, 'postBodyMissing')
if (!body.consent || typeof body.consent !== 'number' || body.consent < 1)
return this.setResponse(400, 'consentRequired')
@ -275,20 +275,18 @@ UserModel.prototype.confirm = async function ({ body, params }) {
if (!this.Confirmation.exists) {
log.warn(err, `Could not find confirmation id ${params.id}`)
return this.setResponse(404, 'failedToFindConfirmationId')
return this.setResponse(404)
}
if (this.Confirmation.record.type !== 'signup') {
log.warn(err, `Confirmation mismatch; ${params.id} is not a signup id`)
return this.setResponse(404, 'confirmationIdTypeMismatch')
return this.setResponse(404)
}
if (this.error) return this
const data = this.Confirmation.clear.data
if (data.ehash !== this.Confirmation.record.user.ehash)
return this.setResponse(404, 'confirmationEhashMismatch')
if (data.id !== this.Confirmation.record.user.id)
return this.setResponse(404, 'confirmationUserIdMismatch')
if (data.ehash !== this.Confirmation.record.user.ehash) return this.setResponse(404)
if (data.id !== this.Confirmation.record.user.id) return this.setResponse(404)
// Load user
await this.read({ id: this.Confirmation.record.user.id })
@ -404,12 +402,12 @@ UserModel.prototype.guardedUpdate = async function ({ body, user }) {
if (!this.Confirmation.exists) {
log.warn(err, `Could not find confirmation id ${params.id}`)
return this.setResponse(404, 'failedToFindConfirmationId')
return this.setResponse(404)
}
if (this.Confirmation.record.type !== 'emailchange') {
log.warn(err, `Confirmation mismatch; ${params.id} is not an emailchange id`)
return this.setResponse(404, 'confirmationIdTypeMismatch')
return this.setResponse(404)
}
const data = this.Confirmation.clear.data
@ -570,6 +568,7 @@ UserModel.prototype.setResponse = function (status = 200, error = false, data =
this.response.body.result = 'error'
this.error = true
} else this.error = false
if (status === 404) this.response.body = null
return this.setExists()
}

View file

@ -40,6 +40,10 @@ export function usersRoutes(tools) {
app.post('/account/mfa/key', passport.authenticate(...bsc), (req, res) =>
Users.updateMfa(req, res, tools)
)
// Check whether a username is available
app.post('/available/username', (req, res) => Users.isUsernameAvailable(req, res, tools))
/*
// Remove account
@ -95,11 +99,5 @@ export function usersRoutes(tools) {
(req, res) => User.readProfile(req, res, params)
)
// Check whether a username is available
app.post(
'/available/username',
passport.authenticate('jwt', { session: false }),
(req, res) => User.isUsernameAvailable(req, res, params)
)
*/
}

View file

@ -258,4 +258,36 @@ export const userTests = async (chai, config, expect, store) => {
})
})
})
describe(`${store.icon('user')} Check for available usernames`, () => {
it(`${store.icon('user')} Should find a username is available`, (done) => {
chai
.request(config.api)
.post(`/available/username`)
.send({
username: 'haochi',
})
.end((err, res) => {
expect(err === null).to.equal(true)
expect(res.status).to.equal(404)
done()
})
})
it(`${store.icon('user')} Should find a username is not available`, (done) => {
chai
.request(config.api)
.post(`/available/username`)
.send({
username: store.account.username,
})
.end((err, res) => {
expect(err === null).to.equal(true)
expect(res.status).to.equal(200)
expect(res.body.result).to.equal('success')
expect(res.body.available).to.equal(false)
expect(res.body.username).to.equal(store.account.username)
done()
})
})
})
}