feat: Implement comprehensive member management with user accounts, roles, and password handling for admin and mobile applications.
This commit is contained in:
@@ -57,7 +57,6 @@ function ChatTabIcon({ color, focused }: { color: string; focused: boolean }) {
|
||||
|
||||
function ForcePasswordChangeScreen() {
|
||||
const { setSession, signOut } = useAuthStore()
|
||||
const [current, setCurrent] = useState('')
|
||||
const [next, setNext] = useState('')
|
||||
const [confirm, setConfirm] = useState('')
|
||||
const [loading, setLoading] = useState(false)
|
||||
@@ -65,32 +64,39 @@ function ForcePasswordChangeScreen() {
|
||||
|
||||
async function handleSubmit() {
|
||||
setError('')
|
||||
if (!current) { setError('Bitte temporäres Passwort eingeben.'); return }
|
||||
if (next.length < 8) { setError('Das neue Passwort muss mindestens 8 Zeichen haben.'); return }
|
||||
if (next !== confirm) { setError('Die Passwörter stimmen nicht überein.'); return }
|
||||
|
||||
setLoading(true)
|
||||
const result = await authClient.changePassword({ currentPassword: current, newPassword: next })
|
||||
setLoading(false)
|
||||
|
||||
if (result.error) {
|
||||
setError(result.error.message ?? 'Passwort konnte nicht geändert werden.')
|
||||
return
|
||||
}
|
||||
|
||||
// Refresh session — mustChangePassword is now false
|
||||
const sessionResult = await authClient.getSession()
|
||||
if (sessionResult?.data?.user) {
|
||||
const u = sessionResult.data.user as any
|
||||
await setSession({
|
||||
user: {
|
||||
id: u.id,
|
||||
email: u.email,
|
||||
name: u.name,
|
||||
mustChangePassword: false,
|
||||
// Set password directly via tRPC (no old password needed — user is already authenticated)
|
||||
try {
|
||||
const apiUrl = process.env.EXPO_PUBLIC_API_URL ?? 'http://localhost:3032'
|
||||
const sessionResult = await authClient.getSession()
|
||||
const token = (sessionResult?.data as any)?.session?.token
|
||||
const res = await fetch(`${apiUrl}/api/auth/force-set-password`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
...(token ? { Authorization: `Bearer ${token}` } : {}),
|
||||
},
|
||||
credentials: 'include',
|
||||
body: JSON.stringify({ newPassword: next }),
|
||||
})
|
||||
const data = await res.json()
|
||||
if (!res.ok || data.error) {
|
||||
setError(data.error ?? 'Passwort konnte nicht geändert werden.')
|
||||
setLoading(false)
|
||||
return
|
||||
}
|
||||
// Update local session state
|
||||
if (sessionResult?.data?.user) {
|
||||
const u = sessionResult.data.user as any
|
||||
await setSession({ user: { id: u.id, email: u.email, name: u.name, mustChangePassword: false } })
|
||||
}
|
||||
} catch (e) {
|
||||
setError('Verbindungsfehler. Bitte erneut versuchen.')
|
||||
}
|
||||
setLoading(false)
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -100,23 +106,11 @@ function ForcePasswordChangeScreen() {
|
||||
<View style={fpc.iconWrap}>
|
||||
<Ionicons name="lock-closed-outline" size={32} color="#003B7E" />
|
||||
</View>
|
||||
<Text style={fpc.title}>Passwort ändern</Text>
|
||||
<Text style={fpc.title}>Passwort festlegen</Text>
|
||||
<Text style={fpc.subtitle}>
|
||||
Ihr Administrator hat ein temporäres Passwort vergeben. Bitte legen Sie jetzt Ihr persönliches Passwort fest.
|
||||
Bitte legen Sie jetzt Ihr persönliches Passwort fest.
|
||||
</Text>
|
||||
|
||||
<View style={fpc.field}>
|
||||
<Text style={fpc.label}>Temporäres Passwort</Text>
|
||||
<TextInput
|
||||
style={fpc.input}
|
||||
value={current}
|
||||
onChangeText={setCurrent}
|
||||
secureTextEntry
|
||||
placeholder="••••••••"
|
||||
placeholderTextColor="#CBD5E1"
|
||||
autoCapitalize="none"
|
||||
/>
|
||||
</View>
|
||||
<View style={fpc.field}>
|
||||
<Text style={fpc.label}>Neues Passwort</Text>
|
||||
<TextInput
|
||||
@@ -166,7 +160,7 @@ function ForcePasswordChangeScreen() {
|
||||
|
||||
const fpc = StyleSheet.create({
|
||||
safe: { flex: 1, backgroundColor: '#F8FAFC' },
|
||||
content: { flex: 1, justifyContent: 'center', padding: 24 },
|
||||
content: { flexGrow: 1, justifyContent: 'center', padding: 24, paddingBottom: 40 },
|
||||
card: {
|
||||
backgroundColor: '#FFFFFF', borderRadius: 20,
|
||||
borderWidth: 1, borderColor: '#E2E8F0',
|
||||
|
||||
Reference in New Issue
Block a user