Change ussername & password endpoints
This commit is contained in:
90
src/index.ts
90
src/index.ts
@@ -32,6 +32,8 @@ import { handler as berryDashIconMarketplacePostHandler } from './routes/berryda
|
|||||||
|
|
||||||
import { handler as berryDashAccountLoginPostHandler } from './routes/berrydash/account/login/post'
|
import { handler as berryDashAccountLoginPostHandler } from './routes/berrydash/account/login/post'
|
||||||
import { handler as berryDashAccountRegisterPostHandler } from './routes/berrydash/account/register/post'
|
import { handler as berryDashAccountRegisterPostHandler } from './routes/berrydash/account/register/post'
|
||||||
|
import { handler as berryDashAccountChangeUsernamePostHandler } from './routes/berrydash/account/change-username/post'
|
||||||
|
import { handler as berryDashAccountChangePasswordPostHandler } from './routes/berrydash/account/change-password/post'
|
||||||
import { handler as berryDashAccountSaveGetHandler } from './routes/berrydash/account/save/get'
|
import { handler as berryDashAccountSaveGetHandler } from './routes/berrydash/account/save/get'
|
||||||
import { handler as berryDashAccountSavePostHandler } from './routes/berrydash/account/save/post'
|
import { handler as berryDashAccountSavePostHandler } from './routes/berrydash/account/save/post'
|
||||||
|
|
||||||
@@ -392,34 +394,6 @@ app.post(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
app.get(
|
|
||||||
'/berrydash/account/save',
|
|
||||||
context => berryDashAccountSaveGetHandler(context),
|
|
||||||
{
|
|
||||||
detail: {
|
|
||||||
description:
|
|
||||||
"The endpoint for getting the account's save file. The contents will fully replace the current save file entirely on the client.",
|
|
||||||
tags: ['Berry Dash', 'Accounts']
|
|
||||||
},
|
|
||||||
headers: t.Object({
|
|
||||||
authorization: t.String()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
)
|
|
||||||
app.post(
|
|
||||||
'/berrydash/account/save',
|
|
||||||
context => berryDashAccountSavePostHandler(context),
|
|
||||||
{
|
|
||||||
detail: {
|
|
||||||
description:
|
|
||||||
"The endpoint for overwriting the account's save file on the server.",
|
|
||||||
tags: ['Berry Dash', 'Accounts']
|
|
||||||
},
|
|
||||||
headers: t.Object({
|
|
||||||
authorization: t.String()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
)
|
|
||||||
app.post(
|
app.post(
|
||||||
'/berrydash/account/login',
|
'/berrydash/account/login',
|
||||||
context => berryDashAccountLoginPostHandler(context),
|
context => berryDashAccountLoginPostHandler(context),
|
||||||
@@ -451,6 +425,66 @@ app.post(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
app.post(
|
||||||
|
'/berrydash/account/change-username',
|
||||||
|
context => berryDashAccountChangeUsernamePostHandler(context),
|
||||||
|
{
|
||||||
|
detail: {
|
||||||
|
description: "The endpoint for changing the account's user name.",
|
||||||
|
tags: ['Berry Dash', 'Accounts']
|
||||||
|
},
|
||||||
|
body: t.Object({
|
||||||
|
newUsername: t.String()
|
||||||
|
}),
|
||||||
|
headers: t.Object({
|
||||||
|
authorization: t.String()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
app.post(
|
||||||
|
'/berrydash/account/change-password',
|
||||||
|
context => berryDashAccountChangePasswordPostHandler(context),
|
||||||
|
{
|
||||||
|
detail: {
|
||||||
|
description: "The endpoint for changing the account's password.",
|
||||||
|
tags: ['Berry Dash', 'Accounts']
|
||||||
|
},
|
||||||
|
body: t.Object({
|
||||||
|
newPassword: t.String()
|
||||||
|
}),
|
||||||
|
headers: t.Object({
|
||||||
|
authorization: t.String()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
app.get(
|
||||||
|
'/berrydash/account/save',
|
||||||
|
context => berryDashAccountSaveGetHandler(context),
|
||||||
|
{
|
||||||
|
detail: {
|
||||||
|
description:
|
||||||
|
"The endpoint for getting the account's save file. The contents will fully replace the current save file entirely on the client.",
|
||||||
|
tags: ['Berry Dash', 'Accounts']
|
||||||
|
},
|
||||||
|
headers: t.Object({
|
||||||
|
authorization: t.String()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
app.post(
|
||||||
|
'/berrydash/account/save',
|
||||||
|
context => berryDashAccountSavePostHandler(context),
|
||||||
|
{
|
||||||
|
detail: {
|
||||||
|
description:
|
||||||
|
"The endpoint for overwriting the account's save file on the server.",
|
||||||
|
tags: ['Berry Dash', 'Accounts']
|
||||||
|
},
|
||||||
|
headers: t.Object({
|
||||||
|
authorization: t.String()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
app.all('*', () =>
|
app.all('*', () =>
|
||||||
jsonResponse(
|
jsonResponse(
|
||||||
{
|
{
|
||||||
|
|||||||
80
src/routes/berrydash/account/change-password/post.ts
Normal file
80
src/routes/berrydash/account/change-password/post.ts
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
import { Context } from 'elysia'
|
||||||
|
import {
|
||||||
|
getClientIp,
|
||||||
|
getDatabaseConnection,
|
||||||
|
jsonResponse
|
||||||
|
} from '../../../../lib/util'
|
||||||
|
import { checkAuthorization } from '../../../../lib/bd/auth'
|
||||||
|
import { users } from '../../../../lib/tables'
|
||||||
|
import { eq } from 'drizzle-orm'
|
||||||
|
import bcrypt from 'bcryptjs'
|
||||||
|
|
||||||
|
type Body = {
|
||||||
|
newPassword: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function handler (context: Context) {
|
||||||
|
const dbInfo0 = getDatabaseConnection(0)
|
||||||
|
const dbInfo1 = getDatabaseConnection(1)
|
||||||
|
|
||||||
|
if (!dbInfo0 || !dbInfo1)
|
||||||
|
return jsonResponse(
|
||||||
|
{ success: false, message: 'Failed to connect to database' },
|
||||||
|
500
|
||||||
|
)
|
||||||
|
const { connection: connection0, db: db0 } = dbInfo0
|
||||||
|
const { connection: connection1, db: db1 } = dbInfo1
|
||||||
|
|
||||||
|
const ip = getClientIp(context)
|
||||||
|
const authorizationToken = context.headers.authorization
|
||||||
|
const authResult = await checkAuthorization(
|
||||||
|
authorizationToken as string,
|
||||||
|
db1,
|
||||||
|
db0,
|
||||||
|
ip
|
||||||
|
)
|
||||||
|
if (!authResult.valid) {
|
||||||
|
connection0.end()
|
||||||
|
connection1.end()
|
||||||
|
return jsonResponse({ success: false, message: 'Unauthorized' }, 401)
|
||||||
|
}
|
||||||
|
const userId = authResult.id
|
||||||
|
|
||||||
|
const body = context.body as Body
|
||||||
|
if (!body.newPassword) {
|
||||||
|
connection0.end()
|
||||||
|
connection1.end()
|
||||||
|
return jsonResponse(
|
||||||
|
{ success: false, message: 'No new password provided' },
|
||||||
|
400
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
!/^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d!@#$%^&*()_\-+=]{8,}$/.test(
|
||||||
|
body.newPassword
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
connection0.end()
|
||||||
|
connection1.end()
|
||||||
|
return jsonResponse(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
message:
|
||||||
|
'New password must be at least 8 characters with at least one letter and one number',
|
||||||
|
data: null
|
||||||
|
},
|
||||||
|
400
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const hashedPassword = await bcrypt.hash(body.newPassword, 10)
|
||||||
|
|
||||||
|
await db0
|
||||||
|
.update(users)
|
||||||
|
.set({ password: hashedPassword })
|
||||||
|
.where(eq(users.id, userId))
|
||||||
|
.execute()
|
||||||
|
|
||||||
|
return jsonResponse({ success: true, message: null })
|
||||||
|
}
|
||||||
73
src/routes/berrydash/account/change-username/post.ts
Normal file
73
src/routes/berrydash/account/change-username/post.ts
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
import { Context } from 'elysia'
|
||||||
|
import {
|
||||||
|
getClientIp,
|
||||||
|
getDatabaseConnection,
|
||||||
|
jsonResponse
|
||||||
|
} from '../../../../lib/util'
|
||||||
|
import { checkAuthorization } from '../../../../lib/bd/auth'
|
||||||
|
import { users } from '../../../../lib/tables'
|
||||||
|
import { eq } from 'drizzle-orm'
|
||||||
|
|
||||||
|
type Body = {
|
||||||
|
newUsername: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function handler (context: Context) {
|
||||||
|
const dbInfo0 = getDatabaseConnection(0)
|
||||||
|
const dbInfo1 = getDatabaseConnection(1)
|
||||||
|
|
||||||
|
if (!dbInfo0 || !dbInfo1)
|
||||||
|
return jsonResponse(
|
||||||
|
{ success: false, message: 'Failed to connect to database' },
|
||||||
|
500
|
||||||
|
)
|
||||||
|
const { connection: connection0, db: db0 } = dbInfo0
|
||||||
|
const { connection: connection1, db: db1 } = dbInfo1
|
||||||
|
|
||||||
|
const ip = getClientIp(context)
|
||||||
|
const authorizationToken = context.headers.authorization
|
||||||
|
const authResult = await checkAuthorization(
|
||||||
|
authorizationToken as string,
|
||||||
|
db1,
|
||||||
|
db0,
|
||||||
|
ip
|
||||||
|
)
|
||||||
|
if (!authResult.valid) {
|
||||||
|
connection0.end()
|
||||||
|
connection1.end()
|
||||||
|
return jsonResponse({ success: false, message: 'Unauthorized' }, 401)
|
||||||
|
}
|
||||||
|
const userId = authResult.id
|
||||||
|
|
||||||
|
const body = context.body as Body
|
||||||
|
if (!body.newUsername) {
|
||||||
|
connection0.end()
|
||||||
|
connection1.end()
|
||||||
|
return jsonResponse(
|
||||||
|
{ success: false, message: 'No new username provided' },
|
||||||
|
400
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!/^[a-zA-Z0-9]{3,16}$/.test(body.newUsername)) {
|
||||||
|
connection0.end()
|
||||||
|
connection1.end()
|
||||||
|
return jsonResponse(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
message:
|
||||||
|
'New username must be 3-16 characters, letters and numbers only',
|
||||||
|
data: null
|
||||||
|
},
|
||||||
|
400
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
await db0
|
||||||
|
.update(users)
|
||||||
|
.set({ username: body.newUsername })
|
||||||
|
.where(eq(users.id, userId))
|
||||||
|
.execute()
|
||||||
|
|
||||||
|
return jsonResponse({ success: true, message: null })
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user