mirror of
https://github.com/khairul169/vaulterm.git
synced 2026-09-15 17:03:30 +07:00
feat: team access control
This commit is contained in:
+21
-13
@@ -1,6 +1,8 @@
|
||||
package models
|
||||
|
||||
import "gorm.io/datatypes"
|
||||
import (
|
||||
"gorm.io/datatypes"
|
||||
)
|
||||
|
||||
const (
|
||||
HostTypeSSH = "ssh"
|
||||
@@ -14,8 +16,10 @@ const (
|
||||
type Host struct {
|
||||
Model
|
||||
|
||||
OwnerID string `json:"userId" gorm:"index:hosts_owner_id_idx;type:varchar(26)"`
|
||||
Owner User `json:"user" gorm:"foreignKey:OwnerID"`
|
||||
OwnerID *string `json:"userId" gorm:"type:varchar(26)"`
|
||||
Owner *User `json:"user" gorm:"foreignKey:OwnerID"`
|
||||
TeamID *string `json:"teamId" gorm:"type:varchar(26)"`
|
||||
Team *Team `json:"team" gorm:"foreignKey:TeamID"`
|
||||
|
||||
Type string `json:"type" gorm:"not null;index:hosts_type_idx;type:varchar(16)"`
|
||||
Label string `json:"label"`
|
||||
@@ -24,11 +28,11 @@ type Host struct {
|
||||
OS string `json:"os" gorm:"type:varchar(32)"`
|
||||
Metadata datatypes.JSONMap `json:"metadata"`
|
||||
|
||||
ParentID *string `json:"parentId" gorm:"index:hosts_parent_id_idx;type:varchar(26)"`
|
||||
ParentID *string `json:"parentId" gorm:"type:varchar(26)"`
|
||||
Parent *Host `json:"parent" gorm:"foreignKey:ParentID"`
|
||||
KeyID *string `json:"keyId" gorm:"index:hosts_key_id_idx"`
|
||||
KeyID *string `json:"keyId" gorm:"type:varchar(26)"`
|
||||
Key Keychain `json:"key" gorm:"foreignKey:KeyID"`
|
||||
AltKeyID *string `json:"altKeyId" gorm:"index:hosts_altkey_id_idx"`
|
||||
AltKeyID *string `json:"altKeyId" gorm:"type:varchar(26)"`
|
||||
AltKey Keychain `json:"altKey" gorm:"foreignKey:AltKeyID"`
|
||||
|
||||
Timestamps
|
||||
@@ -58,13 +62,17 @@ func (h *Host) DecryptKeys() (*HostDecrypted, error) {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
type HostHasAccessOptions struct {
|
||||
UserID string
|
||||
}
|
||||
|
||||
func (h *Host) HasAccess(o HostHasAccessOptions) bool {
|
||||
if o.UserID == h.OwnerID {
|
||||
func (h *Host) HasAccess(user *User) bool {
|
||||
if user.IsAdmin() {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
return *h.OwnerID == user.ID || user.IsInTeam(h.TeamID)
|
||||
}
|
||||
|
||||
func (h *Host) CanWrite(user *User) bool {
|
||||
if user.IsAdmin() {
|
||||
return true
|
||||
}
|
||||
teamRole := user.GetTeamRole(h.TeamID)
|
||||
return *h.OwnerID == user.ID || teamRole == TeamRoleOwner || teamRole == TeamRoleAdmin
|
||||
}
|
||||
|
||||
@@ -16,8 +16,10 @@ const (
|
||||
type Keychain struct {
|
||||
Model
|
||||
|
||||
OwnerID string `json:"userId" gorm:"index:hosts_owner_id_idx;type:varchar(26)"`
|
||||
Owner User `json:"user" gorm:"foreignKey:OwnerID"`
|
||||
OwnerID *string `json:"userId" gorm:"type:varchar(26)"`
|
||||
Owner *User `json:"user" gorm:"foreignKey:OwnerID"`
|
||||
TeamID *string `json:"teamId" gorm:"type:varchar(26)"`
|
||||
Team *Team `json:"team" gorm:"foreignKey:TeamID"`
|
||||
|
||||
Label string `json:"label"`
|
||||
Type string `json:"type" gorm:"not null;index:keychains_type_idx;type:varchar(12)"`
|
||||
@@ -55,3 +57,18 @@ func (k *Keychain) DecryptData(data interface{}) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (k *Keychain) HasAccess(user *User) bool {
|
||||
if user.IsAdmin() {
|
||||
return true
|
||||
}
|
||||
return *k.OwnerID == user.ID || user.IsInTeam(k.TeamID)
|
||||
}
|
||||
|
||||
func (k *Keychain) CanWrite(user *User) bool {
|
||||
if user.IsAdmin() {
|
||||
return true
|
||||
}
|
||||
teamRole := user.GetTeamRole(k.TeamID)
|
||||
return *k.OwnerID == user.ID || teamRole == TeamRoleOwner || teamRole == TeamRoleAdmin
|
||||
}
|
||||
|
||||
@@ -2,12 +2,18 @@ package models
|
||||
|
||||
import "time"
|
||||
|
||||
const (
|
||||
TeamRoleOwner = "owner"
|
||||
TeamRoleAdmin = "admin"
|
||||
TeamRoleMember = "member"
|
||||
)
|
||||
|
||||
type Team struct {
|
||||
Model
|
||||
|
||||
Name string `json:"name" gorm:"type:varchar(32)"`
|
||||
Icon string `json:"icon" gorm:"type:varchar(2)"`
|
||||
Members []*User `json:"members" gorm:"many2many:team_members"`
|
||||
Name string `json:"name" gorm:"type:varchar(32)"`
|
||||
Icon string `json:"icon" gorm:"type:varchar(2)"`
|
||||
Members []*TeamMembers `json:"members" gorm:"foreignKey:TeamID"`
|
||||
|
||||
Timestamps
|
||||
SoftDeletes
|
||||
|
||||
+33
-1
@@ -1,5 +1,7 @@
|
||||
package models
|
||||
|
||||
import "slices"
|
||||
|
||||
const (
|
||||
UserRoleUser = "user"
|
||||
UserRoleAdmin = "admin"
|
||||
@@ -14,7 +16,7 @@ type User struct {
|
||||
Email string `json:"email" gorm:"unique"`
|
||||
Role string `json:"role" gorm:"default:user;not null;index:users_role_idx;type:varchar(8)"`
|
||||
|
||||
Teams []*Team `json:"teams" gorm:"many2many:team_members"`
|
||||
Teams []*TeamMembers `json:"teams" gorm:"foreignKey:UserID"`
|
||||
|
||||
Timestamps
|
||||
SoftDeletes
|
||||
@@ -28,3 +30,33 @@ type UserSession struct {
|
||||
Timestamps
|
||||
SoftDeletes
|
||||
}
|
||||
|
||||
func (u *User) IsAdmin() bool {
|
||||
return u.Role == UserRoleAdmin
|
||||
}
|
||||
|
||||
func (u *User) GetTeamRole(teamId *string) string {
|
||||
if u.IsAdmin() {
|
||||
return TeamRoleAdmin
|
||||
}
|
||||
if teamId == nil {
|
||||
return ""
|
||||
}
|
||||
idx := slices.IndexFunc(u.Teams, func(tm *TeamMembers) bool {
|
||||
return tm.TeamID == *teamId
|
||||
})
|
||||
if idx == -1 {
|
||||
return ""
|
||||
}
|
||||
return u.Teams[idx].Role
|
||||
}
|
||||
|
||||
func (u *User) IsInTeam(teamId *string) bool {
|
||||
role := u.GetTeamRole(teamId)
|
||||
return role != ""
|
||||
}
|
||||
|
||||
func (u *User) TeamCanWrite(teamId *string) bool {
|
||||
role := u.GetTeamRole(teamId)
|
||||
return role == TeamRoleAdmin || role == TeamRoleOwner
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user