Skip to content

Commit

Permalink
register
Browse files Browse the repository at this point in the history
  • Loading branch information
GroophyLifefor committed Jan 25, 2025
1 parent 58feb44 commit c199eae
Show file tree
Hide file tree
Showing 9 changed files with 260 additions and 179 deletions.
5 changes: 3 additions & 2 deletions api/Users/getUserInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,16 @@ export async function GET(ctx: Ctx) {

// Configurations
export const path = '/api/getUserInfo';
export const middlewares = ['auth:validToken'];

export const validation: ValidationType = {
query: {
userId: shouldBeUserId,
},
};
export const middlewares = ['auth:validToken'];

const querySchema = z.object(validation.query as z.ZodRawShape);
type QueryType = z.infer<typeof querySchema>;

export const openAPI: OpenAPIDoc = {
description: 'Get the user information',
tags: ['Users'],
Expand Down
148 changes: 148 additions & 0 deletions api/Users/register.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import { type Ctx, StatusCode, ValidationType } from '@/endpoints.ts';
import { z } from 'npm:zod';
import { OpenAPIDoc } from '@/lib/openAPI.types.ts';
import { Buffer } from 'node:buffer';
import { createNewUserIfNeeded, registerParams } from '@/db/models/Users.ts';

async function getDataFromGoogle(accessToken: string) {
const url = new URL('https://www.googleapis.com/oauth2/v3/userinfo');
url.searchParams.append('access_token', accessToken);

const response = await fetch(url.toString(), {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});

if (!response.ok) {
return {
isError: true,
status: 502,
message: 'Failed to get user data from Google',
};
}

const data = await response.json();
return {
isError: false,
data,
};
}

function parseJwt(token: string) {
return JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString());
}

function getDataFromApple(accessToken: string) {
const JWT = accessToken;
const decoded = parseJwt(JWT);

const email = decoded.email;

if (!email) {
return {
isError: true,
status: 400,
message: 'Failed to get email from Apple.',
};
}
const beforeAt = email.split('@')[0];
if (!beforeAt || beforeAt.length < 1) {
return {
isError: true,
status: 400,
message: 'Invalid email from Apple.',
};
}

const name = beforeAt;
const picture = '';

return {
isError: false,
data: {
email,
name,
picture,
},
};
}

export async function POST(ctx: Ctx) {
const requestData = ctx.get('dataValidation').user;
const body: BodyType = requestData.body;

const registerType: 'google' | 'apple' = body.registerType;
const accessToken = body.accessToken;

const data = await {
google: getDataFromGoogle,
apple: getDataFromApple,
}[registerType](accessToken);

if (data.isError) {
return await ctx.json(
{ message: data.message },
data.status as StatusCode
);
}

const requiredData: registerParams = {
registerType,
email: data.data.email,
name: data.data.name,
picture: data.data.picture,
};

const { token, type } = await createNewUserIfNeeded(ctx, requiredData);

return await ctx.json(
{
token,
type,
},
200
);
}

export const path = '/api/register';

export const validation: ValidationType = {
body: z.object({
registerType: z
.string()
.refine(
(v) => ['apple', 'google'].includes(v),
'Invalid registerType, must be "apple" or "google"'
),
accessToken: z.string(),
}),
};
type BodyType = z.infer<typeof validation.body>;

export const openAPI: OpenAPIDoc = {
description: 'Register the user',
tags: ['User'],
responses: {
200: {
type: 'application/json',
zodSchema: z.object({
token: z.string(),
type: z.string(),
}),
},
400: {
type: 'application/json',
zodSchema: z.object({
message: z.string(),
}),
},
502: {
type: 'application/json',
zodSchema: z.object({
message: z.string(),
}),
},
},
};
40 changes: 0 additions & 40 deletions api/noCommentTemplate.ts

This file was deleted.

115 changes: 38 additions & 77 deletions api/template.ts
Original file line number Diff line number Diff line change
@@ -1,97 +1,58 @@
import {
type ctx,
type MiddlewareDataArray,
getDataFromMiddleware,
SetResponse,
type Ctx,
ValidationType,
} from '@/endpoints.ts';
import { IUser } from '@/db/models/Users.ts';
import { z } from 'npm:zod';
import { shouldBeUserId } from '@/lib/userIdCheck.ts';
import { OpenAPIDoc } from "@/lib/openAPI.types.ts";

/**
* STEP 1: (OPTIONAL) Do this setting on
* If you using VSCode, enable 'editor.foldingImportsByDefault' to fold imports
* and get better DX.
*/

/**
* STEP 2: (REQUIRED) Endpoint path implementation
* Don't forget to add filepath to endpoints.ts's loadEndpoints function's return array.
* Because Deno Deploy don't allow dynamic imports cause of security reasons.
*/

/**
* STEP 3: (REQUIRED) Readability
* Don't want create a new file? Create it! Readability is most important thing.
* Split to multiple files if you need. Single Responsibility Principle is base rule.
*/

/**
* POST /api/postEvent
*
* What do: Post the event
*/
export function POST(ctx: ctx, _middlewareDatas: MiddlewareDataArray): void {
// .user means user so developer level which not base(library) level
const authData = getDataFromMiddleware(
_middlewareDatas,
'auth:validToken'
).user;
const user = authData as IUser;

const requestData = getDataFromMiddleware(
_middlewareDatas,
'dataValidation'
).user;
export async function GET(ctx: Ctx) {
const requestData = ctx.get('dataValidation').user
const query: QueryType = requestData.query;
const body: BodyType = requestData.body;

console.log('logging', query.eventId);
console.log('Another logging', body.name);
// middleware converts userId to User
const _targetUser = query.userId;
const _name: string = query.name;
const _log: string = body.log;

return SetResponse(ctx, {
status: 200,
body: {
username: user.username,
},
});
}

/**
* GET /api/postEvent
*
* What do: Get the event
*/
export function GET(ctx: ctx, _middlewareDatas: MiddlewareDataArray): void {
return SetResponse(ctx, {
status: 200,
body: {},
});
// ...
return await ctx.json({message: 'ok'}, 200);
}

// Configurations
export const pattern = new URLPattern({ pathname: '/api/postEvent' });
// ! REQUIRED CONFIGURATION BELOW
export const path = '/api/ENDPOINT';
// ! REQUIRED Endpoint path implementation
// * Don't forget to add filepath to endpoints.ts's loadEndpoints function's return array.
// * Because Deno Deploy don't allow dynamic imports cause of security reasons.
//// ////

// OPTIONAL CONFIGURATIONS BELOW
export const middlewares = ['auth:validToken'];

export const validation: ValidationType = {
// Please use for 'GET', 'DELETE', 'OPTIONS' or 'HEAD'
// /api/postEvent?test=anystring
query: {
eventId: z.string().min(4),
name: z.string().min(1),
userId: shouldBeUserId,
},

// Please use for 'POST', 'PUT' or 'PATCH'
// /api/postEvent
// {
// name: 'anystring',
// description: 'anystring',
// }
body: z.object({
name: z.string().min(5),
description: z.string().min(1),
}),
log: z.string().min(1),
})
};
export const middlewares = ['auth:validToken'];

const querySchema = z.object(validation.query as z.ZodRawShape);
type QueryType = z.infer<typeof querySchema>;
type BodyType = z.infer<typeof validation.body>;

export const openAPI: OpenAPIDoc = {
description: 'Description of the endpoint',
tags: ['Folder Name'],
responses: {
200: {
type: 'application/json',
zodSchema: z.object({
isError: z.boolean(),
message: z.string().optional(),
}),
},
},
}
Loading

0 comments on commit c199eae

Please sign in to comment.