This commit is contained in:
2026-06-23 01:24:22 +02:00
parent e9d77fbd05
commit 5152ec0f7e
8 changed files with 110 additions and 9 deletions
+6 -2
View File
@@ -5,19 +5,23 @@
*/ */
// Composables // Composables
import { createApp } from 'vue' import {createApp} from 'vue'
// Plugins // Plugins
import { registerPlugins } from '@/plugins' import {registerPlugins} from '@/plugins'
// Components // Components
import App from './App.vue' import App from './App.vue'
// Styles // Styles
import 'unfonts.css' import 'unfonts.css'
import {useAppStore} from "@/stores/app.ts";
const app = createApp(App) const app = createApp(App)
registerPlugins(app) registerPlugins(app)
const appStore = useAppStore()
appStore.initialize()
app.mount('#app') app.mount('#app')
+38 -1
View File
@@ -1,9 +1,46 @@
// Utilities // Utilities
import {defineStore} from 'pinia' import {defineStore} from 'pinia'
import {useAuthStore} from "@/stores/auth.ts";
import {useGatewayStore} from "@/stores/gateway.ts";
import {useServerStore} from "@/stores/server.ts";
import {useCategoryStore} from "@/stores/category.ts";
import {useChannelStore} from "@/stores/channel.ts";
export const useAppStore = defineStore('app', { export const useAppStore = defineStore('app', {
state: () => ({ state: () => ({
baseurl: 'http://localhost:8080', baseurl: 'http://localhost:8080',
}), }),
actions: {} actions: {
async initialize() {
const authStore = useAuthStore()
const gatewayStore = useGatewayStore()
const serverStore = useServerStore()
const categoryStore = useCategoryStore()
const channelStore = useChannelStore()
// Définition du trigger de chargement des données de l'application
const loadAppData = async () => {
try {
await Promise.all([
serverStore.fetchServers(),
categoryStore.fetchCategories(),
channelStore.fetchChannels()
])
} catch (e) {
console.error("Erreur lors du chargement des données initiales :", e)
}
}
// On s'abonne à l'événement de connexion de la gateway
window.addEventListener('gateway:connected', loadAppData)
// Initialisation de l'authentification (qui lancera la connexion à la gateway)
await authStore.initialize()
// Sécurité : si la gateway s'est déjà connectée entre-temps
if (gatewayStore.status === 'connected') {
await loadAppData()
}
}
}
}); });
+11 -2
View File
@@ -1,6 +1,15 @@
import {defineStore} from 'pinia' import {defineStore} from 'pinia'
import {useApi} from "@/composables/useApi.ts";
export const useCategoryStore = defineStore("category", { export const useCategoryStore = defineStore("category", {
state: () => ({}), state: () => ({
actions: {} categories: []
}),
actions: {
async fetchCategories() {
let api = useApi();
let response = await api.get("/api/categories");
this.categories = await response.json();
}
}
}); });
+8 -1
View File
@@ -1,4 +1,5 @@
import {defineStore} from 'pinia' import {defineStore} from 'pinia'
import {useApi} from "@/composables/useApi.ts";
/* /*
* This file contains the store for channels. * This file contains the store for channels.
* Centralisation des channels de l'ensemble des serveurs pour faciliter l'intéraction depuis les différents éléments du site * Centralisation des channels de l'ensemble des serveurs pour faciliter l'intéraction depuis les différents éléments du site
@@ -7,5 +8,11 @@ export const useChannelStore = defineStore('channel', {
state: () => ({ state: () => ({
channels: [] channels: []
}), }),
actions: {} actions: {
async fetchChannels() {
let api = useApi();
let response = await api.get("/api/channels");
this.channels = await response.json();
}
}
}) })
+3
View File
@@ -37,6 +37,9 @@ export const useGatewayStore = defineStore('gateway', {
socket.onopen = () => { socket.onopen = () => {
this.status = 'connected' this.status = 'connected'
this.reconnectAttempts = 0 this.reconnectAttempts = 0
// Émission d'un événement global indiquant que la connexion est établie et prête
window.dispatchEvent(new CustomEvent('gateway:connected'))
} }
socket.onclose = () => { socket.onclose = () => {
+13 -2
View File
@@ -1,6 +1,17 @@
import {defineStore} from "pinia"; import {defineStore} from "pinia";
import {useApi} from "@/composables/useApi.ts";
export const useMessageStore = defineStore("message", { export const useMessageStore = defineStore("message", {
state: () => ({}), state: () => ({
actions: {} messages: []
}),
actions: {
async fetchMessages(channel_id: string) {
// todo : ici, les messages ne doivent pas être tous récupérés. Un filtre doit être appliqué.
// pour ne récupérer que les messages du channel actif
let api = useApi();
let response = await api.get("/api/messages");
this.messages = await response.json();
}
}
}); });
+8 -1
View File
@@ -1,8 +1,15 @@
import {defineStore} from "pinia"; import {defineStore} from "pinia";
import {useApi} from "@/composables/useApi.ts";
export const useServerStore = defineStore("server", { export const useServerStore = defineStore("server", {
state: () => ({ state: () => ({
servers: [] servers: []
}), }),
actions: {} actions: {
async fetchServers() {
let api = useApi();
const response = await api.get("/api/servers");
this.servers = await response.json();
}
}
}); });
+23
View File
@@ -149,3 +149,26 @@ pub async fn require_auth(req: Request<Body>, next: Next) -> Response {
HTTPError::Unauthorized.into_response() HTTPError::Unauthorized.into_response()
} }
} }
/// Middleware de sécurité qui impose que l'utilisateur soit un Superuser (administrateur).
pub async fn require_superuser(req: Request<Body>, next: Next) -> Response {
let user_opt = req
.extensions()
.get::<RequestContext>()
.and_then(|ctx| ctx.user.as_ref());
match user_opt {
Some(user) if user.is_superuser => {
// L'utilisateur est identifié ET est superuser, on continue
next.run(req).await
}
Some(_) => {
// Utilisateur connecté mais pas administrateur
HTTPError::Forbidden.into_response()
}
None => {
// Pas d'utilisateur authentifié du tout
HTTPError::Unauthorized.into_response()
}
}
}