Skip to content

Commit 86f6077

Browse files
committed
start rudimentary api key validation
1 parent 84ae992 commit 86f6077

File tree

6 files changed

+54
-9
lines changed

6 files changed

+54
-9
lines changed

services/src/auth/api-key.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export const checkApiKeyAccess = async (apiKey: string, project: string): Promise<boolean> => {
2+
//TODO implement
3+
return Promise.resolve(false)
4+
}

src/lib/server/request-utils.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { error } from '@sveltejs/kit'
2+
import type { z } from 'zod'
3+
4+
export const validateRequestBody = async <T>(req: Request, schema: z.ZodSchema<T>): Promise<T> => {
5+
const body = await req.json()
6+
const validationResult = schema.safeParse(body)
7+
if (!validationResult.success) {
8+
error(400, 'Invalid request')
9+
}
10+
return validationResult.data
11+
}

src/routes/(api)/api/[project]/[lang]/translations/+server.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
1+
import { validateRequestBody } from '$lib/server/request-utils'
2+
import { authorize } from '../../../api-utils'
3+
import { translationPOSTRequestSchema, type ProjectId } from '../../../api.model'
14
import type { RequestHandler } from './$types'
25

3-
export const POST: RequestHandler = ({ params }) => {
6+
export const POST: RequestHandler = async ({ params, request }) => {
7+
authorize(request, params.project as ProjectId)
8+
const newTranslations = validateRequestBody(request, translationPOSTRequestSchema)
49
return new Response(
5-
`getting POST for translations on project "${params.project}" and lang "${params.lang}"`
10+
`getting POST for translations on project "${params.project}" and lang "${params.lang}" with body "${JSON.stringify(newTranslations)}"`
611
)
712
}
813

9-
export const GET: RequestHandler = ({ params }) => {
14+
export const GET: RequestHandler = ({ params, request }) => {
15+
authorize(request, params.project as ProjectId)
1016
return new Response(
1117
`getting GET for translations on project "${params.project}" and lang "${params.lang}"`
1218
)
Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
1+
import { validateRequestBody } from '$lib/server/request-utils'
2+
import { authorize } from '../../api-utils'
3+
import { projectConfigPOSTRequestSchema, type ProjectId } from '../../api.model'
14
import type { RequestHandler } from './$types'
25

3-
export const POST: RequestHandler = ({ params }) => {
4-
return new Response(`getting post for config on project "${params.project}"`)
6+
export const POST: RequestHandler = async ({ params, request }) => {
7+
authorize(request, params.project as ProjectId)
8+
const config = await validateRequestBody(request, projectConfigPOSTRequestSchema)
9+
10+
return new Response(
11+
`getting post for config on project "${params.project}" with payload "${JSON.stringify(config)}"`
12+
)
513
}

src/routes/(api)/api/api-utils.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { checkApiKeyAccess } from 'services/auth/api-key'
2+
import type { ProjectId } from './api.model'
3+
import { error } from '@sveltejs/kit'
4+
5+
export const authorize = async (req: Request, project: ProjectId) => {
6+
const apiKey = req.headers.get('Authorization')
7+
if (!apiKey) {
8+
error(401, 'No API key provided in the Authorization header')
9+
}
10+
const hasAccess = await checkApiKeyAccess(apiKey, project)
11+
if (!hasAccess) {
12+
error(
13+
403,
14+
'The provided API key is invalid, the project does not exist, or the provided key does not grant access to the project'
15+
)
16+
}
17+
}

src/routes/(api)/api/api.model.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,14 @@ import { z } from 'zod'
33
const translationKeySchema = z.string().brand('translation-key')
44
export type TranslationKey = z.infer<typeof translationKeySchema>
55

6-
const translationLanguageSchema = z.string().brand('translation-language')
7-
export type TranslationLanguage = z.infer<typeof translationLanguageSchema>
8-
96
const translationValueSchema = z.string().brand('translation-value')
107
export type TranslationValue = z.infer<typeof translationValueSchema>
118

9+
const projectIdSchema = z.string().brand('project-id')
10+
export type ProjectId = z.infer<typeof projectIdSchema>
11+
1212
const addTranslationCommandSchema = z.object({
1313
key: translationKeySchema,
14-
lang: translationLanguageSchema,
1514
value: translationValueSchema
1615
})
1716
export type AddTranslationCommand = z.infer<typeof addTranslationCommandSchema>

0 commit comments

Comments
 (0)