Replace all marketing placeholder content with real MYeasyCMS content
- Logo: Replace generic Makerkit SVG with MYeasyCMS branded logo (grid icon + styled text) - Blog: Replace 3 SaaS placeholder posts with 5 real articles (Vereinsverwaltung, SEPA, Website, DSGVO, Mitglieder-Tipps) - Changelog: Replace 6 generic entries with real feature announcements (Verbandsverwaltung, Fischerei, Dateien, Kurse, Einladungen, i18n) - Documentation: Rewrite all 20 docs from Makerkit references to MYeasyCMS content - FAQ: Replace 6 generic SaaS questions with 10 real MYeasyCMS questions - Navigation: Replace Changelog link with Contact in main nav - Footer: Reorganize into Product/Company/Legal sections - Translations: Update all EN marketing strings to match real Com.BISS content
This commit is contained in:
@@ -1,382 +1,29 @@
|
||||
---
|
||||
title: "Email & Password"
|
||||
description: "Traditional email and password authentication."
|
||||
title: "E-Mail und Passwort"
|
||||
description: "Anmeldung mit E-Mail-Adresse und Passwort — die Standard-Authentifizierung in MYeasyCMS."
|
||||
publishedAt: 2024-04-11
|
||||
order: 2
|
||||
status: "published"
|
||||
---
|
||||
|
||||
> **Note:** This is mock/placeholder content for demonstration purposes.
|
||||
Die Anmeldung mit E-Mail und Passwort ist die Standard-Authentifizierungsmethode in MYeasyCMS.
|
||||
|
||||
Email and password authentication is the traditional way users sign up and sign in.
|
||||
## Registrierung
|
||||
|
||||
## Overview
|
||||
Neue Benutzer registrieren sich mit ihrer E-Mail-Adresse und einem selbst gewählten Passwort. Nach der Registrierung wird eine Bestätigungs-E-Mail versendet.
|
||||
|
||||
Email/password authentication provides:
|
||||
- User registration with email verification
|
||||
- Secure password storage
|
||||
- Password reset functionality
|
||||
- Session management
|
||||
## Passwortanforderungen
|
||||
|
||||
## Sign Up Flow
|
||||
- Mindestens 8 Zeichen
|
||||
- Kombination aus Buchstaben und Zahlen empfohlen
|
||||
- Das Passwort kann jederzeit in den Profileinstellungen geändert werden
|
||||
|
||||
### User Registration
|
||||
## Passwort vergessen
|
||||
|
||||
```typescript
|
||||
import { signUpAction } from '~/lib/auth/actions';
|
||||
Über die "Passwort vergessen"-Funktion auf der Login-Seite kann ein neues Passwort angefordert werden. Der Benutzer erhält einen Link per E-Mail, um ein neues Passwort festzulegen.
|
||||
|
||||
const result = await signUpAction({
|
||||
email: 'user@example.com',
|
||||
password: 'SecurePassword123!',
|
||||
});
|
||||
```
|
||||
## Sicherheitshinweise
|
||||
|
||||
### Server Action Implementation
|
||||
|
||||
```typescript
|
||||
'use server';
|
||||
|
||||
import { enhanceAction } from '@kit/next/actions';
|
||||
import * as z from 'zod';
|
||||
|
||||
const SignUpSchema = z.object({
|
||||
email: z.string().email(),
|
||||
password: z.string().min(8),
|
||||
});
|
||||
|
||||
export const signUpAction = enhanceAction(
|
||||
async (data) => {
|
||||
const client = getSupabaseServerClient();
|
||||
|
||||
const { data: authData, error } = await client.auth.signUp({
|
||||
email: data.email,
|
||||
password: data.password,
|
||||
options: {
|
||||
emailRedirectTo: `${process.env.NEXT_PUBLIC_SITE_URL}/auth/callback`,
|
||||
},
|
||||
});
|
||||
|
||||
if (error) throw error;
|
||||
|
||||
return { success: true, data: authData };
|
||||
},
|
||||
{ schema: SignUpSchema }
|
||||
);
|
||||
```
|
||||
|
||||
### Sign Up Component
|
||||
|
||||
```tsx
|
||||
'use client';
|
||||
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { signUpAction } from '../_lib/actions';
|
||||
|
||||
export function SignUpForm() {
|
||||
const { register, handleSubmit, formState: { errors } } = useForm();
|
||||
|
||||
const onSubmit = async (data) => {
|
||||
const result = await signUpAction(data);
|
||||
|
||||
if (result.success) {
|
||||
toast.success('Check your email to confirm your account');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
<div>
|
||||
<label>Email</label>
|
||||
<input
|
||||
type="email"
|
||||
{...register('email', { required: true })}
|
||||
/>
|
||||
{errors.email && <span>Email is required</span>}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label>Password</label>
|
||||
<input
|
||||
type="password"
|
||||
{...register('password', { required: true, minLength: 8 })}
|
||||
/>
|
||||
{errors.password && <span>Password must be 8+ characters</span>}
|
||||
</div>
|
||||
|
||||
<button type="submit">Sign Up</button>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Sign In Flow
|
||||
|
||||
### User Login
|
||||
|
||||
```typescript
|
||||
export const signInAction = enhanceAction(
|
||||
async (data) => {
|
||||
const client = getSupabaseServerClient();
|
||||
|
||||
const { error } = await client.auth.signInWithPassword({
|
||||
email: data.email,
|
||||
password: data.password,
|
||||
});
|
||||
|
||||
if (error) throw error;
|
||||
|
||||
redirect('/home');
|
||||
},
|
||||
{ schema: SignInSchema }
|
||||
);
|
||||
```
|
||||
|
||||
### Sign In Component
|
||||
|
||||
```tsx
|
||||
'use client';
|
||||
|
||||
export function SignInForm() {
|
||||
const { register, handleSubmit } = useForm();
|
||||
|
||||
const onSubmit = async (data) => {
|
||||
try {
|
||||
await signInAction(data);
|
||||
} catch (error) {
|
||||
toast.error('Invalid email or password');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
<input
|
||||
type="email"
|
||||
{...register('email')}
|
||||
placeholder="Email"
|
||||
/>
|
||||
<input
|
||||
type="password"
|
||||
{...register('password')}
|
||||
placeholder="Password"
|
||||
/>
|
||||
<button type="submit">Sign In</button>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Email Verification
|
||||
|
||||
### Requiring Email Confirmation
|
||||
|
||||
Configure in Supabase dashboard or config:
|
||||
|
||||
```typescript
|
||||
// config/auth.config.ts
|
||||
export const authConfig = {
|
||||
requireEmailConfirmation: true,
|
||||
};
|
||||
```
|
||||
|
||||
### Handling Unconfirmed Emails
|
||||
|
||||
```typescript
|
||||
export const signInAction = enhanceAction(
|
||||
async (data) => {
|
||||
const client = getSupabaseServerClient();
|
||||
|
||||
const { data: authData, error } = await client.auth.signInWithPassword({
|
||||
email: data.email,
|
||||
password: data.password,
|
||||
});
|
||||
|
||||
if (error) {
|
||||
if (error.message.includes('Email not confirmed')) {
|
||||
return {
|
||||
success: false,
|
||||
error: 'Please confirm your email before signing in',
|
||||
};
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
|
||||
redirect('/home');
|
||||
},
|
||||
{ schema: SignInSchema }
|
||||
);
|
||||
```
|
||||
|
||||
## Password Reset
|
||||
|
||||
### Request Password Reset
|
||||
|
||||
```typescript
|
||||
export const requestPasswordResetAction = enhanceAction(
|
||||
async (data) => {
|
||||
const client = getSupabaseServerClient();
|
||||
|
||||
const { error } = await client.auth.resetPasswordForEmail(data.email, {
|
||||
redirectTo: `${process.env.NEXT_PUBLIC_SITE_URL}/auth/reset-password`,
|
||||
});
|
||||
|
||||
if (error) throw error;
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: 'Check your email for reset instructions',
|
||||
};
|
||||
},
|
||||
{
|
||||
schema: z.object({
|
||||
email: z.string().email(),
|
||||
}),
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
### Reset Password Form
|
||||
|
||||
```tsx
|
||||
'use client';
|
||||
|
||||
export function PasswordResetRequestForm() {
|
||||
const { register, handleSubmit } = useForm();
|
||||
|
||||
const onSubmit = async (data) => {
|
||||
const result = await requestPasswordResetAction(data);
|
||||
|
||||
if (result.success) {
|
||||
toast.success(result.message);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
<input
|
||||
type="email"
|
||||
{...register('email')}
|
||||
placeholder="Enter your email"
|
||||
/>
|
||||
<button type="submit">Send Reset Link</button>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Update Password
|
||||
|
||||
```typescript
|
||||
export const updatePasswordAction = enhanceAction(
|
||||
async (data) => {
|
||||
const client = getSupabaseServerClient();
|
||||
|
||||
const { error } = await client.auth.updateUser({
|
||||
password: data.newPassword,
|
||||
});
|
||||
|
||||
if (error) throw error;
|
||||
|
||||
redirect('/home');
|
||||
},
|
||||
{
|
||||
schema: z.object({
|
||||
newPassword: z.string().min(8),
|
||||
}),
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
## Password Requirements
|
||||
|
||||
### Validation Schema
|
||||
|
||||
```typescript
|
||||
const PasswordSchema = z
|
||||
.string()
|
||||
.min(8, 'Password must be at least 8 characters')
|
||||
.regex(/[A-Z]/, 'Password must contain an uppercase letter')
|
||||
.regex(/[a-z]/, 'Password must contain a lowercase letter')
|
||||
.regex(/[0-9]/, 'Password must contain a number')
|
||||
.regex(/[^A-Za-z0-9]/, 'Password must contain a special character');
|
||||
```
|
||||
|
||||
### Password Strength Indicator
|
||||
|
||||
```tsx
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
|
||||
export function PasswordInput() {
|
||||
const [password, setPassword] = useState('');
|
||||
const strength = calculatePasswordStrength(password);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<input
|
||||
type="password"
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
/>
|
||||
<div className="flex gap-1">
|
||||
{[1, 2, 3, 4].map((level) => (
|
||||
<div
|
||||
key={level}
|
||||
className={cn(
|
||||
'h-1 flex-1 rounded',
|
||||
strength >= level ? 'bg-green-500' : 'bg-gray-200'
|
||||
)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<span className="text-sm">
|
||||
{strength === 4 && 'Strong password'}
|
||||
{strength === 3 && 'Good password'}
|
||||
{strength === 2 && 'Fair password'}
|
||||
{strength === 1 && 'Weak password'}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Session Management
|
||||
|
||||
### Checking Authentication Status
|
||||
|
||||
```typescript
|
||||
import { getSupabaseServerClient } from '@kit/supabase/server-client';
|
||||
|
||||
export async function requireAuth() {
|
||||
const client = getSupabaseServerClient();
|
||||
const { data: { user } } = await client.auth.getUser();
|
||||
|
||||
if (!user) {
|
||||
redirect('/auth/sign-in');
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
```
|
||||
|
||||
### Sign Out
|
||||
|
||||
```typescript
|
||||
export const signOutAction = enhanceAction(
|
||||
async () => {
|
||||
const client = getSupabaseServerClient();
|
||||
await client.auth.signOut();
|
||||
redirect('/auth/sign-in');
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
1. **Enforce strong passwords** - Minimum 8 characters, mixed case, numbers, symbols
|
||||
2. **Rate limit login attempts** - Prevent brute force attacks
|
||||
3. **Use HTTPS only** - Encrypt data in transit
|
||||
4. **Enable email verification** - Confirm email ownership
|
||||
5. **Implement account lockout** - After failed attempts
|
||||
6. **Log authentication events** - Track sign-ins and failures
|
||||
7. **Support 2FA** - Add extra security layer
|
||||
- Verwenden Sie ein einzigartiges Passwort für MYeasyCMS
|
||||
- Geben Sie Ihre Zugangsdaten nicht an andere weiter
|
||||
- Aktivieren Sie die Multi-Faktor-Authentifizierung für zusätzliche Sicherheit
|
||||
|
||||
Reference in New Issue
Block a user