feat: team page

This commit is contained in:
2024-11-14 17:58:19 +07:00
parent 7a00992ff9
commit 71dfbd5db3
23 changed files with 790 additions and 67 deletions
+4 -4
View File
@@ -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
}
+2
View File
@@ -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,
}
+61 -4
View File
@@ -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
}
+149
View File
@@ -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)
}
+16
View File
@@ -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"`
}
+28
View File
@@ -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
}