mirror of
https://github.com/khairul169/vaulterm.git
synced 2026-09-15 17:03:30 +07:00
feat: team page
This commit is contained in:
@@ -56,10 +56,6 @@ func (r *Hosts) Exists(id string) (bool, error) {
|
||||
return count > 0, ret.Error
|
||||
}
|
||||
|
||||
func (r *Hosts) Delete(id string) error {
|
||||
return r.db.Delete(&models.Host{Model: models.Model{ID: id}}).Error
|
||||
}
|
||||
|
||||
func (r *Hosts) Create(item *models.Host) error {
|
||||
return r.db.Create(item).Error
|
||||
}
|
||||
@@ -67,3 +63,7 @@ func (r *Hosts) Create(item *models.Host) error {
|
||||
func (r *Hosts) Update(id string, item *models.Host) error {
|
||||
return r.db.Where("id = ?", id).Updates(item).Error
|
||||
}
|
||||
|
||||
func (r *Hosts) Delete(id string) error {
|
||||
return r.db.Delete(&models.Host{Model: models.Model{ID: id}}).Error
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"rul.sh/vaulterm/app/hosts"
|
||||
"rul.sh/vaulterm/app/keychains"
|
||||
"rul.sh/vaulterm/app/teams"
|
||||
"rul.sh/vaulterm/app/ws"
|
||||
)
|
||||
|
||||
@@ -12,6 +13,7 @@ func InitRouter(app *fiber.App) {
|
||||
routes := []Router{
|
||||
hosts.Router,
|
||||
keychains.Router,
|
||||
teams.Router,
|
||||
ws.Router,
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package teams
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
"rul.sh/vaulterm/db"
|
||||
"rul.sh/vaulterm/models"
|
||||
"rul.sh/vaulterm/utils"
|
||||
@@ -22,17 +23,50 @@ func NewRepository(r *Teams) *Teams {
|
||||
|
||||
func (r *Teams) GetAll() ([]*models.Team, error) {
|
||||
var rows []*models.Team
|
||||
ret := r.db.Order("created_at DESC").Find(&rows)
|
||||
query := r.db.Order("created_at ASC")
|
||||
|
||||
if !r.User.IsAdmin() {
|
||||
query = query.
|
||||
Joins("JOIN team_members ON team_members.team_id = teams.id").
|
||||
Where("team_members.user_id = ?", r.User.ID)
|
||||
}
|
||||
|
||||
ret := query.Find(&rows)
|
||||
return rows, ret.Error
|
||||
}
|
||||
|
||||
func (r *Teams) Create(data *models.Team) error {
|
||||
return r.db.Create(data).Error
|
||||
return r.db.Transaction(func(tx *gorm.DB) error {
|
||||
if err := tx.Create(data).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if r.User.ID != "" {
|
||||
ret := tx.Create(&models.TeamMembers{
|
||||
UserID: r.User.ID,
|
||||
TeamID: data.ID,
|
||||
Role: models.TeamRoleOwner,
|
||||
})
|
||||
if ret.Error != nil {
|
||||
return ret.Error
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (r *Teams) Get(id string) (*models.Team, error) {
|
||||
func (r *Teams) Get(opt GetOptions) (*models.Team, error) {
|
||||
query := r.db.Where("teams.id = ?", opt.ID)
|
||||
|
||||
if opt.WithMembers {
|
||||
query = query.Preload("Members.User", func(db *gorm.DB) *gorm.DB {
|
||||
return db.Select("users.id", "users.name", "users.username", "users.email")
|
||||
})
|
||||
}
|
||||
|
||||
var data models.Team
|
||||
if err := r.db.Where("id = ?", id).First(&data).Error; err != nil {
|
||||
if err := query.First(&data).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -48,3 +82,26 @@ func (r *Teams) Exists(id string) (bool, error) {
|
||||
func (r *Teams) Update(id string, item *models.Team) error {
|
||||
return r.db.Where("id = ?", id).Updates(item).Error
|
||||
}
|
||||
|
||||
func (r *Teams) Delete(id string) error {
|
||||
return r.db.Transaction(func(tx *gorm.DB) error {
|
||||
if err := tx.Where("team_id = ?", id).Delete(&models.TeamMembers{}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Where("id = ?", id).Delete(&models.Team{}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (r *Teams) Invite(teamId string, userId string, role string) error {
|
||||
ret := r.db.
|
||||
Clauses(clause.OnConflict{DoNothing: true}).
|
||||
Create(&models.TeamMembers{
|
||||
TeamID: teamId,
|
||||
UserID: userId,
|
||||
Role: role,
|
||||
})
|
||||
return ret.Error
|
||||
}
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
package teams
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"rul.sh/vaulterm/app/users"
|
||||
"rul.sh/vaulterm/models"
|
||||
"rul.sh/vaulterm/utils"
|
||||
)
|
||||
|
||||
func Router(app fiber.Router) {
|
||||
router := app.Group("/teams")
|
||||
|
||||
router.Get("/", getAll)
|
||||
router.Get("/:id", getById)
|
||||
router.Post("/", create)
|
||||
router.Put("/:id", update)
|
||||
router.Delete("/:id", delete)
|
||||
router.Post("/:id/invite", invite)
|
||||
}
|
||||
|
||||
func getAll(c *fiber.Ctx) error {
|
||||
user := utils.GetUser(c)
|
||||
repo := NewRepository(&Teams{User: user})
|
||||
|
||||
rows, err := repo.GetAll()
|
||||
if err != nil {
|
||||
return utils.ResponseError(c, err, 500)
|
||||
}
|
||||
|
||||
return c.JSON(fiber.Map{"rows": rows})
|
||||
}
|
||||
|
||||
func getById(c *fiber.Ctx) error {
|
||||
user := utils.GetUser(c)
|
||||
repo := NewRepository(&Teams{User: user})
|
||||
|
||||
id := c.Params("id")
|
||||
data, _ := repo.Get(GetOptions{ID: id, WithMembers: true})
|
||||
if data == nil || !user.IsInTeam(&id) {
|
||||
return utils.ResponseError(c, errors.New("team not found"), 404)
|
||||
}
|
||||
|
||||
return c.JSON(data)
|
||||
}
|
||||
|
||||
func create(c *fiber.Ctx) error {
|
||||
var body CreateTeamSchema
|
||||
if err := c.BodyParser(&body); err != nil {
|
||||
return utils.ResponseError(c, err, 500)
|
||||
}
|
||||
|
||||
user := utils.GetUser(c)
|
||||
repo := NewRepository(&Teams{User: user})
|
||||
|
||||
item := &models.Team{
|
||||
Name: body.Name,
|
||||
Icon: body.Icon,
|
||||
}
|
||||
|
||||
if err := repo.Create(item); err != nil {
|
||||
return utils.ResponseError(c, err, 500)
|
||||
}
|
||||
|
||||
return c.Status(http.StatusCreated).JSON(item)
|
||||
}
|
||||
|
||||
func update(c *fiber.Ctx) error {
|
||||
var body CreateTeamSchema
|
||||
if err := c.BodyParser(&body); err != nil {
|
||||
return utils.ResponseError(c, err, 500)
|
||||
}
|
||||
|
||||
user := utils.GetUser(c)
|
||||
repo := NewRepository(&Teams{User: user})
|
||||
|
||||
id := c.Params("id")
|
||||
data, _ := repo.Get(GetOptions{ID: id})
|
||||
if data == nil {
|
||||
return utils.ResponseError(c, errors.New("team not found"), 404)
|
||||
}
|
||||
if !user.TeamCanWrite(&id) {
|
||||
return utils.ResponseError(c, errors.New("no access"), 403)
|
||||
}
|
||||
|
||||
item := &models.Team{
|
||||
Name: body.Name,
|
||||
Icon: body.Icon,
|
||||
}
|
||||
|
||||
if err := repo.Update(id, item); err != nil {
|
||||
return utils.ResponseError(c, err, 500)
|
||||
}
|
||||
|
||||
return c.JSON(item)
|
||||
}
|
||||
|
||||
func delete(c *fiber.Ctx) error {
|
||||
user := utils.GetUser(c)
|
||||
repo := NewRepository(&Teams{User: user})
|
||||
|
||||
id := c.Params("id")
|
||||
data, _ := repo.Get(GetOptions{ID: id})
|
||||
if data == nil {
|
||||
return utils.ResponseError(c, errors.New("team not found"), 404)
|
||||
}
|
||||
if !user.TeamCanWrite(&id) {
|
||||
return utils.ResponseError(c, errors.New("no access"), 403)
|
||||
}
|
||||
|
||||
if err := repo.Delete(id); err != nil {
|
||||
return utils.ResponseError(c, err, 500)
|
||||
}
|
||||
|
||||
return c.JSON(true)
|
||||
}
|
||||
|
||||
func invite(c *fiber.Ctx) error {
|
||||
var body InviteTeamSchema
|
||||
if err := c.BodyParser(&body); err != nil {
|
||||
return utils.ResponseError(c, err, 500)
|
||||
}
|
||||
|
||||
user := utils.GetUser(c)
|
||||
repo := NewRepository(&Teams{User: user})
|
||||
|
||||
id := c.Params("id")
|
||||
exist, _ := repo.Exists(id)
|
||||
if !exist {
|
||||
return utils.ResponseError(c, errors.New("team not found"), 404)
|
||||
}
|
||||
if !user.TeamCanWrite(&id) {
|
||||
return utils.ResponseError(c, errors.New("no access"), 403)
|
||||
}
|
||||
|
||||
userRepo := users.NewRepository(&users.Users{User: user})
|
||||
userData, _ := userRepo.Find(body.Username)
|
||||
if userData.ID == "" {
|
||||
return utils.ResponseError(c, errors.New("user not found"), 404)
|
||||
}
|
||||
|
||||
if err := repo.Invite(id, userData.ID, body.Role); err != nil {
|
||||
return utils.ResponseError(c, err, 500)
|
||||
}
|
||||
|
||||
return c.JSON(true)
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package teams
|
||||
|
||||
type CreateTeamSchema struct {
|
||||
Name string `json:"name"`
|
||||
Icon string `json:"icon"`
|
||||
}
|
||||
|
||||
type GetOptions struct {
|
||||
ID string
|
||||
WithMembers bool
|
||||
}
|
||||
|
||||
type InviteTeamSchema struct {
|
||||
Username string `json:"username"`
|
||||
Role string `json:"role"`
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package users
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
"rul.sh/vaulterm/db"
|
||||
"rul.sh/vaulterm/models"
|
||||
"rul.sh/vaulterm/utils"
|
||||
)
|
||||
|
||||
type Users struct {
|
||||
db *gorm.DB
|
||||
User *utils.UserContext
|
||||
}
|
||||
|
||||
func NewRepository(r *Users) *Users {
|
||||
if r == nil {
|
||||
r = &Users{}
|
||||
}
|
||||
r.db = db.Get()
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *Users) Find(username string) (*models.User, error) {
|
||||
var user models.User
|
||||
ret := r.db.Where("username = ? OR email = ?", username, username).First(&user)
|
||||
|
||||
return &user, ret.Error
|
||||
}
|
||||
@@ -21,7 +21,7 @@ type Team struct {
|
||||
|
||||
type TeamMembers struct {
|
||||
TeamID string `json:"teamId" gorm:"primarykey;type:varchar(26)"`
|
||||
Team Team `json:"team"`
|
||||
Team Team `json:"-"`
|
||||
UserID string `json:"userId" gorm:"primarykey;type:varchar(26)"`
|
||||
User User `json:"user"`
|
||||
Role string `json:"role" gorm:"type:varchar(16)"`
|
||||
|
||||
Reference in New Issue
Block a user