Skip to content

Commit

Permalink
Merge pull request #277 from chingu-x/refactor/auth-architecture-pt2
Browse files Browse the repository at this point in the history
Refactor/auth architecture pt2
  • Loading branch information
Dan-Y-Ko authored Oct 25, 2024
2 parents 8d79eb4 + 80c8ba3 commit b2ca4ab
Show file tree
Hide file tree
Showing 13 changed files with 93 additions and 34 deletions.
8 changes: 4 additions & 4 deletions src/app/(auth)/AuthProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { useEffect } from "react";
import { formatInTimeZone } from "date-fns-tz";
import { clientSignIn, clientSignOut } from "@/store/features/auth/authSlice";
import { clientSignIn } from "@/store/features/auth/authSlice";
import { useAppDispatch } from "@/store/hooks";
import { type User, getUserState } from "@/store/features/user/userSlice";
import { type AppError } from "@/types/types";
Expand Down Expand Up @@ -34,9 +34,9 @@ export default function AuthProvider({ user, error }: AuthProviderProps) {
dispatch(getUserState(userWithDate));
}

if (error) {
dispatch(clientSignOut());
}
// if (error) {
// dispatch(clientSignOut());
// }
}, [dispatch, user, error]);

return null;
Expand Down
3 changes: 2 additions & 1 deletion src/app/(auth)/sign-in/components/SignInFormContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { validateTextInput } from "@/utils/form/validateInput";
import { clientSignIn } from "@/store/features/auth/authSlice";
import { useAppDispatch } from "@/store/hooks";
import routePaths from "@/utils/routePaths";
import { type AuthClientAdapter } from "@/app/(auth)/_adapters/authClientAdapter";
import { type AuthClientAdapter } from "@/modules/auth/adapters/primary/authClientAdapter";
import { TYPES } from "@/di/types";
import { resolve } from "@/di/resolver";

Expand Down Expand Up @@ -48,6 +48,7 @@ function SignInFormContainer({
resolver: zodResolver(validationSchema),
});

