linstrom/storage/roles.go
2024-09-17 17:11:55 +02:00

319 lines
9.9 KiB
Go

package storage
import (
"slices"
"gorm.io/gorm"
)
// 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
// 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 uint
// 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
CanSendCustomEmotes *bool
CanSendCustomReactions *bool
CanSendPublicNotes *bool
CanSendLocalNotes *bool
CanSendFollowerOnlyNotes *bool
CanSendPrivateNotes *bool
CanSendReplies *bool
CanQuote *bool
CanBoost *bool
CanIncludeLinks *bool
CanIncludeSurvey *bool
CanChangeDisplayName *bool
BlockedUsers []string `gorm:"type:bytes;serializer:gob"`
CanSubmitReports *bool
CanLogin *bool
CanMentionOthers *bool
HasMentionCountLimit *bool
MentionLimit *uint32
// CanViewBoosts *bool
// CanViewQuotes *bool
// CanViewMedia *bool
// CanViewCustomEmotes *bool
// --- Automod ---
AutoNsfwMedia *bool
AutoCwPosts *bool
AutoCwPostsText *string
ScanCreatedPublicNotes *bool
ScanCreatedLocalNotes *bool
ScanCreatedFollowerOnlyNotes *bool
ScanCreatedPrivateNotes *bool
DisallowInteractionsWith []string `gorm:"type:bytes;serializer:gob"`
WithholdNotesForManualApproval *bool
WithholdNotesBasedOnRegex *bool
WithholdNotesRegexes []string `gorm:"type:bytes;serializer:gob"`
// --- Admin perms ---
// If set, counts as all permissions being set as given and all restrictions being disabled
FullAdmin *bool
CanAffectOtherAdmins *bool
CanDeleteNotes *bool
CanConfirmWithheldNotes *bool
CanAssignRoles *bool
CanSupressInteractionsBetweenUsers *bool
CanOverwriteDisplayNames *bool
CanManageCustomEmotes *bool
CanViewDeletedNotes *bool
CanRecoverDeletedNotes *bool
CanManageAvatarDecorations *bool
CanManageAds *bool
CanSendAnnouncements *bool
}
/*
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) {
_, 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
}
newRole := Role{Name: name}
err = s.db.Create(&newRole).Error
if err != nil {
return nil, err
}
return &newRole, nil
}
func (s *Storage) FindRoleByName(name string) (*Role, error) {
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 CollapseRolesIntoOne(roles ...*Role) *Role {
// TODO: Can I make a fucking script for automating this bullshit function?
// I. Do. Not. Want. To. Manually adjust this every time I change something about Roles
startingRole := DefaultUserRole
slices.SortFunc(roles, func(a, b *Role) int {
return int(int64(a.Priority) - int64(b.Priority))
})
for _, role := range roles {
if role.CanSendMedia != nil {
*startingRole.CanSendMedia = *role.CanSendMedia
}
if role.CanSendCustomEmotes != nil {
*startingRole.CanSendCustomEmotes = *role.CanSendCustomEmotes
}
if role.CanSendCustomReactions != nil {
*startingRole.CanSendCustomReactions = *role.CanSendCustomReactions
}
if role.CanSendPublicNotes != nil {
*startingRole.CanSendPublicNotes = *role.CanSendPublicNotes
}
if role.CanSendLocalNotes != nil {
*startingRole.CanSendLocalNotes = *role.CanSendLocalNotes
}
if role.CanSendFollowerOnlyNotes != nil {
*startingRole.CanSendFollowerOnlyNotes = *role.CanSendFollowerOnlyNotes
}
if role.CanSendPrivateNotes != nil {
*startingRole.CanSendPrivateNotes = *role.CanSendPrivateNotes
}
if role.CanSendReplies != nil {
*startingRole.CanSendReplies = *role.CanSendReplies
}
if role.CanQuote != nil {
*startingRole.CanQuote = *role.CanQuote
}
if role.CanBoost != nil {
*startingRole.CanBoost = *role.CanBoost
}
if role.CanIncludeLinks != nil {
*startingRole.CanIncludeLinks = *role.CanIncludeLinks
}
if role.CanIncludeSurvey != nil {
*startingRole.CanIncludeSurvey = *role.CanIncludeSurvey
}
if role.CanChangeDisplayName != nil {
*startingRole.CanChangeDisplayName = *role.CanChangeDisplayName
}
if role.BlockedUsers != nil {
startingRole.BlockedUsers = append(startingRole.BlockedUsers, role.BlockedUsers...)
}
if role.CanSubmitReports != nil {
*startingRole.CanSubmitReports = *role.CanSubmitReports
}
if role.CanLogin != nil {
*startingRole.CanLogin = *role.CanLogin
}
if role.CanMentionOthers != nil {
*startingRole.CanMentionOthers = *role.CanMentionOthers
}
if role.HasMentionCountLimit != nil {
*startingRole.HasMentionCountLimit = *role.HasMentionCountLimit
*startingRole.MentionLimit = *role.MentionLimit
}
if role.AutoNsfwMedia != nil {
*startingRole.AutoNsfwMedia = *role.AutoNsfwMedia
}
if role.AutoCwPosts != nil {
*startingRole.AutoCwPosts = *role.AutoCwPosts
}
if role.AutoCwPostsText != nil {
*startingRole.AutoCwPostsText = *role.AutoCwPostsText
}
if role.ScanCreatedPublicNotes != nil {
*startingRole.ScanCreatedPublicNotes = *role.ScanCreatedPublicNotes
}
if role.ScanCreatedLocalNotes != nil {
*startingRole.ScanCreatedLocalNotes = *role.ScanCreatedLocalNotes
}
if role.ScanCreatedFollowerOnlyNotes != nil {
*startingRole.ScanCreatedFollowerOnlyNotes = *role.ScanCreatedFollowerOnlyNotes
}
if role.ScanCreatedPrivateNotes != nil {
*startingRole.ScanCreatedPrivateNotes = *role.ScanCreatedPrivateNotes
}
if role.DisallowInteractionsWith != nil {
startingRole.DisallowInteractionsWith = append(startingRole.DisallowInteractionsWith, role.DisallowInteractionsWith...)
}
if role.WithholdNotesForManualApproval != nil {
*startingRole.WithholdNotesForManualApproval = *role.WithholdNotesForManualApproval
}
if role.WithholdNotesBasedOnRegex != nil {
*startingRole.WithholdNotesBasedOnRegex = *role.WithholdNotesBasedOnRegex
startingRole.WithholdNotesRegexes = append(startingRole.WithholdNotesRegexes, role.WithholdNotesRegexes...)
}
if role.FullAdmin != nil {
*startingRole.FullAdmin = *role.FullAdmin
}
if role.CanAffectOtherAdmins != nil {
*startingRole.CanAffectOtherAdmins = *role.CanAffectOtherAdmins
}
if role.CanDeleteNotes != nil {
*startingRole.CanDeleteNotes = *role.CanDeleteNotes
}
if role.CanConfirmWithheldNotes != nil {
*startingRole.CanConfirmWithheldNotes = *role.CanConfirmWithheldNotes
}
if role.CanAssignRoles != nil {
*startingRole.CanAssignRoles = *role.CanAssignRoles
}
if role.CanSupressInteractionsBetweenUsers != nil {
*startingRole.CanSupressInteractionsBetweenUsers = *role.CanSupressInteractionsBetweenUsers
}
if role.CanOverwriteDisplayNames != nil {
*startingRole.CanOverwriteDisplayNames = *role.CanOverwriteDisplayNames
}
if role.CanManageCustomEmotes != nil {
*startingRole.CanManageCustomEmotes = *role.CanManageCustomEmotes
}
if role.CanViewDeletedNotes != nil {
*startingRole.CanViewDeletedNotes = *role.CanViewDeletedNotes
}
if role.CanRecoverDeletedNotes != nil {
*startingRole.CanRecoverDeletedNotes = *role.CanRecoverDeletedNotes
}
if role.CanManageAvatarDecorations != nil {
*startingRole.CanManageAvatarDecorations = *role.CanManageAvatarDecorations
}
if role.CanManageAds != nil {
*startingRole.CanManageAds = *role.CanManageAds
}
if role.CanSendAnnouncements != nil {
*startingRole.CanSendAnnouncements = *role.CanSendAnnouncements
}
}
return &startingRole
}