feat: team access control

This commit is contained in:
2024-11-12 17:17:10 +00:00
parent f5250d5361
commit 2d4c81e15d
31 changed files with 410 additions and 161 deletions
+12 -19
View File
@@ -20,8 +20,14 @@ func NewRepository(r *Hosts) *Hosts {
return r
}
func (r *Hosts) GetAll() ([]*models.Host, error) {
query := r.ACL(r.db.Order("id DESC"))
func (r *Hosts) GetAll(opt GetAllOpt) ([]*models.Host, error) {
query := r.db.Order("id DESC")
if opt.TeamID != "" {
query = query.Where("hosts.team_id = ?", opt.TeamID)
} else {
query = query.Where("hosts.owner_id = ? AND hosts.team_id IS NULL", r.User.ID)
}
var rows []*models.Host
ret := query.Find(&rows)
@@ -30,10 +36,8 @@ func (r *Hosts) GetAll() ([]*models.Host, error) {
}
func (r *Hosts) Get(id string) (*models.HostDecrypted, error) {
query := r.ACL(r.db)
var host models.Host
ret := query.Joins("Key").Joins("AltKey").Where("hosts.id = ?", id).First(&host)
ret := r.db.Joins("Key").Joins("AltKey").Where("hosts.id = ?", id).First(&host)
if ret.Error != nil {
return nil, ret.Error
}
@@ -48,13 +52,12 @@ func (r *Hosts) Get(id string) (*models.HostDecrypted, error) {
func (r *Hosts) Exists(id string) (bool, error) {
var count int64
ret := r.ACL(r.db.Model(&models.Host{}).Where("id = ?", id)).Count(&count)
ret := r.db.Model(&models.Host{}).Where("id = ?", id).Count(&count)
return count > 0, ret.Error
}
func (r *Hosts) Delete(id string) error {
query := r.ACL(r.db)
return query.Delete(&models.Host{Model: models.Model{ID: id}}).Error
return r.db.Delete(&models.Host{Model: models.Model{ID: id}}).Error
}
func (r *Hosts) Create(item *models.Host) error {
@@ -62,15 +65,5 @@ func (r *Hosts) Create(item *models.Host) error {
}
func (r *Hosts) Update(id string, item *models.Host) error {
query := r.ACL(r.db.Where("id = ?", id))
return query.Updates(item).Error
}
func (r *Hosts) ACL(query *gorm.DB) *gorm.DB {
if r.User.IsAdmin {
return query
}
return query.Where("hosts.owner_id = ?", r.User.ID)
return r.db.Where("id = ?", id).Updates(item).Error
}
+26 -8
View File
@@ -1,6 +1,7 @@
package hosts
import (
"errors"
"fmt"
"net/http"
@@ -19,10 +20,15 @@ func Router(app fiber.Router) {
}
func getAll(c *fiber.Ctx) error {
teamId := c.Query("teamId")
user := utils.GetUser(c)
repo := NewRepository(&Hosts{User: user})
rows, err := repo.GetAll()
if teamId != "" && !user.IsInTeam(&teamId) {
return utils.ResponseError(c, errors.New("no access"), 403)
}
rows, err := repo.GetAll(GetAllOpt{TeamID: teamId})
if err != nil {
return utils.ResponseError(c, err, 500)
}
@@ -41,8 +47,13 @@ func create(c *fiber.Ctx) error {
user := utils.GetUser(c)
repo := NewRepository(&Hosts{User: user})
if body.TeamID != nil && !user.TeamCanWrite(body.TeamID) {
return utils.ResponseError(c, errors.New("no access"), 403)
}
item := &models.Host{
OwnerID: user.ID,
OwnerID: &user.ID,
TeamID: body.TeamID,
Type: body.Type,
Label: body.Label,
Host: body.Host,
@@ -76,13 +87,17 @@ func update(c *fiber.Ctx) error {
repo := NewRepository(&Hosts{User: user})
id := c.Params("id")
exist, _ := repo.Exists(id)
if !exist {
return utils.ResponseError(c, fmt.Errorf("host %s not found", id), 404)
data, _ := repo.Get(id)
if data == nil {
return utils.ResponseError(c, errors.New("host not found"), 404)
}
if !data.CanWrite(&user.User) || !user.TeamCanWrite(body.TeamID) {
return utils.ResponseError(c, errors.New("no access"), 403)
}
item := &models.Host{
Model: models.Model{ID: id},
TeamID: body.TeamID,
Type: body.Type,
Label: body.Label,
Host: body.Host,
@@ -111,9 +126,12 @@ func delete(c *fiber.Ctx) error {
repo := NewRepository(&Hosts{User: user})
id := c.Params("id")
exist, _ := repo.Exists(id)
if !exist {
return utils.ResponseError(c, fmt.Errorf("host %s not found", id), 404)
host, _ := repo.Get(id)
if host == nil {
return utils.ResponseError(c, errors.New("host not found"), 404)
}
if !host.CanWrite(&user.User) {
return utils.ResponseError(c, errors.New("no access"), 403)
}
if err := repo.Delete(id); err != nil {
+5
View File
@@ -9,7 +9,12 @@ type CreateHostSchema struct {
Port int `json:"port"`
Metadata datatypes.JSONMap `json:"metadata"`
TeamID *string `json:"teamId"`
ParentID *string `json:"parentId"`
KeyID *string `json:"keyId"`
AltKeyID *string `json:"altKeyId"`
}
type GetAllOpt struct {
TeamID string
}