// TODO: update error handling
const onSubmit: SubmitHandler<ValidationSchema> = async (data) => {
const { email, password } = data;
const authAdapter = resolve<AuthClientAdapter>(TYPES.AuthClientAdapter);
Expand Down
43 changes: 28 additions & 15 deletions src/components/navbar/DropDown.tsx
Original file line number Diff line number Diff line change
@@ -1,44 +1,57 @@
"use client";

import "reflect-metadata";
import { ChevronDownIcon } from "@heroicons/react/24/outline";
import Link from "next/link";
import { useRouter } from "next/navigation";
import Button from "@/components/Button";
import { useAppDispatch, useUser } from "@/store/hooks";
import { clientSignOut } from "@/store/features/auth/authSlice";
import { serverSignOut } from "@/app/(auth)/authService";
import { onOpenModal } from "@/store/features/modal/modalSlice";
import { TYPES } from "@/di/types";
import { resolve } from "@/di/resolver";
import { type AuthClientAdapter } from "@/modules/auth/adapters/primary/authClientAdapter";
import routePaths from "@/utils/routePaths";

export default function DropDown({ openState }: { openState?: boolean }) {
const router = useRouter();
const dispatch = useAppDispatch();
const allVoyages = useUser().voyageTeamMembers;
const activeVoyage = allVoyages?.find(
(item) => item.voyageTeam.voyage.status.name === "Active",
);

const currentVoyage = activeVoyage?.voyageTeam.name
? `Team - Tier ${activeVoyage.voyageTeam.name
let currentVoyage;

if (activeVoyage?.voyageTeam.name) {
currentVoyage = `Team - Tier ${activeVoyage.voyageTeam.name
.split("-")[1]
.split("tier")[1]
.toUpperCase()} ${activeVoyage.voyageTeam.name
.split("-")[0]
.toUpperCase()}`
: "Please join a voyage to see your status information.";
.toUpperCase()}`;
} else {
currentVoyage = "Please join a voyage to see your status information.";
}
const closed = "hidden";
const open =
"absolute flex flex-col gap-5 z-[1] w-[250px] p-5 bottom-100 translate-y-[15%] shadow-md bg-base-200 right-0 border border-base-100 rounded-2xl";

// TODO: update error handling
async function handleClick() {
const [res, error] = await serverSignOut();
const authAdapter = resolve<AuthClientAdapter>(TYPES.AuthClientAdapter);

if (res) {
dispatch(clientSignOut());
}
await authAdapter.logout();
dispatch(clientSignOut());
router.replace(routePaths.signIn());
// if (res) {
// dispatch(clientSignOut());
// }

if (error) {
dispatch(
onOpenModal({ type: "error", content: { message: error.message } }),
);
}
// if (error) {
// dispatch(
// onOpenModal({ type: "error", content: { message: error.message } }),
// );
// }
}

const handleDropDownClick = (event: React.MouseEvent<HTMLDivElement>) => {
Expand Down
4 changes: 3 additions & 1 deletion src/di/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import { container } from "tsyringe";
import { TYPES } from "./types";
import { AuthApiAdapter } from "@/modules/auth/adapters/secondary/authApiAdapter";
import { AxiosAdapter } from "@/modules/restApi/adapters/secondary/AxiosAdapter";
import { AuthClientAdapter } from "@/app/(auth)/_adapters/authClientAdapter";
import { AuthClientAdapter } from "@/modules/auth/adapters/primary/authClientAdapter";
import { LoginUsecase } from "@/modules/auth/application/usecases/loginUsecase";
import { LogoutUsecase } from "@/modules/auth/application/usecases/logoutUsecase";

container.register(TYPES.RestApiPort, { useClass: AxiosAdapter });
container.register(TYPES.AuthApiPort, { useClass: AuthApiAdapter });
container.register(TYPES.LoginUsecase, { useClass: LoginUsecase });
container.register(TYPES.LogoutUsecase, { useClass: LogoutUsecase });
container.register(TYPES.AuthClientAdapter, { useClass: AuthClientAdapter });

export default container;
1 change: 1 addition & 0 deletions src/di/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ export const TYPES = {

/* UseCases */
LoginUsecase: Symbol.for("LoginUsecase"),
LogoutUsecase: Symbol.for("LogoutUsecase"),
};
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { inject, injectable } from "tsyringe";
import { type LoginRequestDto } from "@/modules/auth/application/dtos/request.dto";
import { type LoginResponseDto } from "@/modules/auth/application/dtos/response.dto";
import { LoginUsecase } from "@/modules/auth/application/usecases/loginUsecase";
import type {
LogoutResponseDto,
LoginResponseDto,
} from "@/modules/auth/application/dtos/response.dto";
import { type LoginUsecase } from "@/modules/auth/application/usecases/loginUsecase";
import { type LogoutUsecase } from "@/modules/auth/application/usecases/logoutUsecase";
import { type AuthClientPort } from "@/modules/auth/ports/primary/authClientPort";
import { TYPES } from "@/di/types";

Expand All @@ -10,9 +14,16 @@ export class AuthClientAdapter implements AuthClientPort {
constructor(
@inject(TYPES.LoginUsecase)
private readonly loginUsecase: LoginUsecase,

@inject(TYPES.LogoutUsecase)
private readonly logoutUsecase: LogoutUsecase,
) {}

async login({ email, password }: LoginRequestDto): Promise<LoginResponseDto> {
return await this.loginUsecase.execute({ email, password });
}

async logout(): Promise<LogoutResponseDto> {
return await this.logoutUsecase.execute();
}
}
11 changes: 10 additions & 1 deletion src/modules/auth/adapters/secondary/authApiAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import { TYPES } from "@/di/types";
import { type AuthApiPort } from "@/modules/auth/ports/secondary/authApiPort";
import { type RestApiPort } from "@/modules/restApi/ports/secondary/restApiPort";
import { type LoginRequestDto } from "@/modules/auth/application/dtos/request.dto";
import { type LoginResponseDto } from "@/modules/auth/application/dtos/response.dto";
import type {
LogoutResponseDto,
LoginResponseDto,
} from "@/modules/auth/application/dtos/response.dto";
import { AuthUrls } from "@/modules/auth/application/constants/authUrls";

@injectable()
Expand All @@ -19,4 +22,10 @@ export class AuthApiAdapter implements AuthApiPort {
payload: { email, password },
});
}

