95 lines
2.3 KiB
TypeScript
95 lines
2.3 KiB
TypeScript
import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
|
|
import { env } from "hono/adapter";
|
|
import mapKeys from "lodash.mapkeys";
|
|
|
|
import { Case, changeStringCase } from "~/libs/changeStringCase";
|
|
import type { AdminSdkCredentials } from "~/libs/fcm/getGoogleAuthToken";
|
|
import { verifyFcmToken } from "~/libs/fcm/verifyFcmToken";
|
|
import { readEnvVariable } from "~/libs/readEnvVariable";
|
|
import { saveToken } from "~/models/token";
|
|
import type { Env } from "~/types/env";
|
|
import {
|
|
ErrorResponse,
|
|
ErrorResponseSchema,
|
|
SuccessResponse,
|
|
SuccessResponseSchema,
|
|
} from "~/types/schema";
|
|
|
|
const app = new OpenAPIHono<Env>();
|
|
|
|
const SaveTokenRequest = z.object({
|
|
token: z.string(),
|
|
deviceId: z.string(),
|
|
});
|
|
|
|
const SaveTokenResponse = SuccessResponseSchema();
|
|
|
|
const route = createRoute({
|
|
tags: ["aniplay", "notifications"],
|
|
operationId: "saveToken",
|
|
summary: "Saves FCM token",
|
|
method: "post",
|
|
path: "/",
|
|
request: {
|
|
body: {
|
|
content: {
|
|
"application/json": {
|
|
schema: SaveTokenRequest,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
responses: {
|
|
200: {
|
|
content: {
|
|
"application/json": {
|
|
schema: SaveTokenResponse,
|
|
},
|
|
},
|
|
description: "Saved token successfully",
|
|
},
|
|
412: {
|
|
content: {
|
|
"application/json": {
|
|
schema: ErrorResponseSchema,
|
|
},
|
|
},
|
|
description: "Token already exists",
|
|
},
|
|
500: {
|
|
content: {
|
|
"application/json": {
|
|
schema: ErrorResponseSchema,
|
|
},
|
|
},
|
|
description: "Unknown error occurred",
|
|
},
|
|
},
|
|
});
|
|
|
|
app.openapi(route, async (c) => {
|
|
const { token, deviceId } = await c.req.json<typeof SaveTokenRequest._type>();
|
|
|
|
try {
|
|
const isValidToken = await verifyFcmToken(
|
|
token,
|
|
mapKeys(
|
|
readEnvVariable<AdminSdkCredentials>(c.env, "ADMIN_SDK_JSON"),
|
|
(_, key) => changeStringCase(key, Case.snake_case, Case.camelCase),
|
|
) as unknown as AdminSdkCredentials,
|
|
);
|
|
if (!isValidToken) {
|
|
return c.json(ErrorResponse, 401);
|
|
}
|
|
|
|
await saveToken(env(c, "workerd"), deviceId, token);
|
|
} catch (error) {
|
|
console.error(new Error("Failed to save token", { cause: error }));
|
|
return c.json(ErrorResponse, 500);
|
|
}
|
|
|
|
return c.json(SuccessResponse);
|
|
});
|
|
|
|
export default app;
|