Skip to content

Commit

Permalink
Fix user-initiated password changes
Browse files Browse the repository at this point in the history
  • Loading branch information
sceuick committed Jun 29, 2023
1 parent 95e5140 commit 40fa746
Show file tree
Hide file tree
Showing 6 changed files with 19 additions and 18 deletions.
4 changes: 2 additions & 2 deletions srv/api/admin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ const searchUsers = handle(async (req) => {
})

const setUserPassword = handle(async (req) => {
assertValid({ username: 'string', password: 'string' }, req.body)
await store.admin.changePassword(req.body)
assertValid({ userId: 'string', password: 'string' }, req.body)
await store.admin.changePassword({ userId: req.body.userId, password: req.body.password })
return { success: true }
})

Expand Down
2 changes: 1 addition & 1 deletion srv/api/user/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ export const login = handle(async (req) => {

export const changePassword = handle(async (req) => {
assertValid({ password: 'string' }, req.body)
await store.admin.changePassword({ username: req.user?.username!, password: req.body.password })
await store.admin.changePassword({ userId: req.userId, password: req.body.password })
return { success: true }
})
4 changes: 2 additions & 2 deletions srv/db/admin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ export async function getUsers(opts: UsersOpts = {}) {
return list
}

export async function changePassword(opts: { username: string; password: string }) {
export async function changePassword(opts: { userId: string; password: string }) {
const hash = await encryptPassword(opts.password)
await db('user').updateOne({ kind: 'user', username: opts.username }, { $set: { hash } })
await db('user').updateOne({ _id: opts.userId }, { $set: { hash } })
return true
}

Expand Down
10 changes: 5 additions & 5 deletions srv/db/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export async function getMetrics() {
}

export async function getProfile(userId: string) {
const profile = await db('profile').findOne({ kind: 'profile', userId })
const profile = await db('profile').findOne({ userId })
return profile
}

Expand All @@ -57,23 +57,23 @@ export async function updateUserUI(userId: string, props: Partial<AppSchema.User
}

export async function updateUser(userId: string, props: Partial<AppSchema.User>) {
await db('user').updateOne({ _id: userId, kind: 'user' }, { $set: props })
await db('user').updateOne({ kind: 'user' }, { $set: props })
return getUser(userId)
}

export async function updateProfile(userId: string, props: Partial<AppSchema.Profile>) {
await db('profile').updateOne({ kind: 'profile', userId }, { $set: props })
await db('profile').updateOne({ userId }, { $set: props })
return getProfile(userId)
}

export async function authenticate(username: string, password: string) {
const user = await db('user').findOne({ kind: 'user', username: username.toLowerCase() })
const user = await db('user').findOne({ username: username.toLowerCase() })
if (!user) return

const match = await bcrypt.compare(password, user.hash)
if (!match) return

const profile = await db('profile').findOne({ kind: 'profile', userId: user._id })
const profile = await db('profile').findOne({ userId: user._id })
if (!profile) return

const token = await createAccessToken(username, user)
Expand Down
13 changes: 7 additions & 6 deletions web/pages/Admin/UsersPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ import PageHeader from '../../shared/PageHeader'
import TextInput from '../../shared/TextInput'
import { getAssetUrl, getStrictForm, setComponentPageTitle } from '../../shared/util'
import { adminStore } from '../../store'
import { AppSchema } from '/common/types'

const UsersPage: Component = () => {
let ref: any
setComponentPageTitle('Users')
const [pw, setPw] = createSignal('')
const [pw, setPw] = createSignal<AppSchema.User>()
const state = adminStore()
const [info, setInfo] = createSignal<{ name: string; id: string }>()

Expand Down Expand Up @@ -46,7 +47,7 @@ const UsersPage: Component = () => {
<div class="w-4/12 px-4 text-xs">{user._id}</div>
<div class="w-2/12 px-4">{user.username}</div>
<div class="flex w-6/12 justify-end gap-2 pr-2">
<Button size="sm" onClick={() => setPw(user.username)}>
<Button size="sm" onClick={() => setPw(user)}>
Set Password
</Button>
<Button size="sm" onClick={() => loadInfo(user._id, user.username)}>
Expand All @@ -56,7 +57,7 @@ const UsersPage: Component = () => {
</div>
)}
</For>
<PasswordModal show={!!pw()} username={pw()} close={() => setPw('')} />
<PasswordModal show={!!pw()} user={pw()!} close={() => setPw(undefined)} />
<InfoModel
show={!!info()}
close={() => setInfo()}
Expand Down Expand Up @@ -102,13 +103,13 @@ const InfoModel: Component<{ show: boolean; close: () => void; userId: string; n
)
}

const PasswordModal: Component<{ username: string; show: boolean; close: () => void }> = (
const PasswordModal: Component<{ user: AppSchema.User; show: boolean; close: () => void }> = (
props
) => {
let ref: any
const save = () => {
const body = getStrictForm(ref, { newPassword: 'string' })
adminStore.setPassword(props.username, body.newPassword, props.close)
adminStore.setPassword(props.user._id, body.newPassword, props.close)
}

return (
Expand All @@ -129,7 +130,7 @@ const PasswordModal: Component<{ username: string; show: boolean; close: () => v
}
>
<div>
Update password for: <b>{props.username}</b>
Update password for: <b>{props.user.username}</b>
</div>
<div>
<form ref={ref}>
Expand Down
4 changes: 2 additions & 2 deletions web/store/admin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ export const adminStore = createStore<AdminState>('admin', { users: [] })((_) =>
return { users: res.result.users }
}
},
async setPassword(_, username: string, password: string, onSuccess?: Function) {
const res = await api.post('/admin/user/password', { username, password })
async setPassword(_, userId: string, password: string, onSuccess?: Function) {
const res = await api.post('/admin/user/password', { userId, password })
if (res.error) return toastStore.error(`Failed to update user: ${res.error}`)
if (res.result) toastStore.success(`Update user settings`)
onSuccess?.()
Expand Down

0 comments on commit 40fa746

Please sign in to comment.