Files
Olares/cli/pkg/wizard/platform.go
eball 99176209ea cli: add user activation command (#1972)
* feat: implement SSI Authentication Client and User Store

* feat: add user activation command with validation and wizard integration

* fix: set default values for BflUrl and VaultUrl in user activation command
2025-10-23 11:03:19 +08:00

139 lines
3.9 KiB
Go

package wizard
import (
"fmt"
)
// WebPlatform implementation - based on original TypeScript WebPlatform
type WebPlatform struct {
SupportedAuthTypes []AuthType
App AppAPI // App interface, currently only interface definition
Mnemonic string // Mnemonic for real JWS signing
DID string // DID for user identification
}
func NewWebPlatform(app AppAPI) *WebPlatform {
return &WebPlatform{
SupportedAuthTypes: []AuthType{AuthTypeSSI},
App: app,
}
}
// NewWebPlatformWithMnemonic creates WebPlatform with mnemonic
func NewWebPlatformWithMnemonic(app AppAPI, mnemonic, did string) *WebPlatform {
return &WebPlatform{
SupportedAuthTypes: []AuthType{AuthTypeSSI},
App: app,
Mnemonic: mnemonic,
DID: did,
}
}
func (p *WebPlatform) getAuthClient(authType AuthType) (AuthClient, error) {
// Only support SSI authentication type
if authType != AuthTypeSSI {
return nil, fmt.Errorf("authentication type not supported: %s", authType)
}
// Check if global storage is initialized
if globalUserStore == nil {
return nil, fmt.Errorf("global stores not initialized, call InitializeGlobalStores first")
}
// Use global storage
return &SSIAuthClient{
UserStore: globalUserStore,
// JWSSigner removed as UserStore.SignJWS() is actually used
}, nil
}
func (p *WebPlatform) prepareCompleteAuthRequest(req *StartAuthRequestResponse) (map[string]any, error) {
client, err := p.getAuthClient(req.Type)
if err != nil {
return nil, NewAuthError(ErrorCodeAuthenticationFailed, "Authentication type not supported!", err)
}
return client.PrepareAuthentication(req.Data)
}
func (p *WebPlatform) StartAuthRequest(opts StartAuthRequestOptions) (*StartAuthRequestResponse, error) {
params := StartAuthRequestParams{
DID: *opts.DID,
Type: opts.Type,
SupportedTypes: p.SupportedAuthTypes,
Purpose: opts.Purpose,
AuthenticatorID: opts.AuthenticatorID,
AuthenticatorIndex: opts.AuthenticatorIndex,
}
return p.App.StartAuthRequest(params)
}
func (p *WebPlatform) CompleteAuthRequest(req *StartAuthRequestResponse) (*AuthenticateResponse, error) {
// If request already verified, return directly
if req.RequestStatus == AuthRequestStatusVerified {
return &AuthenticateResponse{
DID: req.DID,
Token: req.Token,
DeviceTrusted: req.DeviceTrusted,
AccountStatus: *req.AccountStatus,
Provisioning: *req.Provisioning,
}, nil
}
// Prepare authentication data
data, err := p.prepareCompleteAuthRequest(req)
if err != nil {
return nil, NewAuthError(ErrorCodeAuthenticationFailed, "The request was canceled.", err)
}
if data == nil {
return nil, NewAuthError(ErrorCodeAuthenticationFailed, "The request was canceled.", nil)
}
// Only support SSI authentication type, no need to handle other types
// Call App API to complete authentication
params := CompleteAuthRequestParams{
ID: req.ID,
Data: data,
DID: req.DID,
}
response, err := p.App.CompleteAuthRequest(params)
if err != nil {
return nil, err
}
return &AuthenticateResponse{
DID: req.DID,
Token: req.Token,
DeviceTrusted: response.DeviceTrusted,
AccountStatus: response.AccountStatus,
Provisioning: response.Provisioning,
}, nil
}
// Global variables
var platform Platform
var globalUserStore *UserStore
// globalJWSSigner removed as UserStore.SignJWS() is actually used
func SetPlatform(p Platform) {
platform = p
}
// InitializeGlobalStores initializes global storage
func InitializeGlobalStores(mnemonic, terminusName string) error {
// Create UserStore (contains all necessary JWS signing functionality)
userStore, err := NewUserStore(mnemonic, terminusName)
if err != nil {
return fmt.Errorf("failed to create UserStore: %w", err)
}
// Set global variables
globalUserStore = userStore
return nil
}