@gravito/satellite-membership 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.dockerignore +8 -0
- package/.env.example +19 -0
- package/ARCHITECTURE.md +14 -0
- package/CHANGELOG.md +14 -0
- package/Dockerfile +25 -0
- package/README.md +112 -0
- package/WHITEPAPER.md +20 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.js +1121 -0
- package/docs/EXTENDING.md +99 -0
- package/docs/PASSKEYS.md +78 -0
- package/locales/en.json +30 -0
- package/locales/zh-TW.json +30 -0
- package/package.json +35 -0
- package/src/Application/DTOs/MemberDTO.ts +34 -0
- package/src/Application/Mail/ForgotPasswordMail.ts +42 -0
- package/src/Application/Mail/MemberLevelChangedMail.ts +41 -0
- package/src/Application/Mail/WelcomeMail.ts +45 -0
- package/src/Application/Services/PasskeysService.ts +198 -0
- package/src/Application/UseCases/ForgotPassword.ts +34 -0
- package/src/Application/UseCases/LoginMember.ts +64 -0
- package/src/Application/UseCases/RegisterMember.ts +65 -0
- package/src/Application/UseCases/ResetPassword.ts +30 -0
- package/src/Application/UseCases/UpdateMemberLevel.ts +47 -0
- package/src/Application/UseCases/UpdateSettings.ts +81 -0
- package/src/Application/UseCases/VerifyEmail.ts +23 -0
- package/src/Domain/Contracts/IMemberPasskeyRepository.ts +8 -0
- package/src/Domain/Contracts/IMemberRepository.ts +11 -0
- package/src/Domain/Entities/Member.ts +219 -0
- package/src/Domain/Entities/MemberPasskey.ts +97 -0
- package/src/Infrastructure/Auth/SentinelMemberProvider.ts +52 -0
- package/src/Infrastructure/Persistence/AtlasMemberPasskeyRepository.ts +63 -0
- package/src/Infrastructure/Persistence/AtlasMemberRepository.ts +91 -0
- package/src/Infrastructure/Persistence/Migrations/20250101_create_members_table.ts +30 -0
- package/src/Infrastructure/Persistence/Migrations/20250102_create_member_passkeys_table.ts +25 -0
- package/src/Interface/Http/Controllers/PasskeyController.ts +98 -0
- package/src/Interface/Http/Middleware/VerifySingleDevice.ts +51 -0
- package/src/index.ts +234 -0
- package/src/manifest.json +15 -0
- package/tests/PasskeysService.test.ts +113 -0
- package/tests/email-integration.test.ts +161 -0
- package/tests/grand-review.ts +176 -0
- package/tests/integration.test.ts +75 -0
- package/tests/member.test.ts +47 -0
- package/tests/unit.test.ts +7 -0
- package/tests/update-settings.test.ts +101 -0
- package/tsconfig.json +26 -0
- package/views/emails/level_changed.html +35 -0
- package/views/emails/reset_password.html +34 -0
- package/views/emails/welcome.html +31 -0
package/.dockerignore
ADDED
package/.env.example
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Application
|
|
2
|
+
APP_NAME="membership"
|
|
3
|
+
APP_ENV=development
|
|
4
|
+
APP_KEY=
|
|
5
|
+
APP_DEBUG=true
|
|
6
|
+
APP_URL=http://localhost:3000
|
|
7
|
+
|
|
8
|
+
# Server
|
|
9
|
+
PORT=3000
|
|
10
|
+
|
|
11
|
+
# Database
|
|
12
|
+
DB_CONNECTION=sqlite
|
|
13
|
+
DB_DATABASE=database/database.sqlite
|
|
14
|
+
|
|
15
|
+
# Cache
|
|
16
|
+
CACHE_DRIVER=memory
|
|
17
|
+
|
|
18
|
+
# Logging
|
|
19
|
+
LOG_LEVEL=debug
|
package/ARCHITECTURE.md
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# membership Satellite Architecture
|
|
2
|
+
|
|
3
|
+
This satellite follows the Gravito Satellite Specification v1.0.
|
|
4
|
+
|
|
5
|
+
## Design
|
|
6
|
+
- **DDD**: Domain logic is separated from framework concerns.
|
|
7
|
+
- **Dogfooding**: Uses official Gravito modules (@gravito/atlas, @gravito/stasis).
|
|
8
|
+
- **Decoupled**: Inter-satellite communication happens via Contracts and Events.
|
|
9
|
+
|
|
10
|
+
## Layers
|
|
11
|
+
- **Domain**: Pure business rules.
|
|
12
|
+
- **Application**: Orchestration of domain tasks.
|
|
13
|
+
- **Infrastructure**: Implementation of persistence and external services.
|
|
14
|
+
- **Interface**: HTTP and Event entry points.
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# @gravito/satellite-membership
|
|
2
|
+
|
|
3
|
+
## 0.1.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies
|
|
8
|
+
- @gravito/atlas@1.0.1
|
|
9
|
+
- @gravito/core@1.0.0
|
|
10
|
+
- @gravito/cosmos@1.0.0
|
|
11
|
+
- @gravito/enterprise@1.0.0
|
|
12
|
+
- @gravito/sentinel@1.0.0
|
|
13
|
+
- @gravito/signal@1.0.0
|
|
14
|
+
- @gravito/stasis@1.0.0
|
package/Dockerfile
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
FROM oven/bun:1.0 AS base
|
|
2
|
+
WORKDIR /usr/src/app
|
|
3
|
+
|
|
4
|
+
# Install dependencies
|
|
5
|
+
FROM base AS install
|
|
6
|
+
RUN mkdir -p /temp/dev
|
|
7
|
+
COPY package.json bun.lockb /temp/dev/
|
|
8
|
+
RUN cd /temp/dev && bun install --frozen-lockfile
|
|
9
|
+
|
|
10
|
+
# Build application
|
|
11
|
+
FROM base AS build
|
|
12
|
+
COPY --from=install /temp/dev/node_modules node_modules
|
|
13
|
+
COPY . .
|
|
14
|
+
ENV NODE_ENV=production
|
|
15
|
+
RUN bun run build
|
|
16
|
+
|
|
17
|
+
# Final production image
|
|
18
|
+
FROM base AS release
|
|
19
|
+
COPY --from=build /usr/src/app/dist/bootstrap.js index.js
|
|
20
|
+
COPY --from=build /usr/src/app/package.json .
|
|
21
|
+
|
|
22
|
+
# Create a non-root user for security
|
|
23
|
+
USER bun
|
|
24
|
+
EXPOSE 3000/tcp
|
|
25
|
+
ENTRYPOINT [ "bun", "run", "index.js" ]
|
package/README.md
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# 🛰️ Gravito Membership Satellite
|
|
2
|
+
|
|
3
|
+
這是 Gravito 生態系中的標準會員管理衛星模組(Satellite)。基於 **DDD (領域驅動設計)** 與 **Galaxy Architecture** 構建,專為高效能、高擴展性與 Bun 原生環境優化。
|
|
4
|
+
|
|
5
|
+
## ✨ 核心功能
|
|
6
|
+
|
|
7
|
+
- **身分驗證 (Auth)**: 整合 Sentinel 模組,支援 Session 登入與 **持久化 (Remember Me)**。
|
|
8
|
+
- **註冊流程**: 包含自動生成驗證權杖與電子郵件發送 Hook。
|
|
9
|
+
- **安全防護**:
|
|
10
|
+
- **多設備登入限制 (Single Device Login)**: 可開關功能,自動註冊並踢除舊裝置。
|
|
11
|
+
- **密碼安全**: 使用 Bun 原生加密,支援自動 Rehash。
|
|
12
|
+
- **Passkeys (WebAuthn)**: 內建 Passkeys 登錄 + 登入 API,可配合 `@simplewebauthn/browser` 與瀏覽器原生驗證器。
|
|
13
|
+
- **美化郵件 (Beautiful Emails)**:
|
|
14
|
+
- 使用 Prism 模板引擎。
|
|
15
|
+
- 支援現代化 HTML 佈局。
|
|
16
|
+
- 完整多語系支持 (i18n)。
|
|
17
|
+
- **動態 Metadata**: 會員實體支援無 Schema 的元數據擴展,適合電商、訂閱制等場景。
|
|
18
|
+
|
|
19
|
+
## 🚀 快速開始
|
|
20
|
+
|
|
21
|
+
... (內容省略) ...
|
|
22
|
+
|
|
23
|
+
## 🛠️ 擴充與自定義 (DX Guide)
|
|
24
|
+
|
|
25
|
+
想要自定義品牌、覆寫郵件樣式或增加業務邏輯?請參考我們的:
|
|
26
|
+
👉 [**Membership 擴充與自定義指南 (EXTENDING.md)**](./docs/EXTENDING.md)
|
|
27
|
+
|
|
28
|
+
想要使用 Passkeys?請參考:
|
|
29
|
+
👉 [**Passkeys Integration Guide (PASSKEYS.md)**](./docs/PASSKEYS.md)
|
|
30
|
+
|
|
31
|
+
## ⚙️ 配置選項
|
|
32
|
+
|
|
33
|
+
在 `core` 配置中調整以下開關:
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
{
|
|
37
|
+
membership: {
|
|
38
|
+
auth: {
|
|
39
|
+
// 是否限制帳號只能在單一裝置登入
|
|
40
|
+
single_device: true,
|
|
41
|
+
// 是否啟用持久化登入 (Remember Me)
|
|
42
|
+
remember_me: true
|
|
43
|
+
},
|
|
44
|
+
branding: {
|
|
45
|
+
name: 'Your Project Name',
|
|
46
|
+
primary_color: '#3b82f6' // Tailwind Blue 500
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
app: {
|
|
50
|
+
url: 'https://yourapp.com'
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## 🎨 自定義模板
|
|
56
|
+
|
|
57
|
+
本模組提供預設的郵件模板。如果您想更換設計,只需在您的專案中建立以下檔案,Prism 會優先使用您的檔案:
|
|
58
|
+
|
|
59
|
+
- `views/emails/welcome.html`
|
|
60
|
+
- `views/emails/reset_password.html`
|
|
61
|
+
- `views/emails/level_changed.html`
|
|
62
|
+
|
|
63
|
+
模板中可以使用 `{{ branding.name }}` 和 `{{ branding.color }}` 來保持一致性。
|
|
64
|
+
|
|
65
|
+
本模組不強制綁定郵件驅動,而是透過 Hook 觸發動作。若您啟用了 `OrbitSignal`,本模組會自動處理以下 Hook:
|
|
66
|
+
|
|
67
|
+
- `membership:send-verification`: 發送註冊驗證郵件。
|
|
68
|
+
- `membership:send-reset-password`: 發送密碼重設郵件。
|
|
69
|
+
- `membership:level-changed`: 當會員等級提升時發送慶祝郵件。
|
|
70
|
+
|
|
71
|
+
## 📦 隊列整合 (Queue Integration)
|
|
72
|
+
|
|
73
|
+
為了獲得最佳效能,建議掛載 `OrbitStream` 來啟用非同步發信。本模組已預設呼叫 `mail.queue()`。
|
|
74
|
+
|
|
75
|
+
### 1. 安裝隊列軌道
|
|
76
|
+
```typescript
|
|
77
|
+
import { OrbitStream } from '@gravito/stream'
|
|
78
|
+
|
|
79
|
+
await core.orbit(new OrbitStream({
|
|
80
|
+
default: 'redis',
|
|
81
|
+
connections: {
|
|
82
|
+
redis: { driver: 'redis', host: 'localhost' }
|
|
83
|
+
}
|
|
84
|
+
}))
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### 2. 運作原理
|
|
88
|
+
- **有隊列時**: 郵件動作會被推入 `default` 隊列,API 請求會立即回傳。
|
|
89
|
+
- **無隊列時**: 系統會自動降級為同步發送(Sync Send),確保功能不中斷。
|
|
90
|
+
|
|
91
|
+
## 🛠️ API 使用範例
|
|
92
|
+
|
|
93
|
+
### 會員註冊
|
|
94
|
+
```typescript
|
|
95
|
+
const register = container.make('membership.register')
|
|
96
|
+
await register.execute({
|
|
97
|
+
name: 'Carl',
|
|
98
|
+
email: 'carl@example.com',
|
|
99
|
+
passwordPlain: 'secret123'
|
|
100
|
+
})
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### 多設備登入檢查 (Middleware)
|
|
104
|
+
您可以將此中間件應用於敏感路由:
|
|
105
|
+
```typescript
|
|
106
|
+
import { verifySingleDevice } from '@gravito/satellite-membership/middleware'
|
|
107
|
+
|
|
108
|
+
router.get('/profile', verifySingleDevice, (c) => { ... })
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## 📄 授權
|
|
112
|
+
MIT License
|
package/WHITEPAPER.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Whitepaper: Gravito Membership Satellite (Identity Governance)
|
|
2
|
+
**Version:** 1.0.0 | **Author:** Gravito Engineering Team
|
|
3
|
+
|
|
4
|
+
## 1. Abstract
|
|
5
|
+
Membership serves as the "Identity Anchor" managing the entire Customer Lifecycle.
|
|
6
|
+
|
|
7
|
+
## 2. Deployment & Governance Scenarios
|
|
8
|
+
|
|
9
|
+
### Case A: Tiered Marketing Synergy
|
|
10
|
+
- **Scenario**: A user completes a purchase that pushes their lifetime spend over $10,000.
|
|
11
|
+
- **Action**: Membership listens to the Commerce `commerce:order-placed` hook, upgrades the member to "Gold", and emits a `member:level-up` event.
|
|
12
|
+
- **Outcome**: The Marketing satellite automatically unlocks a 20% discount for the next visit.
|
|
13
|
+
|
|
14
|
+
### Case B: High-Security Compliance (Single Device)
|
|
15
|
+
- **Scenario**: A fintech client requires that a user can only be logged in from one device at a time.
|
|
16
|
+
- **Action**: Membership enables the `VerifySingleDevice` middleware, comparing the incoming session ID with the `current_session_id` stored in the domain entity.
|
|
17
|
+
- **Outcome**: Fraudulent concurrent sessions are automatically terminated.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
*Gravito Framework: Putting the Member at the Center of the Galaxy.*
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ServiceProvider, Container } from '@gravito/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Membership Satellite Service Provider
|
|
5
|
+
*
|
|
6
|
+
* Handles the registration and initialization of membership services.
|
|
7
|
+
* Optimized for Bun runtime with full i18n support.
|
|
8
|
+
*/
|
|
9
|
+
declare class MembershipServiceProvider extends ServiceProvider {
|
|
10
|
+
/**
|
|
11
|
+
* Register bindings in the container
|
|
12
|
+
*/
|
|
13
|
+
register(container: Container): void;
|
|
14
|
+
/**
|
|
15
|
+
* Expose migration path using Bun-native __dirname
|
|
16
|
+
*/
|
|
17
|
+
getMigrationsPath(): string;
|
|
18
|
+
/**
|
|
19
|
+
* Boot the satellite
|
|
20
|
+
* Loads local translations into the global i18n system.
|
|
21
|
+
*/
|
|
22
|
+
boot(): Promise<void>;
|
|
23
|
+
private buildPasskeysConfig;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export { MembershipServiceProvider };
|