WebAdmin: allow to pre-select groups on add user page

The admin will still be able to choose different groups

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
Nicola Murino
2022-09-13 18:04:27 +02:00
parent bd585d8e52
commit ea3c1d7a3b
24 changed files with 1320 additions and 203 deletions

View File

@@ -35,7 +35,7 @@ import (
)
const (
boltDatabaseVersion = 21
boltDatabaseVersion = 22
)
var (
@@ -372,6 +372,10 @@ func (p *BoltProvider) addAdmin(admin *Admin) error {
if err != nil {
return err
}
groupBucket, err := p.getGroupsBucket(tx)
if err != nil {
return err
}
if a := bucket.Get([]byte(admin.Username)); a != nil {
return fmt.Errorf("admin %v already exists", admin.Username)
}
@@ -383,6 +387,12 @@ func (p *BoltProvider) addAdmin(admin *Admin) error {
admin.LastLogin = 0
admin.CreatedAt = util.GetTimeAsMsSinceEpoch(time.Now())
admin.UpdatedAt = util.GetTimeAsMsSinceEpoch(time.Now())
for idx := range admin.Groups {
err = p.addAdminToGroupMapping(admin.Username, admin.Groups[idx].Name, groupBucket)
if err != nil {
return err
}
}
buf, err := json.Marshal(admin)
if err != nil {
return err
@@ -401,8 +411,11 @@ func (p *BoltProvider) updateAdmin(admin *Admin) error {
if err != nil {
return err
}
groupBucket, err := p.getGroupsBucket(tx)
if err != nil {
return err
}
var a []byte
if a = bucket.Get([]byte(admin.Username)); a == nil {
return util.NewRecordNotFoundError(fmt.Sprintf("admin %v does not exist", admin.Username))
}
@@ -412,6 +425,18 @@ func (p *BoltProvider) updateAdmin(admin *Admin) error {
return err
}
for idx := range oldAdmin.Groups {
err = p.removeAdminFromGroupMapping(oldAdmin.Username, oldAdmin.Groups[idx].Name, groupBucket)
if err != nil {
return err
}
}
for idx := range admin.Groups {
err = p.addAdminToGroupMapping(admin.Username, admin.Groups[idx].Name, groupBucket)
if err != nil {
return err
}
}
admin.ID = oldAdmin.ID
admin.CreatedAt = oldAdmin.CreatedAt
admin.LastLogin = oldAdmin.LastLogin
@@ -431,9 +456,27 @@ func (p *BoltProvider) deleteAdmin(admin Admin) error {
return err
}
if bucket.Get([]byte(admin.Username)) == nil {
var a []byte
if a = bucket.Get([]byte(admin.Username)); a == nil {
return util.NewRecordNotFoundError(fmt.Sprintf("admin %v does not exist", admin.Username))
}
var oldAdmin Admin
err = json.Unmarshal(a, &oldAdmin)
if err != nil {
return err
}
if len(oldAdmin.Groups) > 0 {
groupBucket, err := p.getGroupsBucket(tx)
if err != nil {
return err
}
for idx := range oldAdmin.Groups {
err = p.removeAdminFromGroupMapping(oldAdmin.Username, oldAdmin.Groups[idx].Name, groupBucket)
if err != nil {
return err
}
}
}
if err := p.deleteRelatedAPIKey(tx, admin.Username, APIKeyScopeAdmin); err != nil {
return err
@@ -1014,6 +1057,7 @@ func (p *BoltProvider) addFolder(folder *vfs.BaseVirtualFolder) error {
return fmt.Errorf("folder %v already exists", folder.Name)
}
folder.Users = nil
folder.Groups = nil
return p.addFolderInternal(*folder, bucket)
})
}
@@ -1044,6 +1088,7 @@ func (p *BoltProvider) updateFolder(folder *vfs.BaseVirtualFolder) error {
folder.UsedQuotaFiles = oldFolder.UsedQuotaFiles
folder.UsedQuotaSize = oldFolder.UsedQuotaSize
folder.Users = oldFolder.Users
folder.Groups = oldFolder.Groups
buf, err := json.Marshal(folder)
if err != nil {
return err
@@ -1332,6 +1377,8 @@ func (p *BoltProvider) addGroup(group *Group) error {
group.ID = int64(id)
group.CreatedAt = util.GetTimeAsMsSinceEpoch(time.Now())
group.UpdatedAt = util.GetTimeAsMsSinceEpoch(time.Now())
group.Users = nil
group.Admins = nil
for idx := range group.VirtualFolders {
err = p.addRelationToFolderMapping(&group.VirtualFolders[idx].BaseVirtualFolder, nil, group, foldersBucket)
if err != nil {
@@ -1383,6 +1430,7 @@ func (p *BoltProvider) updateGroup(group *Group) error {
group.ID = oldGroup.ID
group.CreatedAt = oldGroup.CreatedAt
group.Users = oldGroup.Users
group.Admins = oldGroup.Admins
group.UpdatedAt = util.GetTimeAsMsSinceEpoch(time.Now())
buf, err := json.Marshal(group)
if err != nil {
@@ -1408,17 +1456,31 @@ func (p *BoltProvider) deleteGroup(group Group) error {
return err
}
if len(oldGroup.Users) > 0 {
return util.NewValidationError(fmt.Sprintf("the group %#v is referenced, it cannot be removed", group.Name))
return util.NewValidationError(fmt.Sprintf("the group %#v is referenced, it cannot be removed", oldGroup.Name))
}
foldersBucket, err := p.getFoldersBucket(tx)
if err != nil {
return err
}
for idx := range group.VirtualFolders {
err = p.removeRelationFromFolderMapping(group.VirtualFolders[idx], "", group.Name, foldersBucket)
if len(oldGroup.VirtualFolders) > 0 {
foldersBucket, err := p.getFoldersBucket(tx)
if err != nil {
return err
}
for idx := range oldGroup.VirtualFolders {
err = p.removeRelationFromFolderMapping(oldGroup.VirtualFolders[idx], "", oldGroup.Name, foldersBucket)
if err != nil {
return err
}
}
}
if len(oldGroup.Admins) > 0 {
adminsBucket, err := p.getAdminsBucket(tx)
if err != nil {
return err
}
for idx := range oldGroup.Admins {
err = p.removeGroupFromAdminMapping(oldGroup.Name, oldGroup.Admins[idx], adminsBucket)
if err != nil {
return err
}
}
}
return bucket.Delete([]byte(group.Name))
@@ -2517,23 +2579,23 @@ func (p *BoltProvider) migrateDatabase() error {
providerLog(logger.LevelDebug, "bolt database is up to date, current version: %v", version)
return ErrNoInitRequired
case version < 19:
err = fmt.Errorf("database version %v is too old, please see the upgrading docs", version)
err = fmt.Errorf("database schema version %v is too old, please see the upgrading docs", version)
providerLog(logger.LevelError, "%v", err)
logger.ErrorToConsole("%v", err)
return err
case version == 19, version == 20:
logger.InfoToConsole(fmt.Sprintf("updating database version: %d -> 21", version))
providerLog(logger.LevelInfo, "updating database version: %d -> 21", version)
return updateBoltDatabaseVersion(p.dbHandle, 21)
case version == 19, version == 20, version == 21:
logger.InfoToConsole(fmt.Sprintf("updating database schema version: %d -> 22", version))
providerLog(logger.LevelInfo, "updating database schema version: %d -> 22", version)
return updateBoltDatabaseVersion(p.dbHandle, 22)
default:
if version > boltDatabaseVersion {
providerLog(logger.LevelError, "database version %v is newer than the supported one: %v", version,
providerLog(logger.LevelError, "database schema version %v is newer than the supported one: %v", version,
boltDatabaseVersion)
logger.WarnToConsole("database version %v is newer than the supported one: %v", version,
logger.WarnToConsole("database schema version %v is newer than the supported one: %v", version,
boltDatabaseVersion)
return nil
}
return fmt.Errorf("database version not handled: %v", version)
return fmt.Errorf("database schema version not handled: %v", version)
}
}
@@ -2547,8 +2609,8 @@ func (p *BoltProvider) revertDatabase(targetVersion int) error {
}
switch dbVersion.Version {
case 20, 21:
logger.InfoToConsole("downgrading database version: %d -> 19", dbVersion.Version)
providerLog(logger.LevelInfo, "downgrading database version: %d -> 19", dbVersion.Version)
logger.InfoToConsole("downgrading database schema version: %d -> 19", dbVersion.Version)
providerLog(logger.LevelInfo, "downgrading database schema version: %d -> 19", dbVersion.Version)
err := p.dbHandle.Update(func(tx *bolt.Tx) error {
for _, bucketName := range [][]byte{actionsBucket, rulesBucket} {
err := tx.DeleteBucket(bucketName)
@@ -2563,7 +2625,7 @@ func (p *BoltProvider) revertDatabase(targetVersion int) error {
}
return updateBoltDatabaseVersion(p.dbHandle, 19)
default:
return fmt.Errorf("database version not handled: %v", dbVersion.Version)
return fmt.Errorf("database schema version not handled: %v", dbVersion.Version)
}
}
@@ -2766,14 +2828,32 @@ func (p *BoltProvider) removeUserFromGroupMapping(username, groupname string, bu
if err != nil {
return err
}
if util.Contains(group.Users, username) {
var users []string
for _, u := range group.Users {
if u != username {
users = append(users, u)
}
var users []string
for _, u := range group.Users {
if u != username {
users = append(users, u)
}
group.Users = util.RemoveDuplicates(users, false)
}
group.Users = util.RemoveDuplicates(users, false)
buf, err := json.Marshal(group)
if err != nil {
return err
}
return bucket.Put([]byte(group.Name), buf)
}
func (p *BoltProvider) addAdminToGroupMapping(username, groupname string, bucket *bolt.Bucket) error {
g := bucket.Get([]byte(groupname))
if g == nil {
return util.NewRecordNotFoundError(fmt.Sprintf("group %q does not exist", groupname))
}
var group Group
err := json.Unmarshal(g, &group)
if err != nil {
return err
}
if !util.Contains(group.Admins, username) {
group.Admins = append(group.Admins, username)
buf, err := json.Marshal(group)
if err != nil {
return err
@@ -2783,6 +2863,55 @@ func (p *BoltProvider) removeUserFromGroupMapping(username, groupname string, bu
return nil
}
func (p *BoltProvider) removeAdminFromGroupMapping(username, groupname string, bucket *bolt.Bucket) error {
g := bucket.Get([]byte(groupname))
if g == nil {
return util.NewRecordNotFoundError(fmt.Sprintf("group %q does not exist", groupname))
}
var group Group
err := json.Unmarshal(g, &group)
if err != nil {
return err
}
var admins []string
for _, a := range group.Admins {
if a != username {
admins = append(admins, a)
}
}
group.Admins = util.RemoveDuplicates(admins, false)
buf, err := json.Marshal(group)
if err != nil {
return err
}
return bucket.Put([]byte(group.Name), buf)
}
func (p *BoltProvider) removeGroupFromAdminMapping(groupName, adminName string, bucket *bolt.Bucket) error {
var a []byte
if a = bucket.Get([]byte(adminName)); a == nil {
// the admin does not exist so there is no associated group
return nil
}
var admin Admin
err := json.Unmarshal(a, &admin)
if err != nil {
return err
}
var newGroups []AdminGroupMapping
for _, g := range admin.Groups {
if g.Name != groupName {
newGroups = append(newGroups, g)
}
}
admin.Groups = newGroups
buf, err := json.Marshal(admin)
if err != nil {
return err
}
return bucket.Put([]byte(adminName), buf)
}
func (p *BoltProvider) addRelationToFolderMapping(baseFolder *vfs.BaseVirtualFolder, user *User, group *Group, bucket *bolt.Bucket) error {
f := bucket.Get([]byte(baseFolder.Name))
if f == nil {
@@ -2836,7 +2965,7 @@ func (p *BoltProvider) removeRelationFromFolderMapping(folder vfs.VirtualFolder,
return err
}
found := false
if username != "" && util.Contains(baseFolder.Users, username) {
if username != "" {
found = true
var newUserMapping []string
for _, u := range baseFolder.Users {
@@ -2846,7 +2975,7 @@ func (p *BoltProvider) removeRelationFromFolderMapping(folder vfs.VirtualFolder,
}
baseFolder.Users = newUserMapping
}
if groupname != "" && util.Contains(baseFolder.Groups, groupname) {
if groupname != "" {
found = true
var newGroupMapping []string
for _, g := range baseFolder.Groups {
@@ -3066,7 +3195,7 @@ func getBoltDatabaseVersion(dbHandle *bolt.DB) (schemaVersion, error) {
err := dbHandle.View(func(tx *bolt.Tx) error {
bucket := tx.Bucket(dbVersionBucket)
if bucket == nil {
return fmt.Errorf("unable to find database version bucket")
return fmt.Errorf("unable to find database schema version bucket")
}
v := bucket.Get(dbVersionKey)
if v == nil {
@@ -3084,7 +3213,7 @@ func updateBoltDatabaseVersion(dbHandle *bolt.DB, version int) error {
err := dbHandle.Update(func(tx *bolt.Tx) error {
bucket := tx.Bucket(dbVersionBucket)
if bucket == nil {
return fmt.Errorf("unable to find database version bucket")
return fmt.Errorf("unable to find database schema version bucket")
}
newDbVersion := schemaVersion{
Version: version,