Skip to content

Commit 2b9bffd

Browse files
committed
refactor: migrate to drizzle
1 parent 0cd6850 commit 2b9bffd

File tree

7 files changed

+51
-26
lines changed

7 files changed

+51
-26
lines changed

.prettierignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ dist/
33
coverage/
44
.husky/_/
55
pnpm-lock.yaml
6-
vendor/common
6+
vendor/common/

drizzle/schema.ts

+17-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {
22
bigint,
3-
binary,
43
char,
4+
customType,
55
date,
66
float,
77
index,
@@ -530,11 +530,25 @@ export const chiiOauthClients = mysqlTable(
530530
},
531531
);
532532

533+
const mediumblob = (name: string) =>
534+
customType<{ data: Buffer; driverData: string }>({
535+
dataType() {
536+
return 'mediumblob';
537+
},
538+
fromDriver(value) {
539+
return Buffer.from(value);
540+
},
541+
542+
toDriver(value: Buffer): string {
543+
// @ts-expect-error https://github.com/drizzle-team/drizzle-orm/issues/1188
544+
return value;
545+
},
546+
})(name);
547+
533548
export const chiiOsWebSessions = mysqlTable('chii_os_web_sessions', {
534549
key: char('key', { length: 64 }).notNull(),
535550
userID: int('user_id').notNull(),
536-
// Warning: Can't parse mediumblob from database
537-
value: binary('value').notNull(),
551+
value: mediumblob('value').notNull(),
538552
createdAt: bigint('created_at', { mode: 'number' }).notNull(),
539553
expiredAt: bigint('expired_at', { mode: 'number' }).notNull(),
540554
});

lib/auth/session.test.ts

+11-6
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
import { DateTime } from 'luxon';
22
import { afterEach, beforeEach, expect, test } from 'vitest';
33

4-
import { SessionRepo } from '@app/lib/orm/index.ts';
4+
import { db, op } from '@app/drizzle/db.ts';
5+
import { chiiOsWebSessions } from '@app/drizzle/schema.ts';
56

67
import { create, get, revoke } from './session.ts';
78

89
beforeEach(async () => {
9-
await SessionRepo.delete({});
10+
await db.delete(chiiOsWebSessions).execute();
1011
});
1112

1213
afterEach(async () => {
13-
await SessionRepo.delete({});
14+
await db.delete(chiiOsWebSessions).execute();
1415
});
1516

