service

package
v1.28.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 22, 2026 License: AGPL-3.0 Imports: 34 Imported by: 0

Documentation

Index

Constants

View Source
const (
	ActivityFieldOrganizationID    = "organization_id"
	ActivityFieldOrganizationName  = "organization_name"
	ActivityFieldUserID            = "user_id"
	ActivityFieldUserName          = "user_name"
	ActivityFieldUserEmail         = "user_email"
	ActivityFieldPlan              = "plan"
	ActivityFieldOldPlan           = "old_plan"
	ActivityFieldNewPlan           = "new_plan"
	ActivityFieldBillingCycle      = "billing_cycle"
	ActivityFieldSubscriptionID    = "subscription_id"
	ActivityFieldSessionID         = "session_id"
	ActivityFieldCustomerID        = "customer_id"
	ActivityFieldInvoiceID         = "invoice_id"
	ActivityFieldAmount            = "amount"
	ActivityFieldCurrency          = "currency"
	ActivityFieldStatus            = "status"
	ActivityFieldCancelAtPeriodEnd = "cancel_at_period_end"
	ActivityFieldReason            = "reason"
	ActivityFieldError             = "error"
	ActivityFieldItemID            = "item_id"
	ActivityFieldItemType          = "item_type"
	ActivityFieldCollectionID      = "collection_id"
	ActivityFieldCollectionName    = "collection_name"
	ActivityFieldTeamID            = "team_id"
	ActivityFieldTeamName          = "team_name"
	ActivityFieldRole              = "role"
	ActivityFieldOldRole           = "old_role"
	ActivityFieldNewRole           = "new_role"
)

Activity detail field constants

View Source
const (
	PreferenceOwnerUser         = "user"
	PreferenceOwnerOrganization = "organization"
)

Variables

View Source
var (
	ErrExpiredToken    = errors.New("token expired or invalid")
	ErrUnauthorized    = errors.New("unauthorized")
	ErrInvalidPassword = errors.New("invalid password")
	ErrDeviceLimit     = errors.New("device limit exceeded for current plan")
)
View Source
var (
	ErrSubscriptionExpired = fmt.Errorf("subscription has expired")
	ErrPlanLimitReached    = fmt.Errorf("plan limit reached")
	ErrFeatureNotAvailable = fmt.Errorf("feature not available in current plan")
)
View Source
var (
	ErrInvalidRevenueCatSignature = errors.New("invalid_revenuecat_webhook_signature")
	ErrUserNotFoundForRevenueCat  = errors.New("user_not_found_for_revenuecat_event")
	ErrDefaultOrgNotFound         = errors.New("default_organization_not_found_for_user")
	ErrUnknownRevenueCatProduct   = errors.New("unknown_revenuecat_product")
)

Common errors for RevenueCat service

View Source
var (
	ErrSCIMTokenInvalid        = errors.New("invalid SCIM token")
	ErrSCIMUserNotFound        = errors.New("SCIM user not found")
	ErrSCIMGroupNotFound       = errors.New("SCIM group not found")
	ErrSCIMUserExists          = errors.New("SCIM user already exists in organization")
	ErrSCIMProvisioningBlocked = errors.New("SCIM auto-provisioning is blocked until secure org-key exchange is implemented")
)
View Source
var (
	ErrSSOConnectionNotFound  = errors.New("sso connection not found")
	ErrSSOConnectionInactive  = errors.New("sso connection is not active")
	ErrSSOInvalidState        = errors.New("invalid or expired SSO state")
	ErrSSODomainMismatch      = errors.New("email domain does not match SSO connection")
	ErrSSOProtocolMismatch    = errors.New("protocol config missing for connection type")
	ErrSSOProvisioningBlocked = errors.New("automatic provisioning requires org key exchange and is blocked")
	ErrSSOInvalidSAMLResponse = errors.New("invalid SAML response")
)
View Source
var (
	ErrCodeExpired = errors.New("verification code has expired")
	ErrCodeInvalid = errors.New("verification code is invalid")
)
View Source
var ErrInvalidStripeWebhookSignature = errors.New("invalid_stripe_webhook_signature")
View Source
var ErrShareInviteSent = errors.New("share invite email sent")

ErrShareInviteSent indicates a signup email was sent for non-registered recipient.

Functions

func CreateActivityDetails

func CreateActivityDetails(data map[string]interface{}) string

Helper function to create activity details as JSON

Types

type ActivityDetails

type ActivityDetails map[string]interface{}

ActivityDetails is a flexible map for activity details

func (ActivityDetails) ToJSON

func (d ActivityDetails) ToJSON() string

ToJSON converts activity details to JSON string

type ActivityLogger

type ActivityLogger struct {
	// contains filtered or unexported fields
}

ActivityLogger provides helper methods for logging user activities

func NewActivityLogger

func NewActivityLogger(service UserActivityService) *ActivityLogger

NewActivityLogger creates a new activity logger

func (*ActivityLogger) LogActivity

func (l *ActivityLogger) LogActivity(ctx context.Context, userID uint, activityType domain.ActivityType, ipAddress, userAgent string, details ActivityDetails) error

LogActivity logs an activity with structured details

func (*ActivityLogger) LogCheckoutCreated

