package storage import ( "github.com/rs/zerolog/log" "gitlab.com/mstarongitlab/linstrom/util" "gorm.io/gorm" ) //go:generate go build -o RolesGenerator ../cmd/RolesGenerator/main.go //go:generate ./RolesGenerator -input=roles.go -output=rolesUtil_generated.go //go:generate rm RolesGenerator // A role is, in concept, similar to how Discord handles roles // Some permission can be either disallowed (&false), don't care (nil) or allowed (&true) // Don't care just says to use the value from the next lower role where it is set type Role struct { // TODO: More control options // Extend upon whatever Masto, Akkoma and Misskey have // Lots of details please // --- Role metadata --- // Include full db model stuff gorm.Model // Name of the role Name string `gorm:"primaryKey;unique"` // Priority of the role // Lower priority gets applied first and thus overwritten by higher priority ones // If two roles have the same priority, the order is undetermined and may be random // Default priority for new roles is 1 to always overwrite default user // And full admin has max priority possible Priority uint32 // Whether this role is for a for a single user only (like custom, per user permissions in Discord) // If yes, Name will be the id of the user in question IsUserRole bool // Whether this role is one built into Linstrom from the start or not // Note: Built-in roles can't be modified IsBuiltIn bool // --- User permissions --- CanSendMedia *bool // Local & remote CanSendCustomEmotes *bool // Local & remote CanSendCustomReactions *bool // Local & remote CanSendPublicNotes *bool // Local & remote CanSendLocalNotes *bool // Local & remote CanSendFollowerOnlyNotes *bool // Local & remote CanSendPrivateNotes *bool // Local & remote CanSendReplies *bool // Local & remote CanQuote *bool // Local only CanBoost *bool // Local only CanIncludeLinks *bool // Local & remote CanIncludeSurvey *bool // Local CanFederateFedi *bool // Local & remote CanFederateBsky *bool // Local CanChangeDisplayName *bool // Local // Internal ids of accounts blocked by this role BlockedUsers []string `gorm:"type:bytes;serializer:gob"` // Local CanSubmitReports *bool // Local & remote CanLogin *bool // Local CanMentionOthers *bool // Local & remote HasMentionCountLimit *bool // Local & remote MentionLimit *uint32 // Local & remote // CanViewBoosts *bool // CanViewQuotes *bool // CanViewMedia *bool // CanViewCustomEmotes *bool // --- Automod --- AutoNsfwMedia *bool // Local & remote AutoCwPosts *bool // Local & remote AutoCwPostsText *string // Local & remote ScanCreatedPublicNotes *bool // Local & remote ScanCreatedLocalNotes *bool // Local & remote ScanCreatedFollowerOnlyNotes *bool // Local & remote ScanCreatedPrivateNotes *bool // Local & remote // Blocks all interactions and federation between users with the role and all included ids/handles // TODO: Decide whether this is a list of handles or of account ids // Handles would increase the load due to having to search for them first // while ids would require to store every single account mentioned // which could cause escalating storage costs DisallowInteractionsWith []string `gorm:"type:bytes;serializer:gob"` // Local & remote WithholdNotesForManualApproval *bool // Local & remote WithholdNotesBasedOnRegex *bool // Local & remote WithholdNotesRegexes []string `gorm:"type:bytes;serializer:gob"` // Local & remote // --- Admin perms --- // If set, counts as all permissions being set as given and all restrictions being disabled FullAdmin *bool // Local CanAffectOtherAdmins *bool // Local CanDeleteNotes *bool // Local CanConfirmWithheldNotes *bool // Local CanAssignRoles *bool // Local CanSupressInteractionsBetweenUsers *bool // Local CanOverwriteDisplayNames *bool // Local CanManageCustomEmotes *bool // Local CanViewDeletedNotes *bool // Local CanRecoverDeletedNotes *bool // Local CanManageAvatarDecorations *bool // Local CanManageAds *bool // Local CanSendAnnouncements *bool // Local } /* Mastodon permissions (highest permission to lowest): - Admin - Devops - View Audit log - View Dashboard - Manage Reports - Manage Federation - Manage Settings - Manage Blocks - Manage Taxonomies - Manage Appeals - Manage Users - Manage Invites - Manage Rules - Manage Announcements - Manage Custom Emojis - Manage Webhooks - Invite Users - Manage Roles - Manage User Access - Delete User Data */ /* Misskey "permissions" (no order): - Global timeline available (interact with global timeline I think) - Local timeline available (same as global, but for local) - b-something timeline available - Can send public notes - How many mentions a note can have - Can invite others - How many invites can be sent - InviteLimitCycle (whatever that means) - Invite Expiration time (duration of how long invites stay valid I think) - Manage custom emojis - Manage custom avatar decorations - Seach for notes - Use translator - Hide ads from self - How much storage space the user has - Whether to mark all posts from account as nsfw - max number of pinned messages - max number of antennas - max number of muted words - max number of webhooks - max number of clips - max number of notes contained in a clip (? I think. Don't know enough about clips) - Max number of lists of users - max number of users in a user list - rate limit multiplier - max number of applied avatar decorations */ func (s *Storage) NewEmptyRole(name string) (*Role, error) { defer util.Untrace(util.Trace(&log.Logger)) // Check if a role with the given name already exists _, err := s.FindRoleByName(name) switch err { case nil: return nil, ErrEntryAlreadyExists case ErrEntryNotFound: // Empty case, since this is what we want default: return nil, err } // New roles have a priority of 1 by default newRole := Role{Name: name, Priority: 1} err = s.db.Create(&newRole).Error if err != nil { return nil, err } return &newRole, nil } func (s *Storage) FindRoleByName(name string) (*Role, error) { defer util.Untrace(util.Trace(&log.Logger)) role := Role{} err := s.db.Where("name = ?", name).First(&role).Error switch err { case nil: return &role, nil case gorm.ErrRecordNotFound: return nil, ErrEntryNotFound default: return nil, err } } func (s *Storage) FindRolesByNames(names []string) ([]Role, error) { defer util.Untrace(util.Trace(&log.Logger)) roles := []Role{} err := s.db.Where("name IN ?", names).Find(&roles).Error switch err { case nil: return roles, nil case gorm.ErrRecordNotFound: return nil, ErrEntryNotFound default: return nil, err } } func (s *Storage) UpdateRole(role *Role) error { defer util.Untrace(util.Trace(&log.Logger)) return s.db.Save(role).Error }