Skip to content

Commit b339317

Browse files
committed
add project repo and tests
1 parent b0530cf commit b339317

File tree

5 files changed

+120
-34
lines changed

5 files changed

+120
-34
lines changed

pnpm-lock.yaml

Lines changed: 1 addition & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

services/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77
"kysely": "^0.27.3",
88
"pino": "^9.0.0",
99
"pino-pretty": "^11.0.0",
10+
"uuid": "^9.0.1",
1011
"zod": "^3.23.5"
1112
},
1213
"devDependencies": {
14+
"@types/uuid": "^9.0.8",
1315
"vite": "^5.2.11",
1416
"vitest": "^1.5.3"
1517
},
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import { beforeEach, describe, expect, it } from 'vitest'
2+
import { db } from '../db/database'
3+
import { runMigration } from '../db/database-migration-util'
4+
import { createProject } from '../project/project.repository'
5+
import type { ProjectId } from '../../../src/routes/(api)/api/api.model'
6+
import {
7+
createApiKey,
8+
deleteApiKey,
9+
getApiKeysForProject,
10+
projectHasKey
11+
} from './api-key.repository'
12+
13+
beforeEach(async () => {
14+
db.reset()
15+
await runMigration()
16+
})
17+
18+
describe('ApiKey Repository', () => {
19+
let projectId: ProjectId
20+
beforeEach(async () => {
21+
projectId = (await createProject({ name: 'demo project name' })).id as ProjectId
22+
})
23+
24+
describe('createApiKey', () => {
25+
it('should create an api key given an existing project', async () => {
26+
const result = await createApiKey(projectId)
27+
expect(result).toBeTruthy()
28+
expect(false).toBeFalsy()
29+
})
30+
})
31+
32+
describe('getApiKeysForProject', () => {
33+
it('should fetch all apiKeys for a given project', async () => {
34+
const key1 = await createApiKey(projectId)
35+
const key2 = await createApiKey(projectId)
36+
37+
const result = (await getApiKeysForProject(projectId)).map((it) => it.key)
38+
expect(result).toHaveLength(2)
39+
expect(result).includes(key1.key)
40+
expect(result).includes(key2.key)
41+
})
42+
43+
it('should no longer find deleted keys', async () => {
44+
const key = await createApiKey(projectId)
45+
46+
const keysBeforeDelete = await getApiKeysForProject(projectId)
47+
expect(keysBeforeDelete.map((it) => it.key)).toContain(key.key)
48+
49+
await deleteApiKey(projectId, key.key)
50+
const keysAfterDelete = await getApiKeysForProject(projectId)
51+
expect(keysAfterDelete.map((it) => it.key).includes(key.key)).toBe(false)
52+
})
53+
54+
it('should return an empty list in case the project does not exist', async () => {
55+
const keys = await getApiKeysForProject(projectId)
56+
expect(keys).toHaveLength(0)
57+
})
58+
59+
it('should return an empty list if there are no keys', async () => {
60+
const result = await getApiKeysForProject(projectId)
61+
expect(result).toHaveLength(0)
62+
})
63+
})
64+
65+
describe('projectHasKey', () => {
66+
it('should return true if there is a key for the project', async () => {
67+
const key = await createApiKey(projectId)
68+
const result = await projectHasKey(projectId, key.key)
69+
expect(result).toBe(true)
70+
})
71+
72+
it('should return false if the project does not have the corresponding key', async () => {
73+
const result = await projectHasKey(projectId, 'nonexiststant-id')
74+
expect(result).toBe(false)
75+
})
76+
77+
it('should return false if the project does not exist', async () => {
78+
const result = await projectHasKey(4242, 'nonexiststant-id')
79+
expect(result).toBe(false)
80+
})
81+
82+
it('should return false if key and project exist, but do not match', async () => {
83+
const otherProjectId = (await createProject({ name: 'another Project' })).id as ProjectId
84+
const key = await createApiKey(projectId)
85+
86+
const result = await projectHasKey(otherProjectId, key.key)
87+
expect(result).toBe(false)
88+
})
89+
})
90+
})

services/src/auth/api-key-service.test.ts

Whitespace-only changes.
Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,38 @@
11
import { db } from '../db/database'
22
import type { ApiKeyCreationParams, SelectableApiKey } from './api-key'
3+
import { v4 as uuid } from 'uuid'
34

45
export function createApiKey(projectId: number): Promise<SelectableApiKey> {
5-
const insertKey: ApiKeyCreationParams = {
6-
key: 'something',
7-
project_id: projectId
8-
}
9-
return db
10-
.insertInto('apikeys')
11-
.values(insertKey)
12-
.returningAll()
13-
.executeTakeFirstOrThrow(() => new Error('Error creating Api Access Key'))
6+
const insertKey: ApiKeyCreationParams = {
7+
key: uuid(),
8+
project_id: projectId
9+
}
10+
return db
11+
.insertInto('apikeys')
12+
.values(insertKey)
13+
.returningAll()
14+
.executeTakeFirstOrThrow(() => new Error('Error creating Api Access Key'))
1415
}
1516

1617
export function getApiKeysForProject(projectId: number): Promise<SelectableApiKey[]> {
17-
return db.selectFrom('apikeys').selectAll().where('project_id', '==', projectId).execute()
18+
return db.selectFrom('apikeys').selectAll().where('project_id', '==', projectId).execute()
1819
}
1920

2021
export async function projectHasKey(projectId: number, key: string): Promise<boolean> {
21-
const result = await db
22-
.selectFrom('apikeys')
23-
.where('project_id', '==', projectId)
24-
.where('key', '==', key)
25-
.execute()
26-
return !!result.length
22+
const result = await db
23+
.selectFrom('apikeys')
24+
.selectAll()
25+
.where('project_id', '==', projectId)
26+
.where('key', '==', key)
27+
.execute()
28+
29+
return !!result.length
30+
}
31+
32+
export async function deleteApiKey(projectId: number, key: string): Promise<void> {
33+
await db
34+
.deleteFrom('apikeys')
35+
.where('project_id', '==', projectId)
36+
.where('key', '==', key)
37+
.execute()
2738
}

0 commit comments

Comments
 (0)