This repository was archived by the owner on Sep 17, 2024. It is now read-only.
File tree Expand file tree Collapse file tree 8 files changed +53
-21
lines changed
migrations/20240501200641_init Expand file tree Collapse file tree 8 files changed +53
-21
lines changed Original file line number Diff line number Diff line change 11-- CreateTable
22CREATE TABLE "Token " (
33 " id" UUID NOT NULL ,
4- " token " TEXT NOT NULL ,
4+ " tokenHash " TEXT NOT NULL ,
55 " type" TEXT NOT NULL ,
66 " meta" JSONB NOT NULL ,
77 " trace" JSONB NOT NULL ,
@@ -13,4 +13,4 @@ CREATE TABLE "Token" (
1313);
1414
1515-- CreateIndex
16- CREATE UNIQUE INDEX "Token_token_key " ON " Token" (" token " );
16+ CREATE UNIQUE INDEX "Token_tokenHash_key " ON " Token" (" tokenHash " );
Original file line number Diff line number Diff line change @@ -5,7 +5,7 @@ datasource db {
55
66model Token {
77 id String @id @default (uuid () ) @db.Uuid
8- token String @unique
8+ tokenHash String @unique
99 type String
1010 meta Json
1111 trace Json
Original file line number Diff line number Diff line change 11import { ScriptContext } from "../_gen/scripts/create.ts" ;
2- import { TokenWithSecret } from "../utils/types.ts" ;
3- import { tokenFromRow } from "../utils/types.ts" ;
2+ import { TokenWithSecret , tokenFromRowWithSecret , hash } from "../utils/types.ts" ;
43
54export interface Request {
65 type : string ;
@@ -17,10 +16,9 @@ export async function run(
1716 req : Request ,
1817) : Promise < Response > {
1918 const tokenStr = generateToken ( req . type ) ;
20-
2119 const token = await ctx . db . token . create ( {
2220 data : {
23- token : tokenStr ,
21+ tokenHash : await hash ( tokenStr ) ,
2422 type : req . type ,
2523 meta : req . meta ,
2624 trace : ctx . trace ,
@@ -29,7 +27,7 @@ export async function run(
2927 } ) ;
3028
3129 return {
32- token : tokenFromRow ( token ) ,
30+ token : tokenFromRowWithSecret ( token , tokenStr ) ,
3331 } ;
3432}
3533
Original file line number Diff line number Diff line change 11import { ScriptContext } from "../_gen/scripts/extend.ts" ;
2- import { TokenWithSecret } from "../types/common.ts" ;
3- import { tokenFromRow } from "../types/common.ts" ;
2+ import { Token , tokenFromRow } from "../utils/types.ts" ;
43
54export interface Request {
65 token : string ;
76 newExpiration : string | null ;
87}
98
109export interface Response {
11- token : TokenWithSecret ;
10+ token : Token ;
1211}
1312
1413export async function run (
Original file line number Diff line number Diff line change 11import { ScriptContext } from "../_gen/scripts/get.ts" ;
2- import { Token } from "../utils/types.ts" ;
3- import { tokenFromRow } from "../utils/types.ts" ;
2+ import { Token , tokenFromRow } from "../utils/types.ts" ;
43
54export interface Request {
65 tokenIds : string [ ] ;
@@ -23,7 +22,7 @@ export async function run(
2322 } ,
2423 } ) ;
2524
26- const tokens = rows . map ( tokenFromRow ) ;
25+ const tokens = rows . map ( row => tokenFromRow ( row ) ) ;
2726
2827 return { tokens } ;
2928}
Original file line number Diff line number Diff line change 11import { ScriptContext } from "../_gen/scripts/get_by_token.ts" ;
2- import { Token , tokenFromRow } from "../utils/types.ts" ;
2+ import { Token , tokenFromRowWithSecret , hash } from "../utils/types.ts" ;
33
44export interface Request {
55 tokens : string [ ] ;
@@ -13,18 +13,22 @@ export async function run(
1313 ctx : ScriptContext ,
1414 req : Request ,
1515) : Promise < Response > {
16+ const hashed = await Promise . all ( req . tokens . map ( hash ) ) ;
17+ console . log ( hashed ) ;
1618 const rows = await ctx . db . token . findMany ( {
1719 where : {
18- token : {
19- in : req . tokens ,
20+ tokenHash : {
21+ in : hashed ,
2022 } ,
2123 } ,
2224 orderBy : {
2325 createdAt : "desc" ,
2426 } ,
2527 } ) ;
2628
27- const tokens = rows . map ( tokenFromRow ) ;
29+ // Map from the hashed secrets to the original secrets
30+ const hashMap = Object . fromEntries ( req . tokens . map ( ( token , i ) => [ hashed [ i ] , token ] ) ) ;
31+ const tokens = rows . map ( row => tokenFromRowWithSecret ( row , hashMap [ row . tokenHash ] ) ) ;
2832
2933 return { tokens } ;
3034}
Original file line number Diff line number Diff line change 2323 meta : { foo : "bar" } ,
2424 } ) ;
2525
26- await ctx . modules . tokens . revoke ( { tokenIds : [ token . id ] } ) ;
26+ const { updates } = await ctx . modules . tokens . revoke ( { tokenIds : [ token . id ] } ) ;
27+ assertEquals ( updates [ token . id ] , "REVOKED" ) ;
2728
2829 const error = await assertRejects ( async ( ) => {
2930 await ctx . modules . tokens . validate ( { token : token . token } ) ;
Original file line number Diff line number Diff line change @@ -13,13 +13,44 @@ export interface TokenWithSecret extends Token {
1313 token : string ;
1414}
1515
16- export function tokenFromRow (
16+
17+ export function withoutKeys < T extends object , K extends keyof T > (
18+ obj : T ,
19+ keys : K [ ]
20+ ) : Omit < T , K > {
21+ const copy = { ...obj } ;
22+ for ( const key of keys ) {
23+ delete copy [ key ] ;
24+ }
25+ return copy ;
26+ }
27+
28+ export function tokenFromRowWithSecret (
1729 row : prisma . Prisma . TokenGetPayload < any > ,
30+ origToken : string
1831) : TokenWithSecret {
1932 return {
20- ...row ,
33+ ...tokenFromRow ( row ) ,
34+ token : origToken ,
35+ }
36+ }
37+
38+ export function tokenFromRow (
39+ row : prisma . Prisma . TokenGetPayload < any > ,
40+ ) : Token {
41+ return {
42+ ...withoutKeys ( row , [ "tokenHash" ] ) ,
2143 createdAt : row . createdAt . toISOString ( ) ,
2244 expireAt : row . expireAt ?. toISOString ( ) ?? null ,
2345 revokedAt : row . revokedAt ?. toISOString ( ) ?? null ,
2446 } ;
2547}
48+
49+ export async function hash ( token : string ) : Promise < string > {
50+ const encoder = new TextEncoder ( ) ;
51+ const data = encoder . encode ( token ) ;
52+ const hash = await crypto . subtle . digest ( "SHA-256" , data ) ;
53+ const digest = Array . from ( new Uint8Array ( hash ) ) ;
54+ const strDigest = digest . map ( b => b . toString ( 16 ) . padStart ( 2 , "0" ) ) . join ( "" ) ;
55+ return strDigest ;
56+ }
You can’t perform that action at this time.
0 commit comments