-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathcryden.go
More file actions
224 lines (181 loc) · 7.44 KB
/
Copy pathcryden.go
File metadata and controls
224 lines (181 loc) · 7.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
// Package cryden is the main entry point for the CrydennSync authentication engine.
package cryden
import (
"context"
"database/sql"
"fmt"
"github.com/crydensync/cryden/internal/core"
"github.com/crydensync/cryden/internal/stores/memory"
"github.com/crydensync/cryden/internal/stores/sqlite"
"github.com/crydensync/cryden/internal/stores/mongodb"
"github.com/crydensync/cryden/internal/stores/postgres"
)
// Engine is the main authentication engine.
type Engine = core.Engine
// New creates an in-memory engine (perfect for testing)
func New() *Engine {
userStore := memory.NewUserStore()
sessionStore := memory.NewSessionStore()
return core.New(userStore, sessionStore)
}
// WithSQLite creates an engine with persistent SQLite storage
func WithSQLite(dbPath string) (*Engine, error) {
// Create user store (which creates/migrates DB)
userStore, err := sqlite.NewUserStore(dbPath)
if err != nil {
return nil, err
}
// Get the DB connection from user store
// You'll need to add this method to UserStore
type dbGetter interface {
GetDB() *sql.DB
}
getter, ok := userStore.(dbGetter)
if !ok {
return nil, fmt.Errorf("user store does not expose DB connection")
}
db := getter.GetDB()
// Create session store with same DB
sessionStore := sqlite.NewSessionStore(db)
return core.New(userStore, sessionStore), nil
}
// WithMongoDB creates an engine with MongoDB storage
func WithMongoDB(uri, dbName string) (*Engine, error) {
userStore, err := mongodb.NewUserStore(uri, dbName)
if err != nil {
return nil, err
}
sessionStore, err := mongodb.NewSessionStore(uri, dbName)
if err != nil {
return nil, err
}
return core.New(userStore, sessionStore), nil
}
// WithPostgreSQL creates an engine with PostgreSQL storage
func WithPostgreSQL(connStr string) (*Engine, error) {
userStore, err := postgres.NewUserStore(connStr)
if err != nil {
return nil, err
}
// Get the DB connection from user store to reuse
db := userStore.GetDB() // You'll need to add this method
sessionStore := postgres.NewSessionStore(db)
return core.New(userStore, sessionStore), nil
}
// WithFileAuditLogger sets a file-based audit logger
func WithFileAuditLogger(engine *Engine, filePath string) (*Engine, error) {
logger, err := core.NewFileAuditLogger(filePath)
if err != nil {
return nil, err
}
return engine.WithAuditLogger(logger), nil
}
// ==================== AUTHENTICATION FLOWS ====================
// SignUp creates a new user account
func SignUp(ctx context.Context, engine *Engine, email, password string) (*User, error) {
return engine.SignUp(ctx, email, password)
}
// Login authenticates a user and returns tokens
func Login(ctx context.Context, engine *Engine, email, password string, userAgent, ipAddress string) (*TokenPair, *LimitResult, error) {
deviceInfo := core.ParseUserAgent(userAgent)
return engine.Login(ctx, email, password, deviceInfo, ipAddress)
}
// Logout revokes the current session
func Logout(ctx context.Context, engine *Engine, refreshToken string) error {
return engine.Logout(ctx, refreshToken)
}
// LogoutAll revokes ALL sessions for a user
func LogoutAll(ctx context.Context, engine *Engine, userID string) error {
return engine.LogoutAll(ctx, userID)
}
// ChangePassword updates user's password and logs out all devices
func ChangePassword(ctx context.Context, engine *Engine, userID, oldPassword, newPassword string) error {
return engine.ChangePassword(ctx, userID, oldPassword, newPassword)
}
// ChangeEmail updates user's email
func ChangeEmail(ctx context.Context, engine *Engine, userID, newEmail string) error {
return engine.ChangeEmail(ctx, userID, newEmail)
}
// DeleteAccount removes user and all sessions
func DeleteAccount(ctx context.Context, engine *Engine, userID string) error {
return engine.DeleteAccount(ctx, userID)
}
// RefreshToken issues new tokens and rotates the refresh token
func RefreshToken(ctx context.Context, engine *Engine, refreshToken string) (*TokenPair, error) {
return engine.RefreshToken(ctx, refreshToken)
}
// VerifyToken validates a JWT access token and returns the user ID
func VerifyToken(engine *Engine, tokenString string) (string, error) {
claims, err := engine.VerifyToken(tokenString)
if err != nil {
return "", err
}
return claims.UserID, nil
}
// LoginWithDevice is a convenience method that extracts device from context
func LoginWithDevice(ctx context.Context, engine *Engine, email, password string, userAgent, ipAddress string) (*TokenPair, *LimitResult, error) {
return Login(ctx, engine, email, password, userAgent, ipAddress)
}
// ==================== USER MANAGEMENT ====================
// GetUser retrieves a user by ID
func GetUser(ctx context.Context, engine *Engine, userID string) (*User, error) {
return engine.GetUser(ctx, userID)
}
// GetUserByEmail retrieves a user by email
func GetUserByEmail(ctx context.Context, engine *Engine, email string) (*User, error) {
return engine.GetUserByEmail(ctx, email)
}
// ==================== SESSION MANAGEMENT ====================
// ListSessions returns all active sessions for a user
func ListSessions(ctx context.Context, engine *Engine, userID string) ([]Session, error) {
return engine.ListSessions(ctx, userID)
}
// RevokeSession manually revokes a specific session
func RevokeSession(ctx context.Context, engine *Engine, sessionID string) error {
return engine.RevokeSession(ctx, sessionID)
}
// ==================== CONFIGURATION ====================
// WithJWTSecret sets a custom JWT secret
func WithJWTSecret(engine *Engine, secret string) *Engine {
return engine.WithJWTSecret(secret)
}
// WithRateLimiter sets a custom rate limiter
func WithRateLimiter(engine *Engine, limiter RateLimiter) *Engine {
return engine.WithRateLimiter(limiter)
}
// WithAuditLogger sets a custom audit logger
func WithAuditLogger(engine *Engine, logger AuditLogger) *Engine {
return engine.WithAuditLogger(logger)
}
// WithHasher sets a custom password hasher
func WithHasher(engine *Engine, hasher Hasher) *Engine {
return engine.WithHasher(hasher)
}
// ==================== RE-EXPORTED TYPES ====================
type User = core.User
type Session = core.Session
type TokenPair = core.TokenPair
type LimitResult = core.LimitResult
type Claims = core.Claims
// Interfaces
type UserStore = core.UserStore
type SessionStore = core.SessionStore
type Hasher = core.Hasher
type RateLimiter = core.RateLimiter
type AuditLogger = core.AuditLogger
type AuditEntry = core.AuditEntry
// ==================== RE-EXPORTED ERRORS ====================
var (
ErrUserExists = core.ErrUserExists
ErrUserNotFound = core.ErrUserNotFound
ErrInvalidCredentials = core.ErrInvalidCredentials
ErrInvalidEmail = core.ErrInvalidEmail
ErrPasswordTooShort = core.ErrPasswordTooShort
ErrPasswordTooLong = core.ErrPasswordTooLong
ErrPasswordNoUpper = core.ErrPasswordNoUpper
ErrPasswordNoLower = core.ErrPasswordNoLower
ErrPasswordNoNumber = core.ErrPasswordNoNumber
ErrTooManyAttempts = core.ErrTooManyAttempts
ErrInvalidToken = core.ErrInvalidToken
ErrSessionNotFound = core.ErrSessionNotFound
)