feat: add real account workspace controls
This commit is contained in:
@@ -4,6 +4,60 @@ This document covers backend authentication integration using better-auth, inclu
|
||||
|
||||
## 1. Overview
|
||||
|
||||
### Current Project Auth Contract: Session Organization and Profile APIs
|
||||
|
||||
#### 1. Scope / Trigger
|
||||
- Trigger: app shell and account settings need authenticated current-tenant switching and current-account profile updates.
|
||||
- This repository currently uses the custom `teatea_session` HTTP-only cookie plus Drizzle tables (`sessions`, `accounts`, `organizations`, `memberships`, `roles`), not a better-auth runtime.
|
||||
|
||||
#### 2. Signatures
|
||||
- `GET /api/auth/session`: returns current account, active organization, available organization options, membership, and permissions.
|
||||
- `POST /api/auth/organization`: switches `sessions.activeOrganizationId` for the current session.
|
||||
- `PATCH /api/account/profile`: updates the authenticated account's `name` and `avatarUrl`.
|
||||
|
||||
#### 3. Contracts
|
||||
- `GET /api/auth/session` response payload:
|
||||
- `account: PublicAccount | null`
|
||||
- `organization: Organization | null`
|
||||
- `organizations: AccountOrganizationOption[]`
|
||||
- `membership: Membership | null`
|
||||
- `permissions: Permission[]`
|
||||
- `POST /api/auth/organization` request payload: `{ organizationId: string }`.
|
||||
- `PATCH /api/account/profile` request payload: `{ name: string; avatarUrl: string }`.
|
||||
- All responses use `{ success, reason, ...payload }` and `Cache-Control: no-store`.
|
||||
|
||||
#### 4. Validation & Error Matrix
|
||||
- Missing/expired session -> `success: false`, `401`, `未登录或会话已过期`.
|
||||
- Empty `organizationId` -> `success: false`, `400`, `机构不能为空`.
|
||||
- Organization not in authenticated account's available organization list -> `success: false`, `403`, `无权切换到该机构`.
|
||||
- Empty profile `name` -> `success: false`, `400`, `用户名称不能为空`.
|
||||
|
||||
#### 5. Good/Base/Bad Cases
|
||||
- Good: platform account with organization-read permission can switch among active organizations.
|
||||
- Base: organization user can switch only among active memberships.
|
||||
- Bad: never trust a client-provided organization ID without comparing against server-computed organization options.
|
||||
|
||||
#### 6. Tests Required
|
||||
- Session API asserts `organizations` includes `isActive`, `slug`, and `roleLabel`.
|
||||
- Organization switch asserts session row changes and forbidden org IDs are rejected.
|
||||
- Profile update asserts current account only is updated and audit log is recorded.
|
||||
|
||||
#### 7. Wrong vs Correct
|
||||
|
||||
Wrong:
|
||||
```typescript
|
||||
await database.update(sessions).set({ activeOrganizationId: body.organizationId });
|
||||
```
|
||||
|
||||
Correct:
|
||||
```typescript
|
||||
const target = context.organizations.find((organization) => organization.id === organizationId);
|
||||
if (!target) {
|
||||
throw new Error("无权切换到该机构");
|
||||
}
|
||||
await database.update(sessions).set({ activeOrganizationId: organizationId }).where(eq(sessions.id, context.session.id));
|
||||
```
|
||||
|
||||
### What is better-auth
|
||||
|
||||
better-auth is a modern authentication library for TypeScript applications that provides:
|
||||
|
||||
Reference in New Issue
Block a user