auth.ts 3.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. import type { BootstrapResponse, CurrentUser, JsonValue, Profile } from '@shared/types'
  2. import { apiRequest, setApiCsrfToken, unwrapData } from './client'
  3. import { bool, normalizeProfile, normalizeUser, record, string, values } from '@/utils/normalize'
  4. import { getProfileIdentities } from './profiles'
  5. function normalizeBootstrap(payload: unknown): BootstrapResponse {
  6. const root = record(unwrapData(payload as never))
  7. const status = record(root.status)
  8. const authRequired = bool(root.authRequired ?? root.auth_required ?? status.authRequired ?? status.auth_required)
  9. const rawUser = root.user ?? root.identity
  10. const profiles = values(root.profiles).map(normalizeProfile)
  11. const csrfToken = string(root.csrfToken ?? root.csrf_token ?? root.csrf)
  12. const response: BootstrapResponse = {
  13. status: string(status.state ?? root.state) || undefined,
  14. authRequired,
  15. setupRequired: bool(root.setupRequired ?? root.setup_required),
  16. profiles,
  17. csrfToken,
  18. insecureLan: bool(root.insecureLan ?? root.insecure_lan),
  19. groupUploadsEnabled: bool(root.groupUploadsEnabled ?? root.group_uploads_enabled),
  20. upstreamReady: bool(root.upstreamReady ?? root.upstream_ready),
  21. upstreamError: string(root.upstreamError ?? root.upstream_error) || undefined,
  22. serverKind: string(root.serverKind ?? root.server_kind) || undefined,
  23. }
  24. if (rawUser) response.user = normalizeUser(rawUser)
  25. setApiCsrfToken(csrfToken)
  26. return response
  27. }
  28. export async function bootstrap(): Promise<BootstrapResponse> {
  29. return normalizeBootstrap(await apiRequest<unknown>('/api/app/bootstrap', { csrf: false }))
  30. }
  31. export interface LoginInput {
  32. username: string
  33. password: string
  34. provider?: string
  35. }
  36. export async function login(input: LoginInput): Promise<BootstrapResponse> {
  37. const payload = await apiRequest<unknown>('/api/app/login', {
  38. method: 'POST',
  39. body: { ...input, next: '/' } as JsonValue,
  40. notifyUnauthorized: false,
  41. })
  42. const response = normalizeBootstrap(payload)
  43. if (!response.user && response.authRequired) return bootstrap()
  44. return response
  45. }
  46. export async function setup(input: LoginInput): Promise<BootstrapResponse> {
  47. return normalizeBootstrap(await apiRequest<unknown>('/api/app/setup', {
  48. method: 'POST',
  49. body: input as unknown as JsonValue,
  50. notifyUnauthorized: false,
  51. }))
  52. }
  53. export async function logout(): Promise<void> {
  54. await apiRequest('/api/app/logout', { method: 'POST', body: {}, notifyUnauthorized: false })
  55. setApiCsrfToken('')
  56. }
  57. export async function fetchProfiles(): Promise<Profile[]> {
  58. const payload = record(unwrapData(await apiRequest<unknown>('/api/app/profiles')))
  59. return values(payload.profiles ?? payload.items ?? payload).map(normalizeProfile)
  60. }
  61. export async function fetchProfileIdentities(profiles: Profile[]): Promise<Record<string, { displayName: string; avatar: string }>> {
  62. return getProfileIdentities(profiles)
  63. }
  64. export async function fetchCurrentUser(): Promise<CurrentUser | undefined> {
  65. const response = await bootstrap()
  66. return response.user
  67. }
  68. export async function changeCredentials(input: {
  69. currentPassword: string
  70. newPassword: string
  71. username?: string
  72. }): Promise<CurrentUser> {
  73. const payload = record(unwrapData(await apiRequest<unknown>('/api/app/account/credentials', {
  74. method: 'PUT', body: input as unknown as JsonValue, notifyUnauthorized: false,
  75. })))
  76. return normalizeUser(payload.user ?? payload)
  77. }
  78. export async function updateAccountAvatar(avatar: string | null): Promise<CurrentUser> {
  79. const payload = record(unwrapData(await apiRequest<unknown>('/api/app/account/avatar', {
  80. method: 'PUT', body: { avatar } as unknown as JsonValue,
  81. })))
  82. return normalizeUser(payload.user ?? payload)
  83. }