summaryrefslogtreecommitdiff
path: root/garden/src/store/auth.ts
blob: 915e4dec9dc3fe2ce5c76cfbbdd04a5f7a5fac65 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import { createSignal } from "solid-js";
import { api } from "../api";
import type { User } from "../types/user";

interface AuthResponse {
  token: string;
  user: User;
}

interface MessageResponse {
  message: string;
}

interface ErrorResponse {
  error: string;
}

const [user, setUser] = createSignal<User | null>(null);
const [token, setToken] = createSignal<string | null>(localStorage.getItem("token"));
const [loading, setLoading] = createSignal(true);

async function initialize() {
  const stored = token();
  if (!stored) {
    setLoading(false);
    return;
  }

  try {
    const response = await api<User>("/auth/me", { token: stored });
    if (response.ok) {
      setUser(response.data);
    } else {
      localStorage.removeItem("token");
      setToken(null);
    }
  } catch {
    localStorage.removeItem("token");
    setToken(null);
  }
  setLoading(false);
}

async function login(username: string, password: string): Promise<string | null> {
  const response = await api<AuthResponse | ErrorResponse>("/auth/login", {
    method: "POST",
    body: { username, password },
  });

  if (response.ok) {
    const data = response.data as AuthResponse;
    localStorage.setItem("token", data.token);
    setToken(data.token);
    setUser(data.user);
    return null;
  }

  return (response.data as ErrorResponse).error;
}

async function register(username: string, email: string, password: string, displayName: string): Promise<string | null> {
  const response = await api<MessageResponse | ErrorResponse>("/auth/register", {
    method: "POST",
    body: { username, email, password, display_name: displayName },
  });

  if (response.ok) return null;
  return (response.data as ErrorResponse).error;
}

async function verify(verificationToken: string, type: string): Promise<string | null> {
  const response = await api<MessageResponse | ErrorResponse>("/auth/verify", {
    method: "POST",
    body: { token: verificationToken, type },
  });

  if (response.ok) return null;
  return (response.data as ErrorResponse).error;
}

async function reactivate(email: string): Promise<string | null> {
  const response = await api<MessageResponse | ErrorResponse>("/auth/reactivate", {
    method: "POST",
    body: { email },
  });

  if (response.ok) return null;
  return (response.data as ErrorResponse).error;
}

async function heartbeat() {
  const stored = token();
  if (stored) {
    await api("/auth/heartbeat", { method: "POST", token: stored });
  }
}

async function logout() {
  const stored = token();
  if (stored) {
    await api("/auth/logout", { method: "POST", token: stored });
  }
  localStorage.removeItem("token");
  setToken(null);
  setUser(null);
}

export const auth = { user, token, loading, initialize, login, register, verify, reactivate, heartbeat, logout };