From 13fd66dec59a04264c7a33fee478251477485dac Mon Sep 17 00:00:00 2001 From: Arif Rahman Hakim Date: Fri, 30 Aug 2024 13:21:27 +0800 Subject: [PATCH] feat: implement login with sso --- src/api/authApi.ts | 47 +++++++++++++++-------- src/stores/auth.ts | 82 ++++++++++++++++++++++++----------------- src/views/LoginView.vue | 54 +++++++++++++++++++++++++-- 3 files changed, 131 insertions(+), 52 deletions(-) diff --git a/src/api/authApi.ts b/src/api/authApi.ts index 3e01895..fca2322 100644 --- a/src/api/authApi.ts +++ b/src/api/authApi.ts @@ -2,22 +2,39 @@ import { useAuthStore } from "@/stores/auth"; import { BASE_URL } from "./api"; export const login = async (payload: any) => { - const auth = useAuthStore(); + const auth = useAuthStore(); - const response = await fetch(`${BASE_URL}/v1/auth/login`, { - method: "POST", - headers: { - "Authorization": `Bearer ${auth.token}`, - "Content-Type": "application/json" - }, - body: JSON.stringify(payload) - }); + const response = await fetch(`${BASE_URL}/v1/auth/login`, { + method: "POST", + headers: { + Authorization: `Bearer ${auth.token}`, + "Content-Type": "application/json", + }, + body: JSON.stringify(payload), + }); - const result = await response.json(); + const result = await response.json(); - if (!response.ok) { - throw new Error(result.message) - } + if (!response.ok) { + throw new Error(result.message); + } - return result; -}; \ No newline at end of file + return result; +}; + +export const loginSso = async (token: string) => { + const response = await fetch(`${BASE_URL}/v1/users/me`, { + headers: { + Authorization: `Bearer ${token}`, + "Content-Type": "application/json", + }, + }); + + const result = await response.json(); + + if (!response.ok) { + throw new Error(result.message); + } + + return result; +}; diff --git a/src/stores/auth.ts b/src/stores/auth.ts index a1fd4b2..bbe73cb 100644 --- a/src/stores/auth.ts +++ b/src/stores/auth.ts @@ -1,39 +1,53 @@ -import { login } from '@/api/authApi' -import { defineStore } from 'pinia' +import { login, loginSso } from "@/api/authApi"; +import { defineStore } from "pinia"; export const useAuthStore = defineStore({ - id: 'auth', - state: () => { - return { - token: '', - isLogin: false, - } + id: "auth", + state: () => { + return { + token: "", + isLogin: false, + }; + }, + actions: { + logout() { + this.$patch({ + token: "", + isLogin: false, + }); + + this.router.push({ name: "login" }); }, - actions: { - logout() { - this.$patch({ - token: '', - isLogin: false, - }); - - this.router.push({ "name": "login" }) - }, - - async login(payload: any) { - const result = await login(payload); - - if (result.data) { - this.$patch({ - token: result.data.token, - isLogin: true, - }); - - this.router.push({ "name": "dashboard" }) - } - - return result; - } + + async login(payload: any) { + const result = await login(payload); + + if (result.data) { + this.$patch({ + token: result.data.token, + isLogin: true, + }); + + this.router.push({ name: "dashboard" }); + } + + return result; }, - persist: true, -}) + async loginSso(token: any) { + const result = await loginSso(token); + + if (result.data) { + this.$patch({ + token: token, + isLogin: true, + }); + + this.router.push({ name: "dashboard" }); + } + + return result; + }, + }, + persist: true, +}); diff --git a/src/views/LoginView.vue b/src/views/LoginView.vue index c0bc6b7..bc1eb38 100644 --- a/src/views/LoginView.vue +++ b/src/views/LoginView.vue @@ -28,7 +28,7 @@ OR - + Login with SSO BPS @@ -43,6 +43,8 @@ import { ref, reactive, watch } from "vue"; import type { FormInstance, FormRules } from "element-plus"; import { useAuthStore } from "@/stores/auth"; import { ElNotification } from "element-plus"; +import { BASE_URL } from "@/api/api"; +import { useRoute } from "vue-router"; const app = import.meta.env.VITE_APP_TITLE; @@ -51,7 +53,7 @@ const initialState = { password: "", }; -const enableSso = ref(false); +const enableSso = ref(true); const rules = reactive>({ email: [ @@ -72,7 +74,7 @@ const rules = reactive>({ const formRef = ref(); const form = reactive({ ...initialState }); - +const route = useRoute(); const auth = useAuthStore(); const loading = ref(false); const error = ref(""); @@ -115,6 +117,52 @@ const login = async (formEl: FormInstance | undefined) => { }); }; +const loginSso = async () => { + window.location.href = `${BASE_URL}/v1/auth/sso`; +} + +const handleError = (error: any) => { + let message = ""; + if (error == "user_not_found") { + message = "User tidak ditemukan"; + } else { + message = "Terjadi kesalahan, silahkan coba lagi"; + } + + feedback.value = { + title: "Error", + message: message, + type: "error", + }; +}; + + +watch(() => route.query.token, async (token) => { + if (token) { + + try { + await auth.loginSso(token); + feedback.value = { + title: "Success", + message: "Successfully logged in", + type: "success", + }; + } catch (e) { + if (e instanceof Error) { + feedback.value = { + title: "Error", + message: "Something went wrong, please try again", + type: "error", + }; + } + } + } +}, { immediate: true }); + +watch(() => route.query.error, async (error) => { + if (error) handleError(error); +}, { immediate: true }); + watch( () => feedback.value, (feedback: any) => {