func (l *ActivityLogger) LogCheckoutCreated(ctx context.Context, userID uint, ipAddress, userAgent string, orgID uint, orgName, plan, billingCycle, sessionID string)

LogCheckoutCreated logs checkout session creation

func (*ActivityLogger) LogCollectionCreated

func (l *ActivityLogger) LogCollectionCreated(ctx context.Context, userID uint, ipAddress, userAgent string, orgID uint, orgName string, collectionID uint, collectionName string)

LogCollectionCreated logs collection creation

func (*ActivityLogger) LogCollectionShared

func (l *ActivityLogger) LogCollectionShared(ctx context.Context, userID uint, ipAddress, userAgent string, orgID uint, orgName string, collectionID uint, collectionName string, sharedWithUserID uint, sharedWithUserName string)

LogCollectionShared logs collection sharing

func (*ActivityLogger) LogCustomActivity

func (l *ActivityLogger) LogCustomActivity(ctx context.Context, userID uint, activityType domain.ActivityType, ipAddress, userAgent string, details ActivityDetails)

LogCustomActivity logs a custom activity with flexible details

func (*ActivityLogger) LogError

func (l *ActivityLogger) LogError(ctx context.Context, userID uint, ipAddress, userAgent string, operation string, err error)

LogError logs an error activity

func (*ActivityLogger) LogInvoicePaid

func (l *ActivityLogger) LogInvoicePaid(ctx context.Context, userID uint, ipAddress, userAgent string, orgID uint, orgName, invoiceID string, amount int64, currency string)

LogInvoicePaid logs successful invoice payment

func (*ActivityLogger) LogInvoicePaymentFailed

func (l *ActivityLogger) LogInvoicePaymentFailed(ctx context.Context, userID uint, ipAddress, userAgent string, orgID uint, orgName, invoiceID string, amount int64, currency, reason string)

LogInvoicePaymentFailed logs failed invoice payment

func (*ActivityLogger) LogMemberRoleChanged

func (l *ActivityLogger) LogMemberRoleChanged(ctx context.Context, userID uint, ipAddress, userAgent string, orgID uint, orgName string, targetUserID uint, targetUserName, oldRole, newRole string)

LogMemberRoleChanged logs member role change

func (*ActivityLogger) LogOrganizationCreated

func (l *ActivityLogger) LogOrganizationCreated(ctx context.Context, userID uint, ipAddress, userAgent string, orgID uint, orgName, plan string)

LogOrganizationCreated logs organization creation

func (*ActivityLogger) LogOrganizationDeleted

func (l *ActivityLogger) LogOrganizationDeleted(ctx context.Context, userID uint, ipAddress, userAgent string, orgID uint, orgName string)

LogOrganizationDeleted logs organization deletion

func (*ActivityLogger) LogOrganizationDowngraded

func (l *ActivityLogger) LogOrganizationDowngraded(ctx context.Context, userID uint, ipAddress, userAgent string, orgID uint, orgName, subscriptionID, oldPlan, newPlan, reason string)

LogOrganizationDowngraded logs organization plan downgrade

func (*ActivityLogger) LogOrganizationUpgraded

func (l *ActivityLogger) LogOrganizationUpgraded(ctx context.Context, userID uint, ipAddress, userAgent string, orgID uint, orgName, subscriptionID, oldPlan, newPlan, billingCycle, status string)

LogOrganizationUpgraded logs organization plan upgrade

func (*ActivityLogger) LogSubscriptionCanceled

func (l *ActivityLogger) LogSubscriptionCanceled(ctx context.Context, userID uint, ipAddress, userAgent string, orgID uint, orgName, subscriptionID, plan string, cancelAtPeriodEnd bool)

LogSubscriptionCanceled logs subscription cancellation

func (*ActivityLogger) LogSubscriptionCreated

func (l *ActivityLogger) LogSubscriptionCreated(ctx context.Context, userID uint, ipAddress, userAgent string, orgID uint, orgName, subscriptionID, plan, billingCycle, status string)

LogSubscriptionCreated logs subscription creation

func (*ActivityLogger) LogSubscriptionReactivated

func (l *ActivityLogger) LogSubscriptionReactivated(ctx context.Context, userID uint, ipAddress, userAgent string, orgID uint, orgName, subscriptionID, plan string)

LogSubscriptionReactivated logs subscription reactivation

func (*ActivityLogger) LogSubscriptionUpdated

func (l *ActivityLogger) LogSubscriptionUpdated(ctx context.Context, userID uint, ipAddress, userAgent string, orgID uint, orgName, subscriptionID, plan, billingCycle, status string)

LogSubscriptionUpdated logs subscription update

func (*ActivityLogger) LogTeamCreated

func (l *ActivityLogger) LogTeamCreated(ctx context.Context, userID uint, ipAddress, userAgent string, orgID uint, orgName string, teamID uint, teamName string)

LogTeamCreated logs team creation

type AuthConfig

type AuthConfig struct {
	JWTSecret            string
	AccessTokenDuration  string
	RefreshTokenDuration string
}

type AuthService

