From ec41110e0b4bdf83001d10646e79d849d884ea1d Mon Sep 17 00:00:00 2001 From: L-Nafaryus Date: Mon, 8 Jul 2024 16:26:35 +0500 Subject: [PATCH] fix: api client, auth workflow --- .../src/materia-frontend/src/api/auth.ts | 9 +- .../src/materia-frontend/src/api/index.ts | 1 + .../materia-frontend/src/api/repository.ts | 23 +++++ .../src/materia-frontend/src/api/user.ts | 85 +++++-------------- .../src/materia-frontend/src/assets/style.css | 8 +- .../materia-frontend/src/{api => }/client.ts | 11 +-- .../src/materia-frontend/src/index.ts | 1 + .../materia-frontend/src/resources/index.ts | 23 +++++ .../src/materia-frontend/src/router.ts | 16 ++-- .../src/materia-frontend/src/stores/index.ts | 9 +- .../src/materia-frontend/src/views/Base.vue | 50 +++++------ .../materia-frontend/src/views/Repository.vue | 81 ++++++++++++++++++ .../src/views/auth/SignIn.vue | 4 +- .../src/views/auth/SignUp.vue | 2 +- 14 files changed, 199 insertions(+), 124 deletions(-) create mode 100644 materia-web-client/src/materia-frontend/src/api/repository.ts rename materia-web-client/src/materia-frontend/src/{api => }/client.ts (81%) create mode 100644 materia-web-client/src/materia-frontend/src/resources/index.ts create mode 100644 materia-web-client/src/materia-frontend/src/views/Repository.vue diff --git a/materia-web-client/src/materia-frontend/src/api/auth.ts b/materia-web-client/src/materia-frontend/src/api/auth.ts index b3b4ab7..14329be 100644 --- a/materia-web-client/src/materia-frontend/src/api/auth.ts +++ b/materia-web-client/src/materia-frontend/src/api/auth.ts @@ -1,4 +1,4 @@ -import { client, type ResponseError, handle_error } from "@/api/client"; +import { api_client, type ResponseError, handle_error } from "@/client"; export interface UserCredentials { name: string, @@ -7,17 +7,16 @@ export interface UserCredentials { } export async function signup(body: UserCredentials): Promise { - return await client.post("/auth/signup", JSON.stringify(body)) + return await api_client.post("/auth/signup", JSON.stringify(body)) .catch(handle_error); } export async function signin(body: UserCredentials): Promise { - return await client.post("/auth/signin", JSON.stringify(body)) + return await api_client.post("/auth/signin", JSON.stringify(body)) .catch(handle_error); } - export async function signout(): Promise { - return await client.post("/auth/signout") + return await api_client.get("/auth/signout") .catch(handle_error); } diff --git a/materia-web-client/src/materia-frontend/src/api/index.ts b/materia-web-client/src/materia-frontend/src/api/index.ts index 465df04..9d61d82 100644 --- a/materia-web-client/src/materia-frontend/src/api/index.ts +++ b/materia-web-client/src/materia-frontend/src/api/index.ts @@ -1,2 +1,3 @@ export * as auth from "@/api/auth"; export * as user from "@/api/user"; +export * as repository from "@/api/repository"; diff --git a/materia-web-client/src/materia-frontend/src/api/repository.ts b/materia-web-client/src/materia-frontend/src/api/repository.ts new file mode 100644 index 0000000..0567836 --- /dev/null +++ b/materia-web-client/src/materia-frontend/src/api/repository.ts @@ -0,0 +1,23 @@ +import { api_client, type ResponseError, handle_error } from "@/client"; + +export interface RepositoryInfo { + id: number, + capacity: number, + used?: number +} + +export async function info(): Promise { + return await api_client.get("/repository") + .then(async response => { return Promise.resolve(response.data); }) + .catch(handle_error); +} + +export async function create(): Promise { + return await api_client.post("/repository") + .catch(handle_error); +} + +export async function remove(): Promise { + return await api_client.delete("/repository") + .catch(handle_error); +} diff --git a/materia-web-client/src/materia-frontend/src/api/user.ts b/materia-web-client/src/materia-frontend/src/api/user.ts index 2b7289c..cd924bf 100644 --- a/materia-web-client/src/materia-frontend/src/api/user.ts +++ b/materia-web-client/src/materia-frontend/src/api/user.ts @@ -1,4 +1,4 @@ -import { client, upload_client, resources_client, type ResponseError, handle_error } from "@/api/client"; +import { api_client, type ResponseError, handle_error } from "@/client"; export interface UserCredentials { name: string, @@ -6,77 +6,30 @@ export interface UserCredentials { email?: string } -export async function signup(body: UserCredentials): Promise { - return await client.post("/auth/signup", JSON.stringify(body)) - .catch(handle_error); +export interface UserInfo { + id: string, + name: string, + lower_name: string, + full_name?: string, + email?: string, + is_email_private: boolean, + must_change_password: boolean, + login_type: string, + created: number, + updated: number, + last_login?: number, + is_active: boolean, + is_admin: boolean, + avatar?: string } -export async function signin(body: UserCredentials): Promise { - return await client.post("/auth/signin", JSON.stringify(body)) - .catch(handle_error); -} export type Image = string | ArrayBuffer; -export async function register(body: NewUser): Promise { - return await client.post("/user/register", JSON.stringify(body)) - .then(async response => { return Promise.resolve(response.data); }) +export async function info(): Promise { + return await api_client.get("/user") + .then(async response => { return Promise.resolve(response.data); }) .catch(handle_error); } -export async function login(body: LoginUser): Promise { - return await client.post("/user/login", JSON.stringify(body)) - .then(async response => { return Promise.resolve(response.data); }) - .catch(handle_error); -} -export async function remove(body: RemoveUser): Promise { - return await client.post("/user/remove", JSON.stringify(body)) - .then(async () => { return Promise.resolve(null); }) - .catch(handle_error); -} - -export async function logout(): Promise { - return await client.get("/user/logout") - .then(async () => { return Promise.resolve(null); }) - .catch(handle_error); -} - -export async function current(): Promise { - return await client.get("/user/current") - .then(async response => { return Promise.resolve(response.data); }) - .catch(handle_error); -} - -export async function avatar(file: FormData, progress?: any): Promise { - return await upload_client.post("/user/avatar", file, { - onUploadProgress: progress ?? null, - //headers: { "Accept-Encoding": "gzip" } - }) - .then(async () => { return Promise.resolve(null); }) - .catch(handle_error); -} - -export async function get_avatar(avatar: string): Promise { - return await resources_client.get("/avatars/".concat(avatar)) - .then(async response => { - return new Promise((resolve, reject) => { - let reader = new FileReader(); - - reader.onload = () => { - resolve(reader.result); - }; - reader.onerror = (e) => { - reject(e); - }; - reader.readAsDataURL(response.data); - }) - }) - .catch(handle_error); -} - -export async function profile(login: string): Promise { - return await client.get("/user/".concat(login)) - .then(async response => { return Promise.resolve(response.data); }) - .catch(handle_error); -} diff --git a/materia-web-client/src/materia-frontend/src/assets/style.css b/materia-web-client/src/materia-frontend/src/assets/style.css index a517b63..5cf7282 100644 --- a/materia-web-client/src/materia-frontend/src/assets/style.css +++ b/materia-web-client/src/materia-frontend/src/assets/style.css @@ -22,11 +22,15 @@ } .button { - @apply pt-2 pb-2 pl-5 pr-5 rounded bg-ctp-mantle hover:bg-ctp-base text-ctp-blue; + @apply pt-2 pb-2 pl-5 pr-5 rounded bg-ctp-mantle hover:bg-ctp-base text-ctp-blue cursor-pointer; } .link-button { - @apply button text-ctp-green; + @apply button text-ctp-green cursor-pointer; + } + + .hline { + @apply border-t border-ctp-overlay0 ml-0 mr-0; } h1 { diff --git a/materia-web-client/src/materia-frontend/src/api/client.ts b/materia-web-client/src/materia-frontend/src/client.ts similarity index 81% rename from materia-web-client/src/materia-frontend/src/api/client.ts rename to materia-web-client/src/materia-frontend/src/client.ts index 2620180..437b98f 100644 --- a/materia-web-client/src/materia-frontend/src/api/client.ts +++ b/materia-web-client/src/materia-frontend/src/client.ts @@ -30,7 +30,7 @@ export function handle_error(error: AxiosError): Promise { const debug = import.meta.hot; -export const client: AxiosInstance = axios.create({ +export const api_client: AxiosInstance = axios.create({ baseURL: debug ? "http://localhost:54601/api" : "/api", headers: { "Content-Type": "application/json" @@ -38,17 +38,8 @@ export const client: AxiosInstance = axios.create({ withCredentials: true, }); -export const upload_client: AxiosInstance = axios.create({ - baseURL: debug ? "http://localhost:54601/api" : "/api", - headers: { - "Content-Type": "multipart/form-data" - }, - withCredentials: true, -}); - export const resources_client: AxiosInstance = axios.create({ baseURL: debug ? "http://localhost:54601/resources" : "/resources", responseType: "blob" }); -export default client; diff --git a/materia-web-client/src/materia-frontend/src/index.ts b/materia-web-client/src/materia-frontend/src/index.ts index f6c0c3c..5bc2604 100644 --- a/materia-web-client/src/materia-frontend/src/index.ts +++ b/materia-web-client/src/materia-frontend/src/index.ts @@ -1 +1,2 @@ export * as api from "@/api"; +export * as resources from "@/resources"; diff --git a/materia-web-client/src/materia-frontend/src/resources/index.ts b/materia-web-client/src/materia-frontend/src/resources/index.ts new file mode 100644 index 0000000..bf2fc2f --- /dev/null +++ b/materia-web-client/src/materia-frontend/src/resources/index.ts @@ -0,0 +1,23 @@ +import { resources_client, type ResponseError, handle_error } from "@/client"; + + +export type Image = string | ArrayBuffer; + +export async function avatars(avatar_id: string, format?: string): Promise { + return await resources_client.get("/avatars/".concat(avatar_id), { params: { format: format ? format : "png" }}) + .then(async response => { + return new Promise((resolve, reject) => { + let reader = new FileReader(); + + reader.onload = () => { + resolve(reader.result); + }; + reader.onerror = (e) => { + reject(e); + }; + reader.readAsDataURL(response.data); + }) + + }) + .catch(handle_error); +} diff --git a/materia-web-client/src/materia-frontend/src/router.ts b/materia-web-client/src/materia-frontend/src/router.ts index 882ffc0..fa23620 100644 --- a/materia-web-client/src/materia-frontend/src/router.ts +++ b/materia-web-client/src/materia-frontend/src/router.ts @@ -1,18 +1,16 @@ import { createRouter, createWebHistory } from "vue-router"; -import { user } from "@/api"; import { useUserStore } from "@/stores"; - +import { api, resources } from "@"; async function check_authorized(): Promise { const userStore = useUserStore(); - // TODO: add timer - return await user.current() - .then(async user => { userStore.current = user; }) + return await api.user.info() + .then(async user_info => { userStore.info = user_info; }) .then(async () => { - if (userStore.current.avatar?.length) { - await user.get_avatar(userStore.current.avatar) + if (!userStore.avatar && userStore.info.avatar) { + await resources.avatars(userStore.info.avatar) .then(async avatar => { userStore.avatar = avatar; }) } }) @@ -69,8 +67,8 @@ const router = createRouter({ ] }, { - path: "/:user", name: "profile", beforeEnter: [bypass_auth], - component: () => import("@/views/user/Profile.vue") + path: "/:user/repository", name: "repository", beforeEnter: [required_auth], + component: () => import("@/views/Repository.vue") }, { path: "/admin/settings", name: "settings", beforeEnter: [required_auth, required_admin], diff --git a/materia-web-client/src/materia-frontend/src/stores/index.ts b/materia-web-client/src/materia-frontend/src/stores/index.ts index 9a87b24..93de975 100644 --- a/materia-web-client/src/materia-frontend/src/stores/index.ts +++ b/materia-web-client/src/materia-frontend/src/stores/index.ts @@ -2,17 +2,18 @@ import { defineStore } from "pinia"; import { ref, type Ref } from "vue"; import { user } from "@/api"; +import { resources } from "@"; export const useUserStore = defineStore("user", () => { - const current: Ref = ref(null); - const avatar: Ref = ref(null); + const info: Ref = ref(null); + const avatar: Ref = ref(null); function clear() { - current.value = null; + info.value = null; avatar.value = null; } - return { current, avatar, clear }; + return { info, avatar, clear }; }); export const useMiscStore = defineStore("misc", () => { diff --git a/materia-web-client/src/materia-frontend/src/views/Base.vue b/materia-web-client/src/materia-frontend/src/views/Base.vue index d146cda..9f3f78d 100644 --- a/materia-web-client/src/materia-frontend/src/views/Base.vue +++ b/materia-web-client/src/materia-frontend/src/views/Base.vue @@ -5,14 +5,15 @@ import DropdownMenu from "@/components/DropdownMenu.vue"; import { ref, onMounted } from "vue"; import router from "@/router"; -import { user } from "@/api"; +import { user, auth } from "@/api"; +import { resources } from "@"; import { useUserStore } from "@/stores"; const userStore = useUserStore(); const error = ref(null); async function signout() { - await user.logout() + await auth.signout() .then(async () => { userStore.clear(); router.push({ path: "/" }); @@ -28,36 +29,36 @@ async function signout() { -