preliminary frontend for ther auth api
Some checks failed
Build and Deploy Frontend / build-and-deploy (push) Failing after 4s
Build and Deploy API / build-and-deploy (push) Successful in 12s

This commit is contained in:
2026-03-17 22:30:59 -05:00
parent c19cd0c718
commit 661bb03d1d
7 changed files with 54 additions and 21 deletions

View File

@@ -7,5 +7,7 @@ public class User {
public string Name { get; set; } = ""; public string Name { get; set; } = "";
public string Email { get; set; } = ""; public string Email { get; set; } = "";
public string PasswordHash { get; set; } = ""; public string PasswordHash { get; set; } = "";
public string Role { get; set; }
public DateTime CreatedAt { get; set; }
}; };

View File

@@ -1,19 +1,12 @@
// services are kinda whatever, but in general its a good idea for all api calls to be within a service (at least thats how angular handles it) // services are kinda whatever, but in general its a good idea for all api calls to be within a service (at least thats how angular handles it)
// this user service will handle all to <-> from the server when handling user objects // this user service will handle all to <-> from the server when handling user objects
// should be injected with the http client (I think its axios ?)
import axios from "axios"; import api from "./axios.ts"
import type {AxiosResponse } from "axios";
import type { User } from "../models/User.ts"; import type { User } from "../models/User.ts";
const API_URL: string = "/users"; const API_URL: string = "/users";
const baseUrl: string = import.meta.env.DEV ? import.meta.env.VITE_DEV_API_URL : "https://app.vxbard.net/api" // TODO: overarching api service
const api = axios.create({
baseURL: baseUrl
});
export const getUsers = () => api.get<User[]>(`${API_URL}`); export const getUsers = () => api.get<User[]>(`${API_URL}`);
export const getUser = (id: number) => api.get<User>(`${API_URL}/${id}`); export const getUser = (id: number) => api.get<User>(`${API_URL}/${id}`);

View File

@@ -4,5 +4,6 @@
export interface User { export interface User {
id: number; id: number;
name: string; name: string;
email: string email: string;
password: string;
} }

View File

@@ -13,9 +13,10 @@ const route = useRoute();
const router = useRouter(); const router = useRouter();
const user = ref<User>({ const user = ref<User>({
name: "",
id: 0, id: 0,
name: "",
email: "", email: "",
password: ""
}); });
const id: string | undefined = route.params.id as string | undefined const id: string | undefined = route.params.id as string | undefined

View File

@@ -2,14 +2,22 @@
<script setup lang="ts"> <script setup lang="ts">
import { onMounted } from "vue" import { onMounted } from "vue"
import { useRoute, useRouter } from "vue-router";
import { useUsersStore } from "../stores/UsersStore.ts" import { useUsersStore } from "../stores/UsersStore.ts"
import * as authApi from "../api/AuthApi";
const store = useUsersStore() const store = useUsersStore()
const router = useRouter();
onMounted(() => { onMounted(() => {
store.fetchUsers() store.fetchUsers()
}) })
function logout() {
authApi.logout();
router.push("/login");
}
</script> </script>
<template> <template>
@@ -31,5 +39,6 @@ onMounted(() => {
</td> </td>
</tr> </tr>
</table> </table>
<button @click="logout()">Logout</button>
</div> </div>
</template> </template>

View File

@@ -2,21 +2,48 @@
// the router creates front-end endpoints and serves pages to them // the router creates front-end endpoints and serves pages to them
import { createRouter, createWebHistory } from "vue-router"; import { createRouter, createWebHistory } from "vue-router";
import LoginForm from "../pages/LoginForm.vue";
import RegisterForm from "../pages/RegisterForm.vue";
import UsersList from "../pages/UsersList.vue"; import UsersList from "../pages/UsersList.vue";
import UserForm from "../pages/UserForm.vue"; import UserForm from "../pages/UserForm.vue";
import index from "../pages/index.vue"; import index from "../pages/index.vue";
// link path to the page component // link path to the page component
const routes = [ const routes = [
{ path: "/", component: index }, { path: "/", component: index },
{ path: "/users", component: UsersList }, { path: "/login", component: LoginForm },
{ path: "/user/new", component: UserForm }, { path: "/register", component: RegisterForm },
{ path: "/user/:id", component: UserForm } { path: "/users", component: UsersList },
{ path: "/user/new", component: UserForm, meta: { requiresAuth: true } },
{ path: "/user/:id", component: UserForm, meta: { requiresAuth: true } }
]; // I really like this ]; // I really like this
const router = createRouter({ const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL), history: createWebHistory(import.meta.env.BASE_URL),
routes: routes, routes: routes,
});
// intercept before routing
router.beforeEach((to, from, next) => {
const token = localStorage.getItem("token");
if(to.meta.requiresAuth && !token) { // if the page requires use to be signed in, they must have at least a token set
next("/login");
} else {
next();
}
// TODO: if they have a token, but invalid, it will still send them to the page (the api will catch non-authorized though)
// maybe have a "validate token" from the api and refresh it if valid
/*
} else {
bool authorizedUser = authApi.refreshToken(token);
if(authorizedUser) {
next();
} else {
next("/login");
}
}
*/
}); });
export default router; export default router;

View File

@@ -6,7 +6,7 @@
import { defineStore } from "pinia"; import { defineStore } from "pinia";
import type { User } from "../models/User.ts"; import type { User } from "../models/User.ts";
import * as api from "../api/UsersApi"; import * as usersApi from "../api/UsersApi";
interface UserState { interface UserState {
users: User[]; users: User[];
@@ -23,24 +23,24 @@ export const useUsersStore = defineStore("users", {
actions: { actions: {
async fetchUsers() { async fetchUsers() {
this.loading = true; this.loading = true;
const response = await api.getUsers(); const response = await usersApi.getUsers();
this.users = response.data; this.users = response.data;
this.loading = false; this.loading = false;
}, },
async addUser(user: User) { async addUser(user: User) {
const response = await api.createUser(user); const response = await usersApi.createUser(user);
this.users.push(response.data); this.users.push(response.data);
}, },
async updateUser(id: number, user: User) { async updateUser(id: number, user: User) {
await api.updateUser(id, user); await usersApi.updateUser(id, user);
const index = this.users.findIndex(i => i.id === id); const index = this.users.findIndex(i => i.id === id);
this.users[index] = user; this.users[index] = user;
}, },
async removeUser(id: number) { async removeUser(id: number) {
await api.deleteUser(id); await usersApi.deleteUser(id);
this.users = this.users.filter(i => i.id !== id); this.users = this.users.filter(i => i.id !== id);
} }
} }