mStar
575392d6d4
New error is for indicating actions that are not ever allowed, even for admins And you can now delete roles
230 lines
7.4 KiB
Go
230 lines
7.4 KiB
Go
package storage
|
|
|
|
import (
|
|
"github.com/rs/zerolog/log"
|
|
"gitlab.com/mstarongitlab/goutils/sliceutils"
|
|
"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
|
|
}
|
|
|
|
func (s *Storage) DeleteRoleByName(name string) error {
|
|
// Prevent deletion of built-in roles
|
|
if sliceutils.Contains(
|
|
sliceutils.Map(allDefaultRoles, func(t *Role) string { return t.Name }),
|
|
name,
|
|
) {
|
|
return ErrNotAllowed
|
|
}
|
|
defer util.Untrace(util.Trace(&log.Logger))
|
|
return s.db.Where(&Role{Name: name, IsBuiltIn: false}).Delete(&Role{}).Error
|
|
}
|