feat: Users API, ownership transfer and removal of the legacy role string
This commit is contained in:
1 parent
094df63a7f
commit
80f7037d3a
124 files changed
+4644
-824
No files matched your search
@@ -145,8 +145,8 @@ func (r *RoleRepository) Delete(id uint32) error {
|
||||
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).First(&entity.Role{}, id).Error; err != nil {
|
||||
return mapNotFoundErr(err, role.ErrRoleNotFound)
|
||||
}
|
||||
var members int64
|
||||
if err := tx.Model(&entity.User{}).Where("role_id = ?", id).Count(&members).Error; err != nil {
|
||||
members, err := countMembers(tx, id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if members > 0 {
|
||||
@@ -159,24 +159,68 @@ func (r *RoleRepository) Delete(id uint32) error {
|
||||
})
|
||||
}
|
||||
|
||||
func (r *RoleRepository) ReassignMembers(from uint32, to uint32) (int, error) {
|
||||
moved := r.db.Model(&entity.User{}).
|
||||
Where("role_id = ? AND EXISTS (SELECT 1 FROM roles WHERE id = ?)", from, to).
|
||||
UpdateColumn("role_id", to)
|
||||
if moved.Error != nil {
|
||||
return 0, moved.Error
|
||||
}
|
||||
if moved.RowsAffected > 0 {
|
||||
return int(moved.RowsAffected), nil
|
||||
}
|
||||
var targets int64
|
||||
if err := r.db.Model(&entity.Role{}).Where("id = ?", to).Count(&targets).Error; err != nil {
|
||||
func countMembers(tx *gorm.DB, id uint32) (int64, error) {
|
||||
var users, invites int64
|
||||
if err := tx.Model(&entity.User{}).Where("role_id = ?", id).Count(&users).Error; err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if targets == 0 {
|
||||
return 0, role.ErrInvalidReassign
|
||||
if err := tx.Model(&entity.Invite{}).Where("role_id = ? AND accepted_at IS NULL", id).Count(&invites).Error; err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return 0, nil
|
||||
return users + invites, nil
|
||||
}
|
||||
|
||||
type memberRow struct {
|
||||
RoleID uint32
|
||||
Members int
|
||||
}
|
||||
|
||||
func (r *RoleRepository) MemberCounts() (map[uint32]int, error) {
|
||||
var users, invites []memberRow
|
||||
if err := r.db.Model(&entity.User{}).Select("role_id, COUNT(*) AS members").Where("role_id IS NOT NULL").Group("role_id").Scan(&users).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := r.db.Model(&entity.Invite{}).Select("role_id, COUNT(*) AS members").Where("role_id IS NOT NULL AND accepted_at IS NULL").Group("role_id").Scan(&invites).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
counts := map[uint32]int{}
|
||||
for _, row := range append(users, invites...) {
|
||||
if row.RoleID != 0 {
|
||||
counts[row.RoleID] += row.Members
|
||||
}
|
||||
}
|
||||
return counts, nil
|
||||
}
|
||||
|
||||
func (r *RoleRepository) ReassignMembers(from uint32, to uint32) (int, error) {
|
||||
moved := 0
|
||||
err := r.db.Transaction(func(tx *gorm.DB) error {
|
||||
target := "EXISTS (SELECT 1 FROM roles WHERE id = ?)"
|
||||
users := tx.Model(&entity.User{}).Where("role_id = ? AND "+target, from, to).UpdateColumn("role_id", to)
|
||||
if users.Error != nil {
|
||||
return users.Error
|
||||
}
|
||||
invites := tx.Model(&entity.Invite{}).Where("role_id = ? AND accepted_at IS NULL AND "+target, from, to).UpdateColumn("role_id", to)
|
||||
if invites.Error != nil {
|
||||
return invites.Error
|
||||
}
|
||||
moved = int(users.RowsAffected + invites.RowsAffected)
|
||||
if moved > 0 {
|
||||
return nil
|
||||
}
|
||||
var targets int64
|
||||
if err := tx.Model(&entity.Role{}).Where("id = ?", to).Count(&targets).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if targets == 0 {
|
||||
return role.ErrInvalidReassign
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return moved, nil
|
||||
}
|
||||
|
||||
func (r *RoleRepository) RemoveTypedGrants(typeKey string) (int, error) {
|
||||
|
||||
Reference in new issue
Block a user