async logout(): Promise<LogoutResponseDto> {
return await this.apiClient.post({
url: AuthUrls.logout,
});
}
}
1 change: 1 addition & 0 deletions src/modules/auth/application/constants/authUrls.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export const AuthUrls = {
login: "/api/v1/auth/login",
logout: "/api/v1/auth/logout",
} as const;
16 changes: 16 additions & 0 deletions src/modules/auth/application/usecases/logoutUsecase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { inject, injectable } from "tsyringe";
import { TYPES } from "@/di/types";
import { type AuthApiPort } from "@/modules/auth/ports/secondary/authApiPort";
import { type LogoutResponseDto } from "@/modules/auth/application/dtos/response.dto";

@injectable()
export class LogoutUsecase {
constructor(
@inject(TYPES.AuthApiPort)
private readonly authApi: AuthApiPort,
) {}

async execute(): Promise<LogoutResponseDto> {
return await this.authApi.logout();
}
}
6 changes: 5 additions & 1 deletion src/modules/auth/ports/primary/authClientPort.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { type LoginRequestDto } from "@/modules/auth/application/dtos/request.dto";
import { type LoginResponseDto } from "@/modules/auth/application/dtos/response.dto";
import type {
LogoutResponseDto,
LoginResponseDto,
} from "@/modules/auth/application/dtos/response.dto";

export interface AuthClientPort {
login: (props: LoginRequestDto) => Promise<LoginResponseDto>;
logout: () => Promise<LogoutResponseDto>;
}
6 changes: 5 additions & 1 deletion src/modules/auth/ports/secondary/authApiPort.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { type LoginRequestDto } from "@/modules/auth/application/dtos/request.dto";
import { type LoginResponseDto } from "@/modules/auth/application/dtos/response.dto";
import type {
LogoutResponseDto,
LoginResponseDto,
} from "@/modules/auth/application/dtos/response.dto";

export interface AuthApiPort {
login: ({ email, password }: LoginRequestDto) => Promise<LoginResponseDto>;
logout: () => Promise<LogoutResponseDto>;
}
10 changes: 5 additions & 5 deletions src/modules/restApi/ports/secondary/restApiPort.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import type {
} from "@/modules/restApi/application/entities/restApiParams";

export interface RestApiPort {
get<X>(params: GetParams): Promise<X>;
get: <X>(params: GetParams) => Promise<X>;

post<X, Y>(params: PostParams<X>): Promise<Y>;
post: <X, Y>(params: PostParams<X>) => Promise<Y>;

patch<X, Y>(params: PatchParams<X>): Promise<Y>;
patch: <X, Y>(params: PatchParams<X>) => Promise<Y>;

delete<X>(params: DeleteParams): Promise<X>;
delete: <X>(params: DeleteParams) => Promise<X>;

unauthpost<X, Y>(params: UnauthPostParams<X>): Promise<Y>;
unauthpost: <X, Y>(params: UnauthPostParams<X>) => Promise<Y>;
}
3 changes: 0 additions & 3 deletions src/utils/routePaths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@ const routePaths = {
signIn() {
return "/sign-in";
},
signOut() {
return "/sign-out";
},
signUp() {
return "/sign-up";
},
Expand Down

0 comments on commit b2ca4ab

Please sign in to comment.