refactor #26
@ -10,9 +10,8 @@ export interface ClientInfoHeader {
|
|||||||
ip: string;
|
ip: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getUserHeaderInformation = (ctx: Context): UserHeaderInformation => {
|
export const getUserHeaderInformation = (clientInfo: string): UserHeaderInformation => {
|
||||||
const clientInfoHeader =
|
const clientInfoHeader = (JSON.parse(clientInfo) as ClientInfoHeader) ?? ("unknown" as string);
|
||||||
(JSON.parse(ctx.request.headers.get("x-client-info") as string) as ClientInfoHeader) ?? ("unknown" as string);
|
|
||||||
|
|
||||||
const userHeaderInformation = {
|
const userHeaderInformation = {
|
||||||
ip: clientInfoHeader.ip ?? "unknown",
|
ip: clientInfoHeader.ip ?? "unknown",
|
||||||
|
|||||||
@ -1,14 +1,17 @@
|
|||||||
import { Context } from "elysia";
|
import { Context, Static } from "elysia";
|
||||||
import { returnWriteResponse } from "../../../helpers/callback/httpResponse";
|
import { returnWriteResponse } from "../../../helpers/callback/httpResponse";
|
||||||
import { githubCallbackService } from "../services/http/githubCallback.service";
|
import { githubCallbackService } from "../services/http/githubCallback.service";
|
||||||
import { mainErrorHandler } from "../../../helpers/error/handler";
|
import { mainErrorHandler } from "../../../helpers/error/handler";
|
||||||
import { getUserHeaderInformation } from "../../../helpers/http/userHeader/getUserHeaderInformation";
|
import { getUserHeaderInformation } from "../../../helpers/http/userHeader/getUserHeaderInformation";
|
||||||
|
import { githubCallbackSchema } from "../schemas/githubCallback.schema";
|
||||||
|
|
||||||
export const githubCallbackController = async (
|
export const githubCallbackController = async (ctx: {
|
||||||
ctx: Context & { query: { code: string; callbackURI: string } }
|
set: Context["set"];
|
||||||
) => {
|
query: Static<typeof githubCallbackSchema.query>;
|
||||||
|
headers: Static<typeof githubCallbackSchema.headers>;
|
||||||
|
}) => {
|
||||||
try {
|
try {
|
||||||
const userHeaderInfo = getUserHeaderInformation(ctx);
|
const userHeaderInfo = getUserHeaderInformation(ctx.headers["x-client-info"]);
|
||||||
|
|
||||||
const authToken = await githubCallbackService(ctx.query, userHeaderInfo);
|
const authToken = await githubCallbackService(ctx.query, userHeaderInfo);
|
||||||
return returnWriteResponse(ctx.set, 200, "Authenticated successfully!", {
|
return returnWriteResponse(ctx.set, 200, "Authenticated successfully!", {
|
||||||
|
|||||||
@ -1,21 +1,18 @@
|
|||||||
import { Context } from "elysia";
|
import { Context, Static } from "elysia";
|
||||||
import { returnReadResponse } from "../../../helpers/callback/httpResponse";
|
import { returnReadResponse } from "../../../helpers/callback/httpResponse";
|
||||||
import { githubRequestService } from "../services/http/githubRequest.service";
|
import { githubRequestService } from "../services/http/githubRequest.service";
|
||||||
import { mainErrorHandler } from "../../../helpers/error/handler";
|
import { mainErrorHandler } from "../../../helpers/error/handler";
|
||||||
|
import { githubRequestSchema } from "../schemas/githubRequest.schema";
|
||||||
|
|
||||||
export const githubRequestController = async (
|
export const githubRequestController = async (ctx: {
|
||||||
ctx: Context & { query: { callback?: string } },
|
set: Context["set"];
|
||||||
) => {
|
query: Static<typeof githubRequestSchema.query>;
|
||||||
|
}) => {
|
||||||
try {
|
try {
|
||||||
const loginUrl = await githubRequestService(ctx.query.callback);
|
const loginUrl = await githubRequestService(ctx.query.callback);
|
||||||
return returnReadResponse(
|
return returnReadResponse(ctx.set, 200, "GitHub login URL created successfully.", {
|
||||||
ctx.set,
|
endpointUrl: loginUrl,
|
||||||
200,
|
});
|
||||||
"Login URL generated successfully",
|
|
||||||
{
|
|
||||||
endpointUrl: loginUrl,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return mainErrorHandler(ctx.set, error);
|
return mainErrorHandler(ctx.set, error);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,17 +1,20 @@
|
|||||||
import { Context } from "elysia";
|
import { Context, Static } from "elysia";
|
||||||
import { returnReadResponse } from "../../../helpers/callback/httpResponse";
|
import { returnReadResponse } from "../../../helpers/callback/httpResponse";
|
||||||
import { mainErrorHandler } from "../../../helpers/error/handler";
|
import { mainErrorHandler } from "../../../helpers/error/handler";
|
||||||
import { googleCallbackService } from "../services/http/googleCallback.service";
|
import { googleCallbackService } from "../services/http/googleCallback.service";
|
||||||
import { getUserHeaderInformation } from "../../../helpers/http/userHeader/getUserHeaderInformation";
|
import { getUserHeaderInformation } from "../../../helpers/http/userHeader/getUserHeaderInformation";
|
||||||
|
import { googleCallbackSchema } from "../schemas/googleCallback.schema";
|
||||||
|
|
||||||
export const googleCallbackController = async (
|
export const googleCallbackController = async (ctx: {
|
||||||
ctx: Context & { query: { code: string; state: string; callbackURI: string } },
|
set: Context["set"];
|
||||||
) => {
|
query: Static<typeof googleCallbackSchema.query>;
|
||||||
|
headers: Static<typeof googleCallbackSchema.headers>;
|
||||||
|
}) => {
|
||||||
try {
|
try {
|
||||||
const userHeaderInfo = getUserHeaderInformation(ctx);
|
const userHeaderInfo = getUserHeaderInformation(ctx.headers["x-client-info"]);
|
||||||
|
|
||||||
const authToken = await googleCallbackService(ctx.query, userHeaderInfo);
|
const authToken = await googleCallbackService(ctx.query, userHeaderInfo);
|
||||||
return returnReadResponse(ctx.set, 200, "Authenticated successfully!", {
|
return returnReadResponse(ctx.set, 200, "Authentication successful!", {
|
||||||
authToken,
|
authToken,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@ -12,6 +12,9 @@ import { getOauthProvidersSchema } from "./schemas/getOauthProviders.schema";
|
|||||||
import { getCallbackProviderUrlSchema } from "./schemas/getCallbackProviderUrl.schema";
|
import { getCallbackProviderUrlSchema } from "./schemas/getCallbackProviderUrl.schema";
|
||||||
import { googleRequestSchema } from "./schemas/googleRequest.schema";
|
import { googleRequestSchema } from "./schemas/googleRequest.schema";
|
||||||
import { googleCallbackSchema } from "./schemas/googleCallback.schema";
|
import { googleCallbackSchema } from "./schemas/googleCallback.schema";
|
||||||
|
import { githubRequestSchema } from "./schemas/githubRequest.schema";
|
||||||
|
import { githubCallbackSchema } from "./schemas/githubCallback.schema";
|
||||||
|
import { logoutSchema } from "./schemas/logout.schema";
|
||||||
|
|
||||||
export const authModule = new Elysia({ prefix: "/auth", tags: ["Authentication"] })
|
export const authModule = new Elysia({ prefix: "/auth", tags: ["Authentication"] })
|
||||||
.post("/token/validate", tokenValidationController, tokenValidationSchema)
|
.post("/token/validate", tokenValidationController, tokenValidationSchema)
|
||||||
@ -19,6 +22,6 @@ export const authModule = new Elysia({ prefix: "/auth", tags: ["Authentication"]
|
|||||||
.get("/providers/:name/callback", getCallbackProviderUrlController, getCallbackProviderUrlSchema)
|
.get("/providers/:name/callback", getCallbackProviderUrlController, getCallbackProviderUrlSchema)
|
||||||
.get("/google", googleRequestController, googleRequestSchema)
|
.get("/google", googleRequestController, googleRequestSchema)
|
||||||
.get("/google/callback", googleCallbackController, googleCallbackSchema)
|
.get("/google/callback", googleCallbackController, googleCallbackSchema)
|
||||||
.get("/github", githubRequestController)
|
.get("/github", githubRequestController, githubRequestSchema)
|
||||||
.get("/github/callback", githubCallbackController)
|
.get("/github/callback", githubCallbackController, githubCallbackSchema)
|
||||||
.post("/logout", logoutController);
|
.post("/logout", logoutController, logoutSchema);
|
||||||
|
|||||||
57
src/modules/auth/schemas/githubCallback.schema.ts
Normal file
57
src/modules/auth/schemas/githubCallback.schema.ts
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import { t } from "elysia";
|
||||||
|
import { AppRouteSchema } from "../../../helpers/types/AppRouteSchema";
|
||||||
|
|
||||||
|
export const githubCallbackSchema = {
|
||||||
|
headers: t.Object({
|
||||||
|
"x-client-info": t.String({
|
||||||
|
examples: [
|
||||||
|
'{"os":"Windows","osVersion":"10","browser":"Chrome","browserVersion":"89.0.4389.82","deviceType":"Desktop","ip":"192.168.1.1"}',
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
query: t.Object({
|
||||||
|
code: t.String({ examples: ["4/0AY0e-xxxxxxxxx"] }),
|
||||||
|
callbackURI: t.String({ examples: ["https://example.com/auth/github/callback"] }),
|
||||||
|
}),
|
||||||
|
detail: {
|
||||||
|
summary: "GitHub OAuth callback endpoint",
|
||||||
|
description:
|
||||||
|
"Handles the callback from GitHub OAuth and processes the authentication response. This endpoint also processes the account provisioning if the user is logging in for the first time.",
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
description: "Authentication successful",
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
schema: {
|
||||||
|
type: "object",
|
||||||
|
properties: {
|
||||||
|
success: {
|
||||||
|
type: "boolean",
|
||||||
|
example: true,
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
type: "number",
|
||||||
|
example: 200,
|
||||||
|
},
|
||||||
|
message: {
|
||||||
|
type: "string",
|
||||||
|
example: "Authentication successful",
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
type: "object",
|
||||||
|
properties: {
|
||||||
|
authToken: {
|
||||||
|
type: "string",
|
||||||
|
description: "JWT token for authenticated user",
|
||||||
|
example: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} satisfies AppRouteSchema;
|
||||||
54
src/modules/auth/schemas/githubRequest.schema.ts
Normal file
54
src/modules/auth/schemas/githubRequest.schema.ts
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import { t } from "elysia";
|
||||||
|
import { AppRouteSchema } from "../../../helpers/types/AppRouteSchema";
|
||||||
|
|
||||||
|
export const githubRequestSchema = {
|
||||||
|
query: t.Object({
|
||||||
|
callback: t.Optional(
|
||||||
|
t.String({
|
||||||
|
description: "The callback URL to redirect after GitHub authentication. It should be URL-encoded if provided.",
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
detail: {
|
||||||
|
summary: "Initiate GitHub OAuth flow",
|
||||||
|
description:
|
||||||
|
"This endpoint initiates the GitHub OAuth flow by redirecting the user to GitHub's authentication page.",
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
description: "GitHub login URL created successfully.",
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
schema: {
|
||||||
|
type: "object",
|
||||||
|
properties: {
|
||||||
|
success: {
|
||||||
|
type: "boolean",
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
type: "number",
|
||||||
|
default: 200,
|
||||||
|
},
|
||||||
|
message: {
|
||||||
|
type: "string",
|
||||||
|
default: "GitHub login URL created successfully.",
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
type: "object",
|
||||||
|
properties: {
|
||||||
|
endpointUrl: {
|
||||||
|
type: "string",
|
||||||
|
description: "The URL to redirect the user for GitHub authentication.",
|
||||||
|
example:
|
||||||
|
"https://github.com/login/oauth/authorize?client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI&response_type=code&scope=user:email",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} satisfies AppRouteSchema;
|
||||||
97
src/modules/auth/schemas/logout.schema.ts
Normal file
97
src/modules/auth/schemas/logout.schema.ts
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
import { AppRouteSchema } from "../../../helpers/types/AppRouteSchema";
|
||||||
|
|
||||||
|
export const logoutSchema = {
|
||||||
|
detail: {
|
||||||
|
summary: "Logout endpoint",
|
||||||
|
description: "Logs out the authenticated user by invalidating their session or token.",
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
description: "Logout successful",
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
schema: {
|
||||||
|
type: "object",
|
||||||
|
properties: {
|
||||||
|
success: {
|
||||||
|
type: "boolean",
|
||||||
|
example: true,
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
type: "number",
|
||||||
|
example: 200,
|
||||||
|
},
|
||||||
|
message: {
|
||||||
|
type: "string",
|
||||||
|
example: "Logout successful",
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
type: "object",
|
||||||
|
description: "Details about the logout operation. This only returned in development environment.",
|
||||||
|
properties: {
|
||||||
|
id: {
|
||||||
|
type: "string",
|
||||||
|
example: "123e4567-e89b-12d3-a456-426614174000",
|
||||||
|
},
|
||||||
|
isAuthenticated: {
|
||||||
|
type: "boolean",
|
||||||
|
example: false,
|
||||||
|
},
|
||||||
|
validUntil: {
|
||||||
|
type: "string",
|
||||||
|
format: "date-time",
|
||||||
|
example: "2024-12-31T23:59:59Z",
|
||||||
|
},
|
||||||
|
userId: {
|
||||||
|
type: "string",
|
||||||
|
example: "user_12345",
|
||||||
|
},
|
||||||
|
deletedAt: {
|
||||||
|
type: "string",
|
||||||
|
format: "date-time",
|
||||||
|
example: "2024-01-02T12:00:00Z",
|
||||||
|
},
|
||||||
|
createdAt: {
|
||||||
|
type: "string",
|
||||||
|
format: "date-time",
|
||||||
|
example: "2024-01-01T12:00:00Z",
|
||||||
|
},
|
||||||
|
updatedAt: {
|
||||||
|
type: "string",
|
||||||
|
format: "date-time",
|
||||||
|
example: "2024-01-02T12:00:00Z",
|
||||||
|
},
|
||||||
|
deviceType: {
|
||||||
|
type: "string",
|
||||||
|
example: "Desktop",
|
||||||
|
},
|
||||||
|
deviceOs: {
|
||||||
|
type: "string",
|
||||||
|
example: "Windows 10",
|
||||||
|
},
|
||||||
|
deviceIp: {
|
||||||
|
type: "string",
|
||||||
|
example: "192.168.1.1",
|
||||||
|
},
|
||||||
|
browser: {
|
||||||
|
type: "string",
|
||||||
|
example: "Chrome 89.0.4389.82",
|
||||||
|
},
|
||||||
|
isOnline: {
|
||||||
|
type: "boolean",
|
||||||
|
example: false,
|
||||||
|
},
|
||||||
|
lastOnline: {
|
||||||
|
type: "string",
|
||||||
|
format: "date-time",
|
||||||
|
example: "2024-01-02T12:00:00Z",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} satisfies AppRouteSchema;
|
||||||
Reference in New Issue
Block a user