Files
Memoh/internal/acl/types.go
T
2026-03-14 17:15:41 +08:00

132 lines
4.6 KiB
Go

package acl
import (
"strings"
"time"
"github.com/memohai/memoh/internal/channel"
)
const (
ActionChatTrigger = "chat.trigger"
EffectAllow = "allow"
EffectDeny = "deny"
SubjectKindGuestAll = "guest_all"
SubjectKindUser = "user"
SubjectKindChannelIdentity = "channel_identity"
)
type Rule struct {
ID string `json:"id"`
BotID string `json:"bot_id"`
Action string `json:"action"`
Effect string `json:"effect"`
SubjectKind string `json:"subject_kind"`
UserID string `json:"user_id,omitempty"`
ChannelIdentityID string `json:"channel_identity_id,omitempty"`
SourceScope *SourceScope `json:"source_scope,omitempty"`
UserUsername string `json:"user_username,omitempty"`
UserDisplayName string `json:"user_display_name,omitempty"`
UserAvatarURL string `json:"user_avatar_url,omitempty"`
ChannelType string `json:"channel_type,omitempty"`
ChannelSubjectID string `json:"channel_subject_id,omitempty"`
ChannelIdentityDisplayName string `json:"channel_identity_display_name,omitempty"`
ChannelIdentityAvatarURL string `json:"channel_identity_avatar_url,omitempty"`
LinkedUserID string `json:"linked_user_id,omitempty"`
LinkedUserUsername string `json:"linked_user_username,omitempty"`
LinkedUserDisplayName string `json:"linked_user_display_name,omitempty"`
LinkedUserAvatarURL string `json:"linked_user_avatar_url,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type ListRulesResponse struct {
Items []Rule `json:"items"`
}
type SourceScope struct {
Channel string `json:"channel,omitempty"`
ConversationType string `json:"conversation_type,omitempty"`
ConversationID string `json:"conversation_id,omitempty"`
ThreadID string `json:"thread_id,omitempty"`
}
type UpsertRuleRequest struct {
UserID string `json:"user_id,omitempty"`
ChannelIdentityID string `json:"channel_identity_id,omitempty"`
SourceScope *SourceScope `json:"source_scope,omitempty"`
}
type ChatTriggerRequest struct {
BotID string
UserID string
ChannelIdentityID string
SourceScope SourceScope
}
type UserCandidate struct {
ID string `json:"id"`
Username string `json:"username"`
DisplayName string `json:"display_name"`
AvatarURL string `json:"avatar_url,omitempty"`
Email string `json:"email,omitempty"`
}
type UserCandidateListResponse struct {
Items []UserCandidate `json:"items"`
}
type ChannelIdentityCandidate struct {
ID string `json:"id"`
UserID string `json:"user_id,omitempty"`
Channel string `json:"channel"`
ChannelSubjectID string `json:"channel_subject_id"`
DisplayName string `json:"display_name,omitempty"`
AvatarURL string `json:"avatar_url,omitempty"`
LinkedUsername string `json:"linked_username,omitempty"`
LinkedDisplayName string `json:"linked_display_name,omitempty"`
LinkedAvatarURL string `json:"linked_avatar_url,omitempty"`
}
type ChannelIdentityCandidateListResponse struct {
Items []ChannelIdentityCandidate `json:"items"`
}
type ObservedConversationCandidate struct {
RouteID string `json:"route_id"`
Channel string `json:"channel"`
ConversationType string `json:"conversation_type,omitempty"`
ConversationID string `json:"conversation_id"`
ThreadID string `json:"thread_id,omitempty"`
ConversationName string `json:"conversation_name,omitempty"`
LastObservedAt time.Time `json:"last_observed_at"`
}
type ObservedConversationCandidateListResponse struct {
Items []ObservedConversationCandidate `json:"items"`
}
func (s SourceScope) Normalize() SourceScope {
scope := SourceScope{
Channel: strings.TrimSpace(s.Channel),
ConversationID: strings.TrimSpace(s.ConversationID),
ThreadID: strings.TrimSpace(s.ThreadID),
}
if raw := strings.TrimSpace(s.ConversationType); raw != "" {
scope.ConversationType = channel.NormalizeConversationType(raw)
}
if scope.ThreadID != "" && scope.ConversationType == "" {
scope.ConversationType = channel.ConversationTypeThread
}
return scope
}
func (s SourceScope) IsZero() bool {
return strings.TrimSpace(s.Channel) == "" &&
strings.TrimSpace(s.ConversationType) == "" &&
strings.TrimSpace(s.ConversationID) == "" &&
strings.TrimSpace(s.ThreadID) == ""
}