1617
test('should create and get session', async () => {
@@ -19,7 +20,9 @@ test('should create and get session', async () => {
1920
regTime: DateTime.fromISO('2010-01-10 10:05:20').toUnixInteger(),
2021
});
2122

22-
const session = await SessionRepo.findOne({ where: { key: token } });
23+
const session = await db.query.chiiOsWebSessions.findFirst({
24+
where: op.eq(chiiOsWebSessions.key, token),
25+
});
2326

2427
expect(session).toBeDefined();
2528

@@ -35,7 +38,7 @@ test('should create and get session', async () => {
3538

3639
test('should revoke session', async () => {
3740
const token = 'fake-random-session-token';
38-
await SessionRepo.insert({
41+
await db.insert(chiiOsWebSessions).values({
3942
key: token,
4043
value: Buffer.from(''),
4144
userID: 0,
@@ -45,7 +48,9 @@ test('should revoke session', async () => {
4548

4649
await revoke(token);
4750

48-
const session = await SessionRepo.findOne({ where: { key: token } });
51+
const session = await db.query.chiiOsWebSessions.findFirst({
52+
where: op.eq(chiiOsWebSessions.key, token),
53+
});
4954

5055
expect(session).toBeDefined();
5156
});

lib/auth/session.ts

+14-7
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import type { CookieSerializeOptions } from '@fastify/cookie';
22
import { DateTime } from 'luxon';
33

4+
import { db, op } from '@app/drizzle/db.ts';
5+
import { chiiOsWebSessions } from '@app/drizzle/schema.ts';
46
import { TypedCache } from '@app/lib/cache.ts';
5-
import { SessionRepo } from '@app/lib/orm/index.ts';
67
import { randomBytes } from '@app/lib/utils/index.ts';
78

89
import type { IAuth } from './index.ts';
@@ -29,7 +30,7 @@ export async function create(user: { id: number; regTime: number }): Promise<str
2930
expired_at: now + 60 * 60 * 24 * 7,
3031
};
3132

32-
await SessionRepo.insert({
33+
await db.insert(chiiOsWebSessions).values({
3334
value: Buffer.from(JSON.stringify(value)),
3435
userID: user.id,
3536
createdAt: value.created_at,
@@ -53,21 +54,27 @@ export async function get(sessionID: string): Promise<IAuth | null> {
5354
return await auth.byUserID(cached.userID);
5455
}
5556

56-
const session = await SessionRepo.findOneBy({ key: sessionID });
57+
const session = await db.query.chiiOsWebSessions.findFirst({
58+
where: op.and(
59+
op.eq(chiiOsWebSessions.key, sessionID),
60+
op.gt(chiiOsWebSessions.expiredAt, DateTime.now().toUnixInteger()),
61+
),
62+
});
5763
if (!session) {
5864
return null;
5965
}
60-
if (session.expiredAt <= DateTime.now().toUnixInteger()) {
61-
return null;
62-
}
6366

6467
await sessionCache.set(sessionID, { userID: session.userID });
6568

6669
return await auth.byUserID(session.userID);
6770
}
6871

6972
export async function revoke(sessionID: string) {
70-
await SessionRepo.update({ key: sessionID }, { expiredAt: DateTime.now().toUnixInteger() });
73+
await db
74+
.update(chiiOsWebSessions)
75+
.set({ expiredAt: DateTime.now().toUnixInteger() })
76+
.where(op.eq(chiiOsWebSessions.key, sessionID))
77+
.execute();
7178

7279
await sessionCache.del(sessionID);
7380
}

lib/orm/index.ts

-3
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,7 @@ export const SubjectRevRepo = AppDataSource.getRepository(SubjectRev);
147147
export const SubjectInterestRepo = AppDataSource.getRepository(SubjectInterest);
148148

149149
export const AccessTokenRepo = AppDataSource.getRepository(OauthAccessTokens);
150-
export const AppRepo = AppDataSource.getRepository(App);
151150
export const OauthClientRepo = AppDataSource.getRepository(OauthClient);
152-
export const SessionRepo = AppDataSource.getRepository(WebSessions);
153151
export const UserGroupRepo = AppDataSource.getRepository(UserGroup);
154152

155153
export const NotifyRepo = AppDataSource.getRepository(Notify);
@@ -175,7 +173,6 @@ export const repo = {
175173
Person: PersonRepo,
176174
PersonSubjects: PersonSubjectsRepo,
177175
AccessToken: AccessTokenRepo,
178-
Session: SessionRepo,
179176
UserGroup: UserGroupRepo,
180177
Notify: NotifyRepo,
181178
NotifyField: NotifyFieldRepo,

routes/private/routes/login.test.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
import { afterEach, beforeEach, describe, expect, test } from 'vitest';
22

3+
import { db } from '@app/drizzle/db.ts';
4+
import { chiiOsWebSessions } from '@app/drizzle/schema.ts';
35
import * as session from '@app/lib/auth/session.ts';
4-
import { SessionRepo } from '@app/lib/orm/index.ts';
56
import redis from '@app/lib/redis.ts';
67
import { createServer } from '@app/lib/server.ts';
78

89
describe('login', () => {
910
beforeEach(async () => {
1011
await redis.flushdb('SYNC');
11-
await SessionRepo.createQueryBuilder().where('true').delete().execute();
12+
await db.delete(chiiOsWebSessions).execute();
1213
});
1314

1415
afterEach(async () => {
1516
await redis.flushdb('SYNC');
16-
await SessionRepo.createQueryBuilder().where('true').delete().execute();
17+
await db.delete(chiiOsWebSessions).execute();
1718
});
1819

1920
test('should failed on too many requests', async () => {

tests/rest/auth.test.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
import { afterEach, beforeEach, expect, test } from 'vitest';
22

3+
import { db } from '@app/drizzle/db.ts';
4+
import { chiiOsWebSessions } from '@app/drizzle/schema.ts';
35
import * as session from '@app/lib/auth/session.ts';
4-
import { SessionRepo } from '@app/lib/orm/index.ts';
56
import { createServer } from '@app/lib/server.ts';
67

78
const treeHoleUser = { id: 382951, nickname: '树洞酱', username: '382951' };
89
const fakeIP = 'fake-client-ip-should-not-fail';
910

1011
beforeEach(async () => {
11-
await SessionRepo.createQueryBuilder().where('true').delete().execute();
12+
await db.delete(chiiOsWebSessions).execute();
1213
});
1314

1415
afterEach(async () => {
15-
await SessionRepo.createQueryBuilder().where('true').delete().execute();
16+
await db.delete(chiiOsWebSessions).execute();
1617
});
1718

1819
test('should pass login/logout authorization flow', async () => {

0 commit comments

Comments
 (0)