forked from remix-run/grunge-stack
-
Notifications
You must be signed in to change notification settings - Fork 0
/
user.server.ts
118 lines (100 loc) · 2.55 KB
/
user.server.ts
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
109
110
111
112
113
114
115
116
117
118
// @ts-ignore
import { documentClient } from "@remix-vendor/cdk";
import bcrypt from "bcryptjs";
import invariant from "tiny-invariant";
import { logger } from "~/logger";
import { db } from "~/ports/db";
export type User = { id: `email#${string}`; email: string };
export type Password = { password: string };
export async function getUserById(id: User["id"]): Promise<User | null> {
logger.info("Getting user by id");
const result = await db.documentClient
.get({
TableName: db.tables.users,
Key: {
pk: id,
},
})
.promise();
const record = result.Item;
if (record) return { id: record.pk, email: record.email };
return null;
}
export async function getUserByEmail(email: User["email"]) {
return getUserById(`email#${email}`);
}
async function getUserPasswordByEmail(email: User["email"]) {
logger.info("Logging in user by email and password");
const result = await db.documentClient
.get({
TableName: db.tables.passwords,
Key: {
pk: `email#${email}`,
},
})
.promise();
const record = result.Item;
logger.info("Retrieved result", result);
if (record) return { hash: record.password };
return null;
}
export async function createUser(
email: User["email"],
password: Password["password"]
) {
const hashedPassword = await bcrypt.hash(password, 10);
await db.documentClient
.put({
TableName: db.tables.passwords,
Item: {
pk: `email#${email}`,
password: hashedPassword,
},
})
.promise();
await db.documentClient
.put({
TableName: db.tables.users,
Item: {
pk: `email#${email}`,
email,
},
})
.promise();
const user = await getUserByEmail(email);
invariant(user, `User not found after being created. This should not happen`);
return user;
}
export async function deleteUser(email: User["email"]) {
await documentClient
.delete({
TableName: db.tables.passwords,
Key: {
pk: `email#${email}`,
},
})
.promise();
await documentClient
.delete({
TableName: db.tables.users,
Key: {
pk: `email#${email}`,
},
})
.promise();
}
export async function verifyLogin(
email: User["email"],
password: Password["password"]
) {
const userPassword = await getUserPasswordByEmail(email);
logger.info("Verifying login", userPassword);
if (!userPassword) {
return undefined;
}
const isValid = await bcrypt.compare(password, userPassword.hash);
if (!isValid) {
return undefined;
}
return getUserByEmail(email);
}