feat(story-1.2): Vue 3 SPA scaffold, base component library, User entity, SpaController
CI / test (push) Has been cancelled
CI / test (push) Has been cancelled
Frontend: - Vue 3 + Vite + TypeScript strict in frontend/; builds to public/build/ - Vue Router (hash-history, requiresAuth guard → /login) and Pinia - Global SCSS design tokens with 6 full themes (Warm Craft, Playful Pop, Sage & Cream, Dusty Mauve, Ocean Dusk, Honey & Slate) - Base components: BaseButton (5 variants), BaseInput (floating label, error state), BaseBottomSheet (slide-up, focus trap, tap-outside dismiss), BaseCard, BaseChip, BaseToast (2.5s auto-dismiss, aria-live polite), BottomNav (4 tabs, hides at 960px) - Type stubs for all API shapes: User, Device, Image, StickerLayer, RenderedAsset, Token Backend: - SpaController catch-all serves public/build/index.html; excludes api/setup/token/login/register - User entity (email+password+roles+theme); UserRepository with PasswordUpgrader - SecurityController with /login, /logout, /register stubs; Twig login form - security.yaml: form_login firewall, remember_me, role_hierarchy, access_control - Migration: create user table Verified: npm run build succeeds, GET / → 302 /login (unauthenticated) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Repository\UserRepository;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
|
||||
#[ORM\Entity(repositoryClass: UserRepository::class)]
|
||||
#[ORM\Table(name: '`user`')]
|
||||
class User implements UserInterface, PasswordAuthenticatedUserInterface
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column]
|
||||
private ?int $id = null;
|
||||
|
||||
#[ORM\Column(length: 180, unique: true)]
|
||||
private string $email = '';
|
||||
|
||||
/** @var list<string> */
|
||||
#[ORM\Column]
|
||||
private array $roles = [];
|
||||
|
||||
#[ORM\Column]
|
||||
private string $password = '';
|
||||
|
||||
#[ORM\Column(length: 50, nullable: true)]
|
||||
private ?string $theme = null;
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getEmail(): string
|
||||
{
|
||||
return $this->email;
|
||||
}
|
||||
|
||||
public function setEmail(string $email): static
|
||||
{
|
||||
$this->email = $email;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUserIdentifier(): string
|
||||
{
|
||||
return $this->email;
|
||||
}
|
||||
|
||||
/** @return list<string> */
|
||||
public function getRoles(): array
|
||||
{
|
||||
$roles = $this->roles;
|
||||
$roles[] = 'ROLE_USER';
|
||||
return array_unique($roles);
|
||||
}
|
||||
|
||||
/** @param list<string> $roles */
|
||||
public function setRoles(array $roles): static
|
||||
{
|
||||
$this->roles = $roles;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPassword(): string
|
||||
{
|
||||
return $this->password;
|
||||
}
|
||||
|
||||
public function setPassword(string $password): static
|
||||
{
|
||||
$this->password = $password;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTheme(): ?string
|
||||
{
|
||||
return $this->theme;
|
||||
}
|
||||
|
||||
public function setTheme(?string $theme): static
|
||||
{
|
||||
$this->theme = $theme;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function eraseCredentials(): void {}
|
||||
}
|
||||
Reference in New Issue
Block a user