More work on auth system I guess, still no motivation though
Some checks failed
/ test (push) Has been cancelled
Some checks failed
/ test (push) Has been cancelled
This commit is contained in:
parent
402932602d
commit
ab3051fa78
4 changed files with 132 additions and 12 deletions
22
README.md
22
README.md
|
@ -1,5 +1,8 @@
|
||||||
Linstrom is a new social media server with the focus on providing users, moderators and admins alike
|
# Linstrom
|
||||||
simple, yet powerful features to moderate the experience.
|
|
||||||
|
Linstrom is a new social media server with the focus on providing
|
||||||
|
users, moderators and admins alike simple, yet powerful features
|
||||||
|
to moderate the experience.
|
||||||
|
|
||||||
## Federation
|
## Federation
|
||||||
|
|
||||||
|
@ -20,3 +23,18 @@ And they all have different woes with their software.
|
||||||
I want to try and make a server that combines the strengths of various
|
I want to try and make a server that combines the strengths of various
|
||||||
project's tooling while also hopefully solving
|
project's tooling while also hopefully solving
|
||||||
some of the weaknesses.
|
some of the weaknesses.
|
||||||
|
|
||||||
|
## Permission system
|
||||||
|
|
||||||
|
All permissions operate on a role based system, similar to what Discord offers.
|
||||||
|
Accounts in power (admins and moderators) are only able to manipulate other accounts
|
||||||
|
via this role system. This prevents moderators from directly manipulating accounts,
|
||||||
|
such as changing their username, info fields or otherwise, while still providing
|
||||||
|
ample control over the activities these accounts can perform.
|
||||||
|
|
||||||
|
These same roles, while most powerful for local accounts, also apply to remote accounts
|
||||||
|
as much as realisticly possible. Preventing a login on a remote server for example
|
||||||
|
might not be possible, but blocking all inbound traffic from that account is.
|
||||||
|
|
||||||
|
However, roles are not only for moderators and admins to use.
|
||||||
|
Normal accounts can also make use of them, all be it in a more limited way.
|
||||||
|
|
12
auth/auth.go
12
auth/auth.go
|
@ -1,11 +1,17 @@
|
||||||
package auth
|
package auth
|
||||||
|
|
||||||
import "gorm.io/gorm"
|
import (
|
||||||
|
"git.mstar.dev/mstar/linstrom/storage"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
type Authentication struct {
|
type Authentication struct {
|
||||||
|
// For when in-depth access is needed
|
||||||
db *gorm.DB
|
db *gorm.DB
|
||||||
|
// Primary method to acquire account data
|
||||||
|
store *storage.Storage
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAuth(db *gorm.DB) *Authentication {
|
func NewAuth(db *gorm.DB, store *storage.Storage) *Authentication {
|
||||||
return &Authentication{db}
|
return &Authentication{db, store}
|
||||||
}
|
}
|
||||||
|
|
102
auth/checks.go
102
auth/checks.go
|
@ -1,15 +1,107 @@
|
||||||
package auth
|
package auth
|
||||||
|
|
||||||
import "git.mstar.dev/mstar/linstrom/storage"
|
import (
|
||||||
|
"git.mstar.dev/mstar/goutils/sliceutils"
|
||||||
|
"git.mstar.dev/mstar/linstrom/storage"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
)
|
||||||
|
|
||||||
// Can actorId access the account with targetId?
|
// Can actorId read the account with targetId?
|
||||||
func (a *Authentication) CanAccessAccount(actorId *string, targetId string) bool { return true }
|
func (a *Authentication) CanReadAccount(actorId *string, targetId string) bool {
|
||||||
|
targetAccount, err := a.store.FindAccountById(targetId)
|
||||||
|
if err != nil {
|
||||||
|
if err == storage.ErrEntryNotFound {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
log.Error().
|
||||||
|
Err(err).
|
||||||
|
Str("account-id", targetId).
|
||||||
|
Msg("Failed to receive account for permission check")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if actorId == nil {
|
||||||
|
// TODO: Decide if roles should have a field to declare an account as follow only/hidden
|
||||||
|
// and then check for that flag here
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
roles, err := a.store.FindRolesByNames(targetAccount.Roles)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().
|
||||||
|
Err(err).
|
||||||
|
Strs("role-names", targetAccount.Roles).
|
||||||
|
Msg("Failed to get roles for target account")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
combined := storage.CollapseRolesIntoOne(roles...)
|
||||||
|
if sliceutils.Contains(combined.BlockedUsers, *actorId) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// Can actorId edit the account with targetId?
|
// Can actorId edit the account with targetId?
|
||||||
func (a *Authentication) CanEditAccount(actorId *string, targetIt *string) bool { return true }
|
// If actorId is nil, it is assumed to be an anonymous user trying to edit the target account
|
||||||
|
// if targetId is nil, it is assumed that the actor is editing themselves
|
||||||
|
func (a *Authentication) CanEditAccount(actorId *string, targetId *string) bool {
|
||||||
|
// FIXME: This entire function feels wrong, idk
|
||||||
|
// Only the owner of an account should be able to edit said account's data
|
||||||
|
// But how do moderation actions play with this? Do they count as edit or as something separate?
|
||||||
|
if actorId == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if targetId == nil {
|
||||||
|
targetId = actorId
|
||||||
|
}
|
||||||
|
targetAccount, err := a.store.FindAccountById(*targetId)
|
||||||
|
if err != nil {
|
||||||
|
if err != storage.ErrEntryNotFound {
|
||||||
|
log.Error().
|
||||||
|
Err(err).
|
||||||
|
Str("target-id", *targetId).
|
||||||
|
Msg("Failed to receive account for permission checks")
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if targetId == actorId {
|
||||||
|
targetRoles, err := a.store.FindRolesByNames(targetAccount.Roles)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().
|
||||||
|
Err(err).
|
||||||
|
Strs("role-names", targetAccount.Roles).
|
||||||
|
Msg("Failed to get roles from storage")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
combined := storage.CollapseRolesIntoOne(targetRoles...)
|
||||||
|
return *combined.CanLogin
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Can actorId delete the account with targetId?
|
// Can actorId delete the account with targetId?
|
||||||
func (a *Authentication) CanDeleteAccount(actorId *string, targetIt *string) bool { return true }
|
// If actorId is nil, it is assumed to be an anonymous user trying to delete the target account
|
||||||
|
// if targetId is nil, it is assumed that the actor is deleting themselves
|
||||||
|
func (a *Authentication) CanDeleteAccount(actorId *string, targetId *string) bool {
|
||||||
|
if actorId == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
acc, err := a.store.FindAccountById(*actorId)
|
||||||
|
if err != nil {
|
||||||
|
// TODO: Logging
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
roles, err := a.store.FindRolesByNames(acc.Roles)
|
||||||
|
if err != nil {
|
||||||
|
// TODO: Logging
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
collapsed := storage.CollapseRolesIntoOne(roles...)
|
||||||
|
if targetId == nil {
|
||||||
|
return *collapsed.CanLogin
|
||||||
|
} else {
|
||||||
|
return *collapsed.CanDeleteAccounts
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Can actorId create a new post at all?
|
// Can actorId create a new post at all?
|
||||||
// Specific restrictions regarding the content are not checked
|
// Specific restrictions regarding the content are not checked
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package storage
|
package storage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/rs/zerolog/log"
|
|
||||||
"git.mstar.dev/mstar/goutils/sliceutils"
|
"git.mstar.dev/mstar/goutils/sliceutils"
|
||||||
"git.mstar.dev/mstar/linstrom/util"
|
"git.mstar.dev/mstar/linstrom/util"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -80,7 +80,10 @@ type Role struct {
|
||||||
// Internal ids of accounts blocked by this role
|
// Internal ids of accounts blocked by this role
|
||||||
BlockedUsers []string `gorm:"type:bytes;serializer:gob"` // Local
|
BlockedUsers []string `gorm:"type:bytes;serializer:gob"` // Local
|
||||||
CanSubmitReports *bool // Local & remote
|
CanSubmitReports *bool // Local & remote
|
||||||
CanLogin *bool // Local
|
// If disabled, an account can no longer be interacted with. The owner can no longer change anything about it
|
||||||
|
// And the UI will show a notice (and maybe include that info in the AP data too)
|
||||||
|
// Only moderators and admins will be able to edit the account's roles
|
||||||
|
CanLogin *bool // Local
|
||||||
|
|
||||||
CanMentionOthers *bool // Local & remote
|
CanMentionOthers *bool // Local & remote
|
||||||
HasMentionCountLimit *bool // Local & remote
|
HasMentionCountLimit *bool // Local & remote
|
||||||
|
@ -125,6 +128,7 @@ type Role struct {
|
||||||
CanManageAvatarDecorations *bool // Local
|
CanManageAvatarDecorations *bool // Local
|
||||||
CanManageAds *bool // Local
|
CanManageAds *bool // Local
|
||||||
CanSendAnnouncements *bool // Local
|
CanSendAnnouncements *bool // Local
|
||||||
|
CanDeleteAccounts *bool // Local
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in a new issue