Consolidates the previously separate omsorgapp and omsorgCore repos (each had their own nested .git with GitHub history) plus the old root-level website/mitarbeiter-app into a single monorepo, matching the structure already documented in the root CLAUDE.md. Also moves the PHP employee app aside as omsorgWeb/mitarbeiter-app-legacy/ to serve as a template for a ground-up rewrite. Fixes .gitignore in the same pass: the config-secrets/uploads/data patterns were unanchored (relative to repo root, not depth-agnostic), so they silently stopped matching once the app moved under omsorgWeb/. Patterns are now **/-prefixed and cover both mitarbeiter-app and mitarbeiter-app-legacy, keeping DB/SMTP credentials and uploaded employee documents out of version control. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
83 lines
2.5 KiB
React
83 lines
2.5 KiB
React
import { createContext, useContext, useEffect, useState, useCallback } from "react";
|
|
|
|
const AuthContext = createContext(null);
|
|
|
|
export function AuthProvider({ children }) {
|
|
const [isAuthenticated, setIsAuthenticated] = useState(false);
|
|
const [user, setUser] = useState(null);
|
|
const [isLoading, setIsLoading] = useState(true);
|
|
const [mustChangePassword, setMustChangePassword] = useState(false);
|
|
|
|
useEffect(() => {
|
|
let cancelled = false;
|
|
|
|
window.omsorg.auth.getSession().then((session) => {
|
|
if (cancelled) return;
|
|
setIsAuthenticated(session.isAuthenticated);
|
|
setUser(session.user);
|
|
setMustChangePassword(!!session.mustChangePassword);
|
|
setIsLoading(false);
|
|
});
|
|
|
|
const unsubscribe = window.omsorg.auth.onSessionChanged((session) => {
|
|
setIsAuthenticated(session.isAuthenticated);
|
|
setUser(session.user);
|
|
setMustChangePassword(!!session.mustChangePassword);
|
|
setIsLoading(false);
|
|
});
|
|
|
|
return () => {
|
|
cancelled = true;
|
|
unsubscribe();
|
|
};
|
|
}, []);
|
|
|
|
const login = useCallback(async (username, password) => {
|
|
const result = await window.omsorg.auth.login(username, password);
|
|
if (result.success) {
|
|
setIsAuthenticated(true);
|
|
setUser(result.user);
|
|
setMustChangePassword(!!result.mustChangePassword);
|
|
}
|
|
return result;
|
|
}, []);
|
|
|
|
const logout = useCallback(async () => {
|
|
await window.omsorg.auth.logout();
|
|
setIsAuthenticated(false);
|
|
setUser(null);
|
|
setMustChangePassword(false);
|
|
}, []);
|
|
|
|
const changePassword = useCallback(async (currentPassword, newPassword) => {
|
|
const result = await window.omsorg.auth.changePassword(currentPassword, newPassword);
|
|
if (result.success) {
|
|
// Serverseitig wurden alle Sessions widerrufen (siehe UserService.ChangeOwnPasswordAsync) -
|
|
// der aktuelle Access-Token ist schon tot, also lokal neu einloggen lassen statt weiterzumachen.
|
|
setIsAuthenticated(false);
|
|
setUser(null);
|
|
setMustChangePassword(false);
|
|
}
|
|
return result;
|
|
}, []);
|
|
|
|
const hasPermission = useCallback(
|
|
(module, action) => !!user?.permissions?.some((p) => p.module === module && p.action === action),
|
|
[user]
|
|
);
|
|
|
|
return (
|
|
<AuthContext.Provider
|
|
value={{ isAuthenticated, user, isLoading, mustChangePassword, login, logout, changePassword, hasPermission }}
|
|
>
|
|
{children}
|
|
</AuthContext.Provider>
|
|
);
|
|
}
|
|
|
|
export function useAuth() {
|
|
const ctx = useContext(AuthContext);
|
|
if (!ctx) throw new Error("useAuth muss innerhalb von AuthProvider verwendet werden");
|
|
return ctx;
|
|
}
|