type AuthService interface {
	SignUp(ctx context.Context, req *domain.SignUpRequest) (*domain.User, error)
	SignIn(ctx context.Context, creds *domain.Credentials) (*domain.AuthResponse, error)
	PreLogin(ctx context.Context, email string) (*domain.PreLoginResponse, error)
	ChangeMasterPassword(ctx context.Context, req *domain.ChangeMasterPasswordRequest) error
	RefreshToken(ctx context.Context, refreshToken string) (*domain.TokenDetails, error)
	ValidateToken(ctx context.Context, token string) (*domain.TokenClaims, error)
	IssueTokenForUser(ctx context.Context, userID uint, app string, deviceID string) (*domain.AuthResponse, error)
	// SignOut revokes only the current session (device), not all sessions.
	// Use token UUID (from JWT claims) to locate and revoke the session.
	SignOut(ctx context.Context, tokenUUID string) error
	ValidateSchema(ctx context.Context, schema string) error
}

AuthService defines the business logic for authentication

func NewAuthService

func NewAuthService(
	userRepo repository.UserRepository,
	tokenRepo repository.TokenRepository,
	verificationRepo repository.VerificationRepository,
	orgRepo repository.OrganizationRepository,
	orgUserRepo repository.OrganizationUserRepository,
	orgFolderRepo repository.OrganizationFolderRepository,
	invitationRepo repository.InvitationRepository,
	subRepo interface {
		GetByOrganizationID(ctx context.Context, orgID uint) (*domain.Subscription, error)
	},
	activityService UserActivityService,
	emailSender email.Sender,
	emailBuilder *email.EmailBuilder,
	config *AuthConfig,
	logger Logger,
) AuthService

NewAuthService creates a new authentication service

type CollectionService

type CollectionService interface {
	Create(ctx context.Context, orgID uint, userID uint, req *domain.CreateCollectionRequest) (*domain.Collection, error)
	GetByID(ctx context.Context, id uint, userID uint) (*domain.Collection, error)
	ListByOrganization(ctx context.Context, orgID uint, userID uint) ([]*domain.Collection, error)
	ListForUser(ctx context.Context, orgID uint, userID uint) ([]*domain.Collection, error)
	Update(ctx context.Context, id uint, userID uint, req *domain.UpdateCollectionRequest) (*domain.Collection, error)
	Delete(ctx context.Context, id uint, userID uint) error

	// Access management
	GrantUserAccess(ctx context.Context, collectionID uint, orgUserID uint, requestingUserID uint, req *domain.GrantCollectionAccessRequest) error
	GrantTeamAccess(ctx context.Context, collectionID uint, teamID uint, requestingUserID uint, req *domain.GrantCollectionAccessRequest) error
	RevokeUserAccess(ctx context.Context, collectionID uint, orgUserID uint, requestingUserID uint) error
	RevokeTeamAccess(ctx context.Context, collectionID uint, teamID uint, requestingUserID uint) error
	GetUserAccess(ctx context.Context, collectionID uint, requestingUserID uint) ([]*domain.CollectionUser, error)
	GetTeamAccess(ctx context.Context, collectionID uint, requestingUserID uint) ([]*domain.CollectionTeam, error)
}

CollectionService defines the business logic for collections

func NewCollectionService

func NewCollectionService(
	collectionRepo repository.CollectionRepository,
	collectionUserRepo repository.CollectionUserRepository,
	collectionTeamRepo repository.CollectionTeamRepository,
	orgUserRepo repository.OrganizationUserRepository,
	teamRepo repository.TeamRepository,
	teamUserRepo repository.TeamUserRepository,
	orgRepo repository.OrganizationRepository,
	orgItemRepo repository.OrganizationItemRepository,
	subRepo interface {
		GetByOrganizationID(ctx context.Context, orgID uint) (*domain.Subscription, error)
	},
	logger Logger,
) CollectionService

NewCollectionService creates a new collection service

type CreateItemRequest

type CreateItemRequest struct {
	ItemType   domain.ItemType     `json:"item_type" validate:"required"`
	Data       string              `json:"data" validate:"required"`
	ItemKeyEnc *string             `json:"item_key_enc,omitempty"`
	Metadata   domain.ItemMetadata `json:"metadata" validate:"required"`
	IsFavorite bool                `json:"is_favorite"`
	FolderID   *uint               `json:"folder_id,omitempty"`
	Reprompt   bool                `json:"reprompt"`
	AutoFill   *bool               `json:"auto_fill,omitempty"`
	AutoLogin  *bool               `json:"auto_login,omitempty"`
}

CreateItemRequest - Request to create an item

type CreateItemShareRequest

type CreateItemShareRequest struct {
	ItemUUID         string
	SharedWithUserID *uint
	SharedWithEmail  string
	CanView          *bool
	CanEdit          *bool
	CanShare         *bool
	EncryptedKey     string
	ExpiresAt        *time.Time
}

CreateItemShareRequest represents a request to share an organization item.

type CreateOrgItemRequest

type CreateOrgItemRequest struct {
	CollectionID *uint               `json:"collection_id,omitempty"`
	ItemType     domain.ItemType     `json:"item_type" validate:"required"`
	Data         string              `json:"data" validate:"required"` // Encrypted with Org Key
	Metadata     domain.ItemMetadata `json:"metadata" validate:"required"`
	IsFavorite   bool                `json:"is_favorite"`
	FolderID     *uint               `json:"folder_id,omitempty"`
	Reprompt     bool                `json:"reprompt"`
	AutoFill     *bool               `json:"auto_fill,omitempty"`
	AutoLogin    *bool               `json:"auto_login,omitempty"`
}

