chore: updated api service and handled the set password in store

This commit is contained in:
guru_sainath 2024-05-08 18:25:22 +05:30
parent 71d0355132
commit 9e60d2c40b
6 changed files with 67 additions and 188 deletions

View File

@ -19,7 +19,7 @@ export abstract class APIService {
(response) => response, (response) => response,
(error) => { (error) => {
if (error.response && error.response.status === 401) window.location.href = "/login"; if (error.response && error.response.status === 401) window.location.href = "/login";
return Promise.reject(error.response?.data ?? error); return Promise.reject(error);
} }
); );
} }

View File

@ -20,7 +20,7 @@ abstract class APIService {
(response) => response, (response) => response,
(error) => { (error) => {
if (error.response && error.response.status === 401) window.location.href = "/"; if (error.response && error.response.status === 401) window.location.href = "/";
return Promise.reject(error.response?.data ?? error); return Promise.reject(error);
} }
); );
} }

View File

@ -56,8 +56,8 @@ const SetPasswordPage: NextPageWithLayout = observer(() => {
const [isPasswordInputFocused, setIsPasswordInputFocused] = useState(false); const [isPasswordInputFocused, setIsPasswordInputFocused] = useState(false);
// hooks // hooks
const { resolvedTheme } = useTheme(); const { resolvedTheme } = useTheme();
// hooks
const { data: user } = useUser(); const { data: user, handleSetPassword } = useUser();
useEffect(() => { useEffect(() => {
if (csrfToken === undefined) if (csrfToken === undefined)
@ -77,15 +77,12 @@ const SetPasswordPage: NextPageWithLayout = observer(() => {
[passwordFormData] [passwordFormData]
); );
const handleSetPassword = async (password: string) => {
if (!csrfToken) throw new Error("csrf token not found");
await authService.setPassword(csrfToken, { password });
};
const handleSubmit = async (e: FormEvent<HTMLFormElement>) => { const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {
try { try {
e.preventDefault(); e.preventDefault();
await handleSetPassword(passwordFormData.password); if (!csrfToken) throw new Error("csrf token not found");
await handleSetPassword(csrfToken, { password: passwordFormData.password });
router.push("/");
} catch (err: any) { } catch (err: any) {
setToast({ setToast({
type: TOAST_TYPE.ERROR, type: TOAST_TYPE.ERROR,

View File

@ -1,107 +1,51 @@
import axios from "axios"; /* eslint-disable @typescript-eslint/no-explicit-any */
import Cookies from "js-cookie"; import axios, { AxiosInstance } from "axios";
export abstract class APIService { export abstract class APIService {
protected baseURL: string; protected baseURL: string;
protected headers: any = {}; private axiosInstance: AxiosInstance;
constructor(baseURL: string) { constructor(baseURL: string) {
this.baseURL = baseURL; this.baseURL = baseURL;
} this.axiosInstance = axios.create({
baseURL,
setCSRFToken(token: string) {
Cookies.set("csrf_token", token, { expires: 30 });
}
getCSRFToken() {
return Cookies.get("csrf_token");
}
setRefreshToken(token: string) {
Cookies.set("refresh_token", token, { expires: 30 });
}
getRefreshToken() {
return Cookies.get("refresh_token");
}
purgeRefreshToken() {
Cookies.remove("refresh_token", { path: "/" });
}
setAccessToken(token: string) {
Cookies.set("access_token", token, { expires: 30 });
}
getAccessToken() {
return Cookies.get("access_token");
}
purgeAccessToken() {
Cookies.remove("access_token", { path: "/" });
}
getHeaders() {
return {
Authorization: `Bearer ${this.getAccessToken()}`,
};
}
get(url: string, config = {}): Promise<any> {
return axios({
method: "get",
url: this.baseURL + url,
headers: this.getAccessToken() ? this.getHeaders() : {},
...config,
withCredentials: true, withCredentials: true,
}); });
this.setupInterceptors();
} }
post(url: string, data = {}, config = {}): Promise<any> { private setupInterceptors() {
return axios({ this.axiosInstance.interceptors.response.use(
method: "post", (response) => response,
url: this.baseURL + url, (error) => {
data, if (error.response && error.response.status === 401) window.location.href = "/accounts/sign-in";
headers: this.getAccessToken() ? this.getHeaders() : {}, return Promise.reject(error);
...config, }
withCredentials: true, );
});
} }
put(url: string, data = {}, config = {}): Promise<any> { get(url: string, params = {}) {
return axios({ return this.axiosInstance.get(url, { params });
method: "put",
url: this.baseURL + url,
data,
headers: this.getAccessToken() ? this.getHeaders() : {},
...config,
withCredentials: true,
});
} }
patch(url: string, data = {}, config = {}): Promise<any> { post(url: string, data: any, config = {}) {
return axios({ return this.axiosInstance.post(url, data, config);
method: "patch",
url: this.baseURL + url,
data,
headers: this.getAccessToken() ? this.getHeaders() : {},
...config,
withCredentials: true,
});
} }
delete(url: string, data?: any, config = {}): Promise<any> { put(url: string, data: any, config = {}) {
return axios({ return this.axiosInstance.put(url, data, config);
method: "delete", }
url: this.baseURL + url,
data: data, patch(url: string, data: any, config = {}) {
headers: this.getAccessToken() ? this.getHeaders() : {}, return this.axiosInstance.patch(url, data, config);
...config, }
withCredentials: true,
}); delete(url: string, data?: any, config = {}) {
return this.axiosInstance.delete(url, { data, ...config });
} }
request(config = {}) { request(config = {}) {
return axios(config); return this.axiosInstance(config);
} }
} }

View File

@ -1,12 +1,5 @@
// types // types
import { import { ICsrfTokenData, IEmailCheckData, IEmailCheckResponse } from "@plane/types";
ICsrfTokenData,
IEmailCheckData,
IEmailCheckResponse,
ILoginTokenResponse,
IMagicSignInData,
IPasswordSignInData,
} from "@plane/types";
// helpers // helpers
import { API_BASE_URL } from "@/helpers/common.helper"; import { API_BASE_URL } from "@/helpers/common.helper";
// services // services
@ -39,18 +32,6 @@ export class AuthService extends APIService {
throw error?.response?.data; throw error?.response?.data;
}); });
async passwordSignIn(data: IPasswordSignInData): Promise<ILoginTokenResponse> {
return this.post("/api/sign-in/", data, { headers: {} })
.then((response) => {
this.setAccessToken(response?.data?.access_token);
this.setRefreshToken(response?.data?.refresh_token);
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async sendResetPasswordLink(data: { email: string }): Promise<any> { async sendResetPasswordLink(data: { email: string }): Promise<any> {
return this.post(`/auth/forgot-password/`, data) return this.post(`/auth/forgot-password/`, data)
.then((response) => response?.data) .then((response) => response?.data)
@ -71,50 +52,6 @@ export class AuthService extends APIService {
}); });
} }
async resetPassword(
uidb64: string,
token: string,
data: {
new_password: string;
}
): Promise<ILoginTokenResponse> {
return this.post(`/api/reset-password/${uidb64}/${token}/`, data, { headers: {} })
.then((response) => {
if (response?.status === 200) {
this.setAccessToken(response?.data?.access_token);
this.setRefreshToken(response?.data?.refresh_token);
return response?.data;
}
})
.catch((error) => {
throw error?.response?.data;
});
}
async emailSignUp(data: { email: string; password: string }): Promise<ILoginTokenResponse> {
return this.post("/api/sign-up/", data, { headers: {} })
.then((response) => {
this.setAccessToken(response?.data?.access_token);
this.setRefreshToken(response?.data?.refresh_token);
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async socialAuth(data: any): Promise<ILoginTokenResponse> {
return this.post("/api/social-auth/", data, { headers: {} })
.then((response) => {
this.setAccessToken(response?.data?.access_token);
this.setRefreshToken(response?.data?.refresh_token);
return response?.data;
})
.catch((error) => {
throw error?.response?.data;
});
}
async generateUniqueCode(data: { email: string }): Promise<any> { async generateUniqueCode(data: { email: string }): Promise<any> {
return this.post("/auth/magic-generate/", data, { headers: {} }) return this.post("/auth/magic-generate/", data, { headers: {} })
.then((response) => response?.data) .then((response) => response?.data)
@ -123,34 +60,6 @@ export class AuthService extends APIService {
}); });
} }
async magicSignIn(data: IMagicSignInData): Promise<any> {
return await this.post("/api/magic-sign-in/", data, { headers: {} })
.then((response) => {
if (response?.status === 200) {
this.setAccessToken(response?.data?.access_token);
this.setRefreshToken(response?.data?.refresh_token);
return response?.data;
}
})
.catch((error) => {
throw error?.response?.data;
});
}
async instanceAdminSignIn(data: IPasswordSignInData): Promise<ILoginTokenResponse> {
return await this.post("/api/instances/admins/sign-in/", data, { headers: {} })
.then((response) => {
if (response?.status === 200) {
this.setAccessToken(response?.data?.access_token);
this.setRefreshToken(response?.data?.refresh_token);
return response?.data;
}
})
.catch((error) => {
throw error?.response?.data;
});
}
async signOut(baseUrl: string): Promise<any> { async signOut(baseUrl: string): Promise<any> {
await this.requestCSRFToken().then((data) => { await this.requestCSRFToken().then((data) => {
const csrfToken = data?.csrf_token; const csrfToken = data?.csrf_token;

View File

@ -1,3 +1,4 @@
import cloneDeep from "lodash/cloneDeep";
import set from "lodash/set"; import set from "lodash/set";
import { action, makeObservable, observable, runInAction } from "mobx"; import { action, makeObservable, observable, runInAction } from "mobx";
// types // types
@ -33,6 +34,7 @@ export interface IUserStore {
// actions // actions
fetchCurrentUser: () => Promise<IUser | undefined>; fetchCurrentUser: () => Promise<IUser | undefined>;
updateCurrentUser: (data: Partial<IUser>) => Promise<IUser | undefined>; updateCurrentUser: (data: Partial<IUser>) => Promise<IUser | undefined>;
handleSetPassword: (csrfToken: string, data: { password: string }) => Promise<IUser | undefined>;
deactivateAccount: () => Promise<void>; deactivateAccount: () => Promise<void>;
signOut: () => Promise<void>; signOut: () => Promise<void>;
} }
@ -75,6 +77,7 @@ export class UserStore implements IUserStore {
// actions // actions
fetchCurrentUser: action, fetchCurrentUser: action,
updateCurrentUser: action, updateCurrentUser: action,
handleSetPassword: action,
deactivateAccount: action, deactivateAccount: action,
signOut: action, signOut: action,
}); });
@ -153,6 +156,32 @@ export class UserStore implements IUserStore {
} }
}; };
/**
* @description update the user password
* @param data
* @returns {Promise<IUser>}
*/
handleSetPassword = async (csrfToken: string, data: { password: string }): Promise<IUser | undefined> => {
const currentUserData = cloneDeep(this.data);
try {
if (currentUserData && currentUserData.is_password_autoset && this.data) {
const user = await this.authService.setPassword(csrfToken, { password: data.password });
set(this.data, ["is_password_autoset"], false);
return user;
}
return undefined;
} catch (error) {
if (this.data) set(this.data, ["is_password_autoset"], true);
runInAction(() => {
this.error = {
status: "user-update-error",
message: "Failed to update current user",
};
});
throw error;
}
};
/** /**
* @description deactivates the current user * @description deactivates the current user
* @returns {Promise<void>} * @returns {Promise<void>}