diff --git a/client/src/App.vue b/client/src/App.vue index 60a4371..d42eb93 100644 --- a/client/src/App.vue +++ b/client/src/App.vue @@ -32,8 +32,33 @@ О проекте + + +
+ + + + +
@@ -45,14 +70,22 @@ diff --git a/client/src/components/routes/users/api.ts b/client/src/components/routes/users/api.ts new file mode 100644 index 0000000..e6eee88 --- /dev/null +++ b/client/src/components/routes/users/api.ts @@ -0,0 +1,21 @@ +import { api } from "@/api"; +import { User } from "@/types/users"; +import { UserCreation } from "@/components/routes/users/types"; + +function getUsers() { + return api.get("/users"); +} + +function createUser(user: UserCreation) { + return api.post("/users", user); +} + +function deleteUser(id: string) { + return api.delete(`/users/user/${id}`); +} + +function updateUser(id: string, user: UserCreation) { + return api.put(`/users/user/${id}`, user); +} + +export const UserAdminAPI = { getUsers, createUser, deleteUser, updateUser }; diff --git a/client/src/components/routes/users/types.ts b/client/src/components/routes/users/types.ts new file mode 100644 index 0000000..2637ee0 --- /dev/null +++ b/client/src/components/routes/users/types.ts @@ -0,0 +1,3 @@ +import { User } from "@/types/users"; + +export type UserCreation = Omit; diff --git a/client/src/config/users.ts b/client/src/config/users.ts new file mode 100644 index 0000000..37eed43 --- /dev/null +++ b/client/src/config/users.ts @@ -0,0 +1,4 @@ +export enum UserRole { + user = "user", + admin = "admin", +} diff --git a/client/src/main.ts b/client/src/main.ts index 04eb87f..16caa8b 100644 --- a/client/src/main.ts +++ b/client/src/main.ts @@ -9,12 +9,20 @@ import { vBsTooltip } from "@/bootstrap/tooltip"; import { plugin, defaultConfig } from "@formkit/vue"; import "@formkit/themes/genesis"; import { createPinia } from "pinia"; +import { useUserStore } from "@/store/user"; -const pinia = createPinia(); +async function bootstrap() { + const pinia = createPinia(); -const app = createApp(App); -app.use(router); -app.use(plugin, defaultConfig()); -app.use(pinia); -app.directive("bs-tooltip", vBsTooltip); -app.mount("#app"); + const userStore = useUserStore(pinia); + await userStore.fetchUser(); + + const app = createApp(App); + app.use(router); + app.use(plugin, defaultConfig()); + app.use(pinia); + app.directive("bs-tooltip", vBsTooltip); + app.mount("#app"); +} + +bootstrap(); diff --git a/client/src/router/index.ts b/client/src/router/index.ts index 1187cb9..b72a066 100644 --- a/client/src/router/index.ts +++ b/client/src/router/index.ts @@ -8,6 +8,8 @@ export const routeNames = { Map: "Map", Object: "Object", Home: "Home", + Auth: "Auth", + Users: "Users", }; export const routePaths = { @@ -18,6 +20,8 @@ export const routePaths = { [routeNames.Map]: "/map/:y?/:x?", [routeNames.Object]: "/object/:id", [routeNames.Home]: "/home", + [routeNames.Auth]: "/auth", + [routeNames.Auth]: "/Users", }; export const routes: RouteRecordRaw[] = [ @@ -63,6 +67,18 @@ export const routes: RouteRecordRaw[] = [ path: routePaths[routeNames.Home], component: () => import("@/views/HomeView.vue"), }, + + { + name: routeNames.Auth, + path: routePaths[routeNames.Auth], + component: () => import("@/views/AuthView.vue"), + }, + + { + name: routeNames.Users, + path: routePaths[routeNames.Users], + component: () => import("@/views/UsersView.vue"), + }, ]; export const router = createRouter({ diff --git a/client/src/store/user.ts b/client/src/store/user.ts new file mode 100644 index 0000000..9e16801 --- /dev/null +++ b/client/src/store/user.ts @@ -0,0 +1,42 @@ +import { defineStore } from "pinia"; +import { computed, readonly, ref } from "vue"; +import { User } from "@/types/users"; +import { UserAPI } from "@/components/routes/auth/api"; + +export const useUserStore = defineStore("user", () => { + const user = ref(null); + + async function fetchUser() { + try { + user.value = (await UserAPI.fetchUser()).data; + } catch (err) { + user.value = null; + } + } + + async function login(login: string, password: string) { + user.value = (await UserAPI.login(login, password)).data; + } + + async function devLogin() { + user.value = (await UserAPI.devLogin()).data; + } + + async function logout() { + user.value = null; + await UserAPI.logout(); + } + + const isAuthed = computed(() => user.value !== null); + const role = computed(() => user.value?.role || null); + + return { + user: readonly(user), + fetchUser, + login, + logout, + devLogin, + isAuthed, + role, + }; +}); diff --git a/client/src/types/users.ts b/client/src/types/users.ts index 3ca53ab..080e226 100644 --- a/client/src/types/users.ts +++ b/client/src/types/users.ts @@ -1,7 +1,9 @@ -export interface UserInfo { - id: string; +export interface User { + _id: { + $oid: string; + }; login: string; password: string; - status: string; + name: string; role: string; } diff --git a/client/src/views/AuthView.vue b/client/src/views/AuthView.vue new file mode 100644 index 0000000..a506aa0 --- /dev/null +++ b/client/src/views/AuthView.vue @@ -0,0 +1,7 @@ + + + + + diff --git a/client/src/views/UsersView.vue b/client/src/views/UsersView.vue new file mode 100644 index 0000000..3f29f38 --- /dev/null +++ b/client/src/views/UsersView.vue @@ -0,0 +1,7 @@ + + + + + diff --git a/server/app/routes/auth.py b/server/app/routes/auth.py index d4c82c7..e7ea716 100644 --- a/server/app/routes/auth.py +++ b/server/app/routes/auth.py @@ -33,7 +33,7 @@ def post(self): return 'Incorrect password', 400 else: login_user(User(user), remember=True) - return 'Logged in', 200 + return parse_json(get_user_by_id(current_user.get_id())), 200 @login_required def get(self): @@ -58,4 +58,4 @@ def get(self): }) admin = db.users.find_one(result.inserted_id) login_user(User(admin), remember=True) - return "Logged in as root" + return parse_json(get_user_by_id(current_user.get_id()))