CreateOrgItemRequest for creating organization items

type ExcludedDomainService

type ExcludedDomainService interface {
	Create(ctx context.Context, userID uint, req *domain.CreateExcludedDomainRequest) (*domain.ExcludedDomain, error)
	GetByUserID(ctx context.Context, userID uint) ([]*domain.ExcludedDomain, error)
	Delete(ctx context.Context, id uint, userID uint) error
	DeleteByDomain(ctx context.Context, userID uint, domain string) error
	IsExcluded(ctx context.Context, userID uint, domain string) (bool, error)
}

ExcludedDomainService defines the business logic for excluded domains

func NewExcludedDomainService

func NewExcludedDomainService(
	repo repository.ExcludedDomainRepository,
	logger Logger,
) ExcludedDomainService

NewExcludedDomainService creates a new excluded domain service

type FeatureService

type FeatureService interface {
	CanCreateCollection(ctx context.Context, orgID uint) (bool, error)
	CanInviteUser(ctx context.Context, orgID uint) (bool, error)
	CanCreateItem(ctx context.Context, orgID uint) (bool, error)
	CanUseTeams(ctx context.Context, orgID uint) (bool, error)
	CanAccessAudit(ctx context.Context, orgID uint) (bool, error)
	CanUseSSO(ctx context.Context, orgID uint) (bool, error)
	GetFeatures(ctx context.Context, orgID uint) (*domain.PlanFeatures, error)
}

FeatureService handles feature gating based on subscription plans

func NewFeatureService

func NewFeatureService(
	orgService interface {
		GetByID(ctx context.Context, id uint, userID uint) (*domain.Organization, error)
		GetMemberCount(ctx context.Context, orgID uint) (int, error)
		GetCollectionCount(ctx context.Context, orgID uint) (int, error)
	},
	subRepo interface {
		GetByOrganizationID(ctx context.Context, orgID uint) (*domain.Subscription, error)
	},
	itemRepo interface {
		CountByOrganizationID(ctx context.Context, orgID uint) (int, error)
	},
) FeatureService

NewFeatureService creates a new feature service

type InvitationService

type InvitationService interface {
	CreateInvitation(ctx context.Context, req *domain.CreateInvitationRequest, createdBy uint, inviterName string) (*domain.Invitation, error)
	GetPendingInvitations(ctx context.Context, email string) ([]*domain.Invitation, error)
	GetSentInvitations(ctx context.Context, userID uint) ([]*domain.Invitation, error)
	AcceptInvitation(ctx context.Context, invitationID uint, userID uint) error
	DeclineInvitation(ctx context.Context, invitationID uint, userID uint) error
}

func NewInvitationService

func NewInvitationService(
	repo repository.InvitationRepository,
	userRepo repository.UserRepository,
	orgRepo repository.OrganizationRepository,
	emailSender email.Sender,
	emailBuilder *email.EmailBuilder,
	logger Logger,
) InvitationService

NewInvitationService creates a new invitation service

type ItemListResponse

type ItemListResponse struct {
	Items   []*domain.Item `json:"items"`
	Total   int64          `json:"total"`
	Page    int            `json:"page"`
	PerPage int            `json:"per_page"`
}

ItemListResponse - Paginated response

type ItemService

type ItemService interface {
	Create(ctx context.Context, schema string, req *CreateItemRequest) (*domain.Item, error)
	GetByID(ctx context.Context, schema string, id uint) (*domain.Item, error)
	GetByUUID(ctx context.Context, schema string, uuid string) (*domain.Item, error)
	GetBySupportID(ctx context.Context, schema string, supportID int64) (*domain.Item, error)
	List(ctx context.Context, schema string, filter repository.ItemFilter) (*ItemListResponse, error)
	Update(ctx context.Context, schema string, id uint, req *UpdateItemRequest) (*domain.Item, error)
	Delete(ctx context.Context, schema string, id uint) error
	HardDelete(ctx context.Context, schema string, id uint) error
}

ItemService interface for vault items

func NewItemService

func NewItemService(repo repository.ItemRepository, logger Logger) ItemService

NewItemService creates a new item service

type ItemShareService

type ItemShareService interface {
	Create(ctx context.Context, ownerID uint, req *CreateItemShareRequest) (*ItemShareWithItem, error)
	ListOwned(ctx context.Context, ownerID uint) ([]*ItemShareWithItem, error)
	ListReceived(ctx context.Context, userID uint) ([]*ItemShareWithItem, error)
	GetByUUID(ctx context.Context, userID uint, shareUUID string) (*ItemShareWithItem, error)
	Revoke(ctx context.Context, ownerID uint, shareID uint) error
	UpdateSharedItem(ctx context.Context, userID uint, shareUUID string, req *UpdateSharedItemRequest) (*domain.OrganizationItem, error)
	UpdatePermissions(ctx context.Context, ownerID uint, shareUUID string, req *UpdateItemSharePermissionsRequest) (*ItemShareWithItem, error)
	ReShare(ctx context.Context, userID uint, shareUUID string, req *CreateItemShareRequest) (*ItemShareWithItem, error)
}

ItemShareService defines the business logic for organization item sharing

func NewItemShareService

