feat: add admin console and account settings
Implement the admin dashboard with review, user, and image management workflows. Add profile settings, password reset, pending upload defaults, community placeholder routing, Vercel SPA rewrites, refreshed header styling, and the OpenCloud color-system skill.
This commit is contained in:
+69
-1
@@ -24,6 +24,24 @@ export const useAuthStore = defineStore('auth', () => {
|
||||
}
|
||||
}
|
||||
|
||||
async function ensureUsernameAvailable(username: string, currentUserId?: string) {
|
||||
let query = supabase
|
||||
.from('profiles')
|
||||
.select('id')
|
||||
.eq('username', username)
|
||||
.limit(1)
|
||||
|
||||
if (currentUserId) {
|
||||
query = query.neq('id', currentUserId)
|
||||
}
|
||||
|
||||
const { data, error } = await query
|
||||
if (error) throw error
|
||||
if (data?.length) {
|
||||
throw new Error('这个昵称已经被使用,请换一个。')
|
||||
}
|
||||
}
|
||||
|
||||
async function login(email: string, password: string) {
|
||||
const { data, error } = await supabase.auth.signInWithPassword({ email, password })
|
||||
if (error) {
|
||||
@@ -40,6 +58,8 @@ export const useAuthStore = defineStore('auth', () => {
|
||||
}
|
||||
|
||||
async function register(email: string, password: string, username: string) {
|
||||
await ensureUsernameAvailable(username)
|
||||
|
||||
const { error } = await supabase.auth.signUp({
|
||||
email,
|
||||
password,
|
||||
@@ -66,6 +86,40 @@ export const useAuthStore = defineStore('auth', () => {
|
||||
profile.value = null
|
||||
}
|
||||
|
||||
async function updateUsername(username: string) {
|
||||
if (!user.value) throw new Error('请先登录。')
|
||||
|
||||
await ensureUsernameAvailable(username, user.value.id)
|
||||
|
||||
const { data, error } = await supabase
|
||||
.from('profiles')
|
||||
.update({ username })
|
||||
.eq('id', user.value.id)
|
||||
.select('*')
|
||||
.single()
|
||||
|
||||
if (error) {
|
||||
if (error.code === '23505') {
|
||||
throw new Error('这个昵称已经被使用,请换一个。')
|
||||
}
|
||||
throw error
|
||||
}
|
||||
|
||||
profile.value = data as Profile
|
||||
}
|
||||
|
||||
async function updatePassword(password: string) {
|
||||
const { error } = await supabase.auth.updateUser({ password })
|
||||
if (error) throw error
|
||||
}
|
||||
|
||||
async function sendPasswordReset(email: string) {
|
||||
const { error } = await supabase.auth.resetPasswordForEmail(email, {
|
||||
redirectTo: `${window.location.origin}/auth/reset-password`,
|
||||
})
|
||||
if (error) throw error
|
||||
}
|
||||
|
||||
async function initialize() {
|
||||
const { data: { session } } = await supabase.auth.getSession()
|
||||
user.value = session?.user ?? null
|
||||
@@ -79,5 +133,19 @@ export const useAuthStore = defineStore('auth', () => {
|
||||
})
|
||||
}
|
||||
|
||||
return { user, profile, loading, isLoggedIn, isAdmin, login, register, logout, initialize }
|
||||
return {
|
||||
user,
|
||||
profile,
|
||||
loading,
|
||||
isLoggedIn,
|
||||
isAdmin,
|
||||
fetchProfile,
|
||||
login,
|
||||
register,
|
||||
logout,
|
||||
updateUsername,
|
||||
updatePassword,
|
||||
sendPasswordReset,
|
||||
initialize,
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user