mirror of
https://gitlab.dit.htwk-leipzig.de/htwk-software/htwkalender.git
synced 2026-01-16 11:32:26 +01:00
feat: Introduce data manager service with PocketBase authentication and professor dashboard.
This commit is contained in:
@@ -19,12 +19,14 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref, onMounted, onUnmounted } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useToast } from "primevue/usetoast";
|
||||
import LocaleSwitcher from "./LocaleSwitcher.vue";
|
||||
import DarkModeSwitcher from "./DarkModeSwitcher.vue";
|
||||
import { useRoute } from "vue-router";
|
||||
import { pb, login, logout } from "../service/pocketbase";
|
||||
|
||||
const { t } = useI18n({ useScope: "global" });
|
||||
const toast = useToast();
|
||||
|
||||
const route = useRoute();
|
||||
|
||||
@@ -98,6 +100,34 @@ const items = computed(() => {
|
||||
return menuItems;
|
||||
});
|
||||
|
||||
async function handleLogin() {
|
||||
try {
|
||||
await login();
|
||||
toast.add({
|
||||
severity: 'success',
|
||||
summary: t('toast.loginSuccess'),
|
||||
detail: t('toast.loginSuccessDetail'),
|
||||
life: 3000
|
||||
});
|
||||
} catch (error: any) {
|
||||
if (error?.message && error.message.includes('Login restricted')) {
|
||||
toast.add({
|
||||
severity: 'error',
|
||||
summary: t('toast.loginError'),
|
||||
detail: t('toast.loginRestricted'),
|
||||
life: 5000
|
||||
});
|
||||
} else {
|
||||
toast.add({
|
||||
severity: 'error',
|
||||
summary: t('toast.loginError'),
|
||||
detail: error?.message || t('toast.loginErrorDetail'),
|
||||
life: 5000
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handleDarkModeToggled(isDarkVar: boolean) {
|
||||
// Do something with isDark value
|
||||
// For example, update the root isDark value
|
||||
@@ -173,7 +203,7 @@ function handleDarkModeToggled(isDarkVar: boolean) {
|
||||
label="Login"
|
||||
icon="pi pi-sign-in"
|
||||
class="p-button-text"
|
||||
@click="login"
|
||||
@click="handleLogin"
|
||||
/>
|
||||
<Button
|
||||
v-else
|
||||
|
||||
@@ -9,6 +9,13 @@
|
||||
"description": "Dein individueller Stundenplan mit Sportevents und Prüfungen. Finde kommende Veranstaltungen oder freie Räume zum Lernen und Arbeiten.",
|
||||
"english": "Englisch",
|
||||
"german": "Deutsch",
|
||||
"toast": {
|
||||
"loginError": "Login fehlgeschlagen",
|
||||
"loginRestricted": "Login nur für Mitarbeitende der HTWK Leipzig.",
|
||||
"loginSuccess": "Login erfolgreich",
|
||||
"loginSuccessDetail": "Du kannst nun deinen Kalender erstellen.",
|
||||
"loginErrorDetail": "Fehler beim Login. Bitte versuche es erneut."
|
||||
},
|
||||
"courseSelection": {
|
||||
"headline": "Willkommen beim HTWKalender",
|
||||
"winterSemester": "Wintersemester",
|
||||
|
||||
@@ -9,6 +9,13 @@
|
||||
"description": "Your individual timetable with sports events and exams. Find upcoming events or free rooms for studying and working.",
|
||||
"english": "English",
|
||||
"german": "German",
|
||||
"toast": {
|
||||
"loginError": "login failed",
|
||||
"loginRestricted": "login restricted to htwk employees",
|
||||
"loginSuccess": "login successful",
|
||||
"loginSuccessDetail": "you can now create your calendar.",
|
||||
"loginErrorDetail": "login failed. please try again."
|
||||
},
|
||||
"courseSelection": {
|
||||
"headline": "welcome to HTWKalender",
|
||||
"winterSemester": "winter semester",
|
||||
|
||||
@@ -19,7 +19,7 @@ export const pb = new PocketBase("/");
|
||||
// Production: https://cal.htwk-leipzig.de/callback
|
||||
|
||||
export const login = async () => {
|
||||
await pb.collection('users').authWithOAuth2({ provider: 'oidc' });
|
||||
return await pb.collection('users').authWithOAuth2({ provider: 'oidc', scopes: ['openid', 'email', 'profile'] });
|
||||
}
|
||||
|
||||
export const logout = () => {
|
||||
|
||||
@@ -68,6 +68,7 @@ onMounted(async () => {
|
||||
return (b.confidenceScore || 0) - (a.confidenceScore || 0); // Descending order
|
||||
});
|
||||
|
||||
// Clear temporary entries and set actual modules
|
||||
modules.value = sortedModules;
|
||||
|
||||
// Pre-select modules with confidence score >= 0.7 (good match or better)
|
||||
@@ -77,12 +78,15 @@ onMounted(async () => {
|
||||
} catch (error: unknown) {
|
||||
console.error("Failed to fetch modules", error);
|
||||
const err = error as { status?: number; message?: string };
|
||||
// Clear temporary entries on error
|
||||
modules.value = [];
|
||||
// If unauthorized, redirect to home
|
||||
if (err.status === 401 || err.message?.includes("401")) {
|
||||
pb.authStore.clear();
|
||||
router.push("/");
|
||||
}
|
||||
} finally {
|
||||
// Always disable loading animation
|
||||
loading.value = false;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -57,6 +57,7 @@ func setupApp() *pocketbase.PocketBase {
|
||||
})
|
||||
service.AddRoutes(services)
|
||||
service.AddSchedules(services)
|
||||
service.AddHooks(app)
|
||||
|
||||
return app
|
||||
}
|
||||
|
||||
34
services/data-manager/service/hooks.go
Normal file
34
services/data-manager/service/hooks.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/pocketbase/pocketbase"
|
||||
"github.com/pocketbase/pocketbase/apis"
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
)
|
||||
|
||||
func AddHooks(app *pocketbase.PocketBase) {
|
||||
app.OnRecordAuthWithOAuth2Request("users").BindFunc(func(e *core.RecordAuthWithOAuth2RequestEvent) error {
|
||||
email := e.OAuth2User.Email
|
||||
|
||||
// If email is not in the main field, try to extract it from RawUser
|
||||
if email == "" {
|
||||
if rawEmail, ok := e.OAuth2User.RawUser["email"].(string); ok {
|
||||
email = rawEmail
|
||||
// Explicitly set the email on the OAuth2User so PocketBase uses it
|
||||
e.OAuth2User.Email = rawEmail
|
||||
}
|
||||
}
|
||||
|
||||
if email == "" {
|
||||
return apis.NewBadRequestError("No email received from OAuth2 provider. Please ensure your account has an email address and the 'email' scope is granted.", nil)
|
||||
}
|
||||
// Restrict login to @htwk-leipzig.de employees only (not students)
|
||||
if !strings.HasSuffix(email, "@htwk-leipzig.de") {
|
||||
return apis.NewBadRequestError("Login restricted to @htwk-leipzig.de emails. Students (@stud.htwk-leipzig.de) are not allowed.", nil)
|
||||
}
|
||||
|
||||
return e.Next()
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user