func NewItemShareService(
	shareRepo repository.ItemShareRepository,
	orgItemRepo repository.OrganizationItemRepository,
	userRepo repository.UserRepository,
	emailSender email.Sender,
	emailBuilder *email.EmailBuilder,
	logger Logger,
) ItemShareService

type ItemShareWithItem

type ItemShareWithItem struct {
	Share *domain.ItemShare
	Item  *domain.OrganizationItem
}

ItemShareWithItem bundles share + organization item data for responses.

type Logger

type Logger interface {
	Debug(msg string, keysAndValues ...interface{})
	Info(msg string, keysAndValues ...interface{})
	Infof(format string, args ...interface{})
	Warn(msg string, keysAndValues ...interface{})
	Error(msg string, keysAndValues ...interface{})
}

Logger defines the logging interface

type OrganizationFolderService

type OrganizationFolderService interface {
	ListByOrganization(ctx context.Context, orgID, userID uint) ([]*domain.OrganizationFolder, error)
	Create(ctx context.Context, orgID, userID uint, req *domain.CreateOrganizationFolderRequest) (*domain.OrganizationFolder, error)
	Update(ctx context.Context, orgID, userID, id uint, req *domain.UpdateOrganizationFolderRequest) (*domain.OrganizationFolder, error)
	Delete(ctx context.Context, orgID, userID, id uint) error
}

OrganizationFolderService defines the business logic for organization folders

type OrganizationItemService

type OrganizationItemService interface {
	Create(ctx context.Context, orgID, userID uint, req *CreateOrgItemRequest) (*domain.OrganizationItem, error)
	GetByID(ctx context.Context, id, userID uint) (*domain.OrganizationItem, error)
	ListByOrganization(ctx context.Context, orgID, userID uint, filter repository.OrganizationItemFilter) ([]*domain.OrganizationItem, int64, error)
	ListByCollection(ctx context.Context, collectionID, userID uint) ([]*domain.OrganizationItem, error)
	Update(ctx context.Context, id, userID uint, req *UpdateOrgItemRequest) (*domain.OrganizationItem, error)
	Delete(ctx context.Context, id, userID uint) (*domain.OrganizationItem, error)
}

OrganizationItemService defines the business logic for organization items (shared vault)

func NewOrganizationItemService

NewOrganizationItemService creates a new organization item service

type OrganizationService

type OrganizationService interface {
	Create(ctx context.Context, userID uint, req *domain.CreateOrganizationRequest) (*domain.Organization, error)
	GetByID(ctx context.Context, id uint, userID uint) (*domain.Organization, error)
	List(ctx context.Context, userID uint) ([]*domain.Organization, error)
	Update(ctx context.Context, id uint, userID uint, req *domain.UpdateOrganizationRequest) (*domain.Organization, error)
	Delete(ctx context.Context, id uint, userID uint) error

	// Member management
	InviteUser(ctx context.Context, orgID uint, inviterUserID uint, req *domain.InviteUserToOrgRequest) (*domain.OrganizationUser, error)
	GetMembers(ctx context.Context, orgID uint, requestingUserID uint) ([]*domain.OrganizationUser, error)
	GetMembership(ctx context.Context, userID uint, orgID uint) (*domain.OrganizationUser, error)
	UpdateMemberRole(ctx context.Context, orgID, orgUserID uint, requestingUserID uint, req *domain.UpdateOrgUserRoleRequest) error
	RemoveMember(ctx context.Context, orgID, orgUserID uint, requestingUserID uint) error
	AcceptInvitation(ctx context.Context, orgUserID uint, userID uint, encryptedOrgKey string) error
	AddExistingMember(ctx context.Context, orgUser *domain.OrganizationUser) error
	DeclineInvitationForUser(ctx context.Context, orgID uint, userID uint) error

	// Statistics
	GetMemberCount(ctx context.Context, orgID uint) (int, error)
	GetCollectionCount(ctx context.Context, orgID uint) (int, error)
}

OrganizationService defines the business logic for organizations

func NewOrganizationService

func NewOrganizationService(
	orgRepo repository.OrganizationRepository,
	orgUserRepo repository.OrganizationUserRepository,
	userRepo repository.UserRepository,
	teamRepo repository.TeamRepository,
	teamUserRepo repository.TeamUserRepository,
	collectionRepo repository.CollectionRepository,
	collectionUserRepo repository.CollectionUserRepository,
	collectionTeamRepo repository.CollectionTeamRepository,
	paymentService PaymentService,
	invitationService InvitationService,
	subRepo interface {
		Create(ctx context.Context, sub *domain.Subscription) error
		GetByOrganizationID(ctx context.Context, orgID uint) (*domain.Subscription, error)
	},
	planRepo interface {
		GetByCode(ctx context.Context, code string) (*domain.Plan, error)
	},
	logger Logger,
) OrganizationService

NewOrganizationService creates a new organization service

type PaymentService

type PaymentService interface {
	// Checkout & Subscriptions
	CreateCheckoutSession(ctx context.Context, orgID, userID uint, plan, billingCycle string, seats int, ipAddress, userAgent string) (string, error)
	HandleWebhook(ctx context.Context, payload []byte, signature string) error

	// Subscription Management
	GetBillingInfo(ctx context.Context, orgID uint) (*domain.BillingInfo, error)
	SyncSubscription(ctx context.Context, orgID uint) error // Manually sync subscription from Stripe

	// Seat management (quantity-based subscriptions)
	PreviewSeatChange(ctx context.Context, orgID, userID uint, seats int) (*domain.SeatChangePreview, error)
	UpdateSubscriptionSeats(ctx context.Context, orgID, userID uint, seats int, ipAddress, userAgent string) error

	// Plan change (inline subscription update for existing subscribers)
	PreviewPlanChange(ctx context.Context, orgID, userID uint, plan, billingCycle string, seats int) (*domain.PlanChangePreview, error)
	ChangePlan(ctx context.Context, orgID, userID uint, plan, billingCycle string, seats int, ipAddress, userAgent string) (*domain.PlanChangeResult, error)
}

PaymentService defines the business logic for Stripe payments (Organization level)

func NewPaymentService

func NewPaymentService(
	stripe *stripeClient.Client,
	orgRepo repository.OrganizationRepository,
	orgUserRepo repository.OrganizationUserRepository,
	userRepo repository.UserRepository,
	subscriptionService SubscriptionService,
	planRepo interface {
		GetByCode(ctx context.Context, code string) (*domain.Plan, error)
	},
	activityService UserActivityService,
	config *config.Config,
	logger Logger,
) PaymentService

NewPaymentService creates a new payment service

type PermissionService

type PermissionService interface {
	Can(ctx context.Context, userID uint, orgID uint, permission string) (bool, error)
	GetEffectiveRole(ctx context.Context, userID uint, orgID uint) (domain.OrganizationRole, error)
	CheckSubscriptionOverride(ctx context.Context, orgID uint) (bool, error)
	GetUserPermissions(ctx context.Context, userID uint, orgID uint) ([]string, error)
}

PermissionService handles authorization and permission checks

func NewPermissionService

func NewPermissionService(
	orgService OrganizationService,
	subRepo interface {
		GetByOrganizationID(ctx context.Context, orgID uint) (*domain.Subscription, error)
	},
) PermissionService

NewPermissionService creates a new permission service

type PreferencesService

type PreferencesService interface {
	ListForUser(ctx context.Context, userID uint, section string) ([]*domain.Preference, error)
	UpsertForUser(ctx context.Context, userID uint, req *domain.UpsertPreferencesRequest) ([]*domain.Preference, error)
}

func NewPreferencesService

func NewPreferencesService(repo repository.PreferencesRepository, logger Logger) PreferencesService

type RevenueCatService

type RevenueCatService interface {
	HandleWebhook(ctx context.Context, payload []byte, signature string) error
}

RevenueCatService handles RevenueCat webhook events for mobile subscriptions. Mobile Pro purchases create org-level subscriptions on the user's default organization.

func NewRevenueCatService

func NewRevenueCatService(
	userRepo repository.UserRepository,
	orgRepo repository.OrganizationRepository,
	subscriptionService SubscriptionService,
	planRepo interface {
		GetByCode(ctx context.Context, code string) (*domain.Plan, error)
	},
	activityService UserActivityService,
	config *config.Config,
	logger Logger,
) RevenueCatService

NewRevenueCatService creates a new RevenueCat service

type SCIMService

type SCIMService interface {
	// Token management
	CreateToken(ctx context.Context, orgID uint, req *domain.CreateSCIMTokenRequest) (*domain.SCIMTokenCreatedDTO, error)
	ListTokens(ctx context.Context, orgID uint) ([]*domain.SCIMTokenDTO, error)
	RevokeToken(ctx context.Context, orgID, tokenID uint) error
	ValidateToken(ctx context.Context, bearerToken string) (orgID uint, err error)

	// SCIM User operations
	ListUsers(ctx context.Context, orgID uint, filter string, startIndex, count int) (*domain.SCIMListResponse, error)
	GetUser(ctx context.Context, orgID uint, userID string) (*domain.SCIMUser, error)
	CreateUser(ctx context.Context, orgID uint, scimUser *domain.SCIMUser) (*domain.SCIMUser, error)
	UpdateUser(ctx context.Context, orgID uint, userID string, scimUser *domain.SCIMUser) (*domain.SCIMUser, error)
	PatchUser(ctx context.Context, orgID uint, userID string, patch *domain.SCIMPatchOp) (*domain.SCIMUser, error)
	DeleteUser(ctx context.Context, orgID uint, userID string) error

	// SCIM Group operations
	ListGroups(ctx context.Context, orgID uint, filter string, startIndex, count int) (*domain.SCIMListResponse, error)
	GetGroup(ctx context.Context, orgID uint, groupID string) (*domain.SCIMGroup, error)
	CreateGroup(ctx context.Context, orgID uint, scimGroup *domain.SCIMGroup) (*domain.SCIMGroup, error)
	UpdateGroup(ctx context.Context, orgID uint, groupID string, scimGroup *domain.SCIMGroup) (*domain.SCIMGroup, error)
	PatchGroup(ctx context.Context, orgID uint, groupID string, patch *domain.SCIMPatchOp) (*domain.SCIMGroup, error)
	DeleteGroup(ctx context.Context, orgID uint, groupID string) error
}

SCIMService handles SCIM 2.0 provisioning operations

func NewSCIMService

func NewSCIMService(
	tokenRepo repository.SCIMTokenRepository,
	userRepo repository.UserRepository,
	orgUserRepo repository.OrganizationUserRepository,
	teamRepo repository.TeamRepository,
	teamUserRepo repository.TeamUserRepository,
	logger Logger,
	baseURL string,
) SCIMService

NewSCIMService creates a new SCIM service

type SSOService

type SSOService interface {
	// Admin operations
	CreateConnection(ctx context.Context, orgID, userID uint, req *domain.CreateSSOConnectionRequest) (*domain.SSOConnection, error)
	GetConnection(ctx context.Context, id uint) (*domain.SSOConnection, error)
	ListConnections(ctx context.Context, orgID uint) ([]*domain.SSOConnection, error)
	UpdateConnection(ctx context.Context, id, userID uint, req *domain.UpdateSSOConnectionRequest) (*domain.SSOConnection, error)
	DeleteConnection(ctx context.Context, id, userID uint) error
	ActivateConnection(ctx context.Context, id, userID uint) (*domain.SSOConnection, error)

	// Authentication flows
	InitiateLogin(ctx context.Context, req *domain.SSOInitiateRequest, baseURL string) (redirectURL string, err error)
	HandleOIDCCallback(ctx context.Context, stateParam, code string) (*domain.SSOCallbackResult, error)
	HandleSAMLCallback(ctx context.Context, relayState, samlResponse string) (*domain.SSOCallbackResult, error)

	// SP metadata
	GetSPMetadata(ctx context.Context, connID uint) (string, error)
}

SSOService handles SSO connection management and authentication flows

func NewSSOService

NewSSOService creates a new SSO service

type SubscriptionService

type SubscriptionService interface {
	Create(ctx context.Context, orgID uint, planCode string, stripeSubscriptionID string, seatsPurchased *int) (*domain.Subscription, error)
	GetByID(ctx context.Context, id uint) (*domain.Subscription, error)
	GetByOrganizationID(ctx context.Context, orgID uint) (*domain.Subscription, error)
	Update(ctx context.Context, sub *domain.Subscription) error
	UpdateSeatsPurchasedByStripeSubscriptionID(ctx context.Context, stripeSubID string, seatsPurchased *int) error
	Upgrade(ctx context.Context, orgID uint, planCode string) error
	Downgrade(ctx context.Context, orgID uint, planCode string) error
	Cancel(ctx context.Context, orgID uint) error
	Resume(ctx context.Context, orgID uint) error
	Renew(ctx context.Context, subID uint) error
	HandlePaymentSuccess(ctx context.Context, stripeSubID string) error
	HandlePaymentFailed(ctx context.Context, stripeSubID string) error
	ExpireSubscription(ctx context.Context, subID uint) error
	CheckExpiredSubscriptions(ctx context.Context) error
}

SubscriptionService handles subscription operations

func NewSubscriptionService

func NewSubscriptionService(
	subRepo interface {
		ExpireActiveByOrganizationID(ctx context.Context, orgID uint, endedAt time.Time) error
		Create(ctx context.Context, sub *domain.Subscription) error
		GetByID(ctx context.Context, id uint) (*domain.Subscription, error)
		GetByOrganizationID(ctx context.Context, orgID uint) (*domain.Subscription, error)
		GetByStripeSubscriptionID(ctx context.Context, stripeSubID string) (*domain.Subscription, error)
		Update(ctx context.Context, sub *domain.Subscription) error
		ListPastDueExpired(ctx context.Context) ([]*domain.Subscription, error)
		ListCanceledExpired(ctx context.Context) ([]*domain.Subscription, error)
		ListManualExpired(ctx context.Context) ([]*domain.Subscription, error)
	},
	planRepo interface {
		GetByCode(ctx context.Context, code string) (*domain.Plan, error)
		GetByID(ctx context.Context, id uint) (*domain.Plan, error)
	},
	orgService OrganizationService,
	emailService interface {
		SendPaymentFailedEmail(ctx context.Context, sub *domain.Subscription) error
		SendSubscriptionExpiredEmail(ctx context.Context, sub *domain.Subscription) error
	},
	stripe any,
	logger Logger,
) SubscriptionService

NewSubscriptionService creates a new subscription service

type TeamService

type TeamService interface {
	Create(ctx context.Context, orgID uint, userID uint, req *domain.CreateTeamRequest) (*domain.Team, error)
	GetByID(ctx context.Context, id uint, userID uint) (*domain.Team, error)
	ListByOrganization(ctx context.Context, orgID uint, userID uint) ([]*domain.Team, error)
	Update(ctx context.Context, id uint, userID uint, req *domain.UpdateTeamRequest) (*domain.Team, error)
	Delete(ctx context.Context, id uint, userID uint) error

	// Member management
	AddMember(ctx context.Context, teamID uint, userID uint, req *domain.AddTeamUserRequest) error
	GetMembers(ctx context.Context, teamID uint, userID uint) ([]*domain.TeamUser, error)
	UpdateMember(ctx context.Context, teamID uint, teamUserID uint, userID uint, req *domain.UpdateTeamUserRequest) error
	RemoveMember(ctx context.Context, teamID uint, teamUserID uint, userID uint) error
}

TeamService defines the business logic for teams

func NewTeamService

NewTeamService creates a new team service

type UpdateItemRequest

type UpdateItemRequest struct {
	Data       *string              `json:"data,omitempty"`
	ItemKeyEnc *string              `json:"item_key_enc,omitempty"`
	Metadata   *domain.ItemMetadata `json:"metadata,omitempty"`
	IsFavorite *bool                `json:"is_favorite,omitempty"`
	FolderID   *uint                `json:"folder_id,omitempty"`
	Reprompt   *bool                `json:"reprompt,omitempty"`
	AutoFill   *bool                `json:"auto_fill,omitempty"`
	AutoLogin  *bool                `json:"auto_login,omitempty"`
}

UpdateItemRequest - Request to update an item

type UpdateItemSharePermissionsRequest

type UpdateItemSharePermissionsRequest struct {
	CanEdit        *bool
	CanShare       *bool
	ExpiresAt      *time.Time
	ClearExpiresAt bool
}

UpdateItemSharePermissionsRequest represents an owner-side update to share permissions/expiry. Note: CanView is always enforced as true for valid shares.

type UpdateOrgItemRequest

type UpdateOrgItemRequest struct {
	CollectionID *uint                `json:"collection_id,omitempty"`
	Data         *string              `json:"data,omitempty"`
	Metadata     *domain.ItemMetadata `json:"metadata,omitempty"`
	IsFavorite   *bool                `json:"is_favorite,omitempty"`
	FolderID     *uint                `json:"folder_id,omitempty"`
	Reprompt     *bool                `json:"reprompt,omitempty"`
	AutoFill     *bool                `json:"auto_fill,omitempty"`
	AutoLogin    *bool                `json:"auto_login,omitempty"`
}

UpdateOrgItemRequest for updating organization items

type UpdateSharedItemRequest

type UpdateSharedItemRequest struct {
	Data     string
	Metadata domain.ItemMetadata
}

UpdateSharedItemRequest represents updates from a share recipient.

type UserActivityService

type UserActivityService interface {
	LogActivity(ctx context.Context, req *domain.CreateActivityRequest) error
	GetUserActivities(ctx context.Context, userID uint, limit int) ([]*domain.UserActivity, error)
	GetLastSignIn(ctx context.Context, userID uint) (*domain.UserActivity, error)
	ListActivities(ctx context.Context, filter repository.ActivityFilter) ([]*domain.UserActivity, int64, error)
	ListActivitiesByUserIDs(ctx context.Context, userIDs []uint, limit int, offset int) ([]*domain.UserActivity, error)
	CleanupOldActivities(ctx context.Context, olderThan time.Duration) (int64, error)
}

UserActivityService defines the business logic for user activities

func NewUserActivityService

func NewUserActivityService(repo repository.UserActivityRepository, logger Logger) UserActivityService

NewUserActivityService creates a new user activity service

type UserAppearancePreferencesService

type UserAppearancePreferencesService interface {
	GetForUser(ctx context.Context, userID uint) (*domain.UserAppearancePreferences, error)
	UpdateForUser(ctx context.Context, userID uint, req *domain.UpdateUserAppearancePreferencesRequest) (*domain.UserAppearancePreferences, error)
}

UserAppearancePreferencesService defines business logic for appearance preferences.

func NewUserAppearancePreferencesService

func NewUserAppearancePreferencesService(
	prefs repository.PreferencesRepository,
	logger Logger,
) UserAppearancePreferencesService

type UserNotificationPreferencesService

type UserNotificationPreferencesService interface {
	GetForUser(ctx context.Context, userID uint) (*domain.UserNotificationPreferences, error)
	UpdateForUser(ctx context.Context, userID uint, req *domain.UpdateUserNotificationPreferencesRequest) (*domain.UserNotificationPreferences, error)
}

UserNotificationPreferencesService defines business logic for notification preferences.

type UserService

type UserService interface {
	GetByID(ctx context.Context, id uint) (*domain.User, error)
	GetByEmail(ctx context.Context, email string) (*domain.User, error)
	List(ctx context.Context) ([]*domain.User, error)
	Create(ctx context.Context, user *domain.User) error
	CreateByAdmin(ctx context.Context, req *domain.CreateUserByAdminRequest) (*domain.User, error)
	Update(ctx context.Context, id uint, user *domain.User) error
	Delete(ctx context.Context, id uint, schema string) error
	ChangeMasterPassword(ctx context.Context, req *domain.ChangeMasterPasswordRequest) error

	// Ownership management
	CheckOwnership(ctx context.Context, userID uint) (*domain.OwnershipCheckResult, error)
	TransferOwnership(ctx context.Context, req *domain.TransferOwnershipRequest) error
	DeleteWithOrganizations(ctx context.Context, userID uint, organizationIDs []uint, schema string) error
}

UserService defines the business logic for users

func NewUserService

NewUserService creates a new user service

type VerificationService

type VerificationService interface {
	GenerateCode(ctx context.Context, email string) (string, error)
	VerifyCode(ctx context.Context, email, code string) error
	ResendCode(ctx context.Context, email string) (string, error)
	CleanupExpiredCodes(ctx context.Context) error
}

VerificationService defines the business logic for email verification

func NewVerificationService

func NewVerificationService(
	repo repository.VerificationRepository,
	userRepo repository.UserRepository,
	logger Logger,
) VerificationService

NewVerificationService creates a new verification service

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL