add tenant page
This commit is contained in:
@@ -1,6 +1,10 @@
|
|||||||
package tenants
|
package tenants
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"backend/providers/jwt"
|
||||||
|
"backend/providers/otel"
|
||||||
|
|
||||||
|
"github.com/gofiber/fiber/v3"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -28,3 +32,23 @@ func (c *Controller) Prepare() error {
|
|||||||
// @Param sortFilter query common.SortQueryFilter true "SortQueryFilter"
|
// @Param sortFilter query common.SortQueryFilter true "SortQueryFilter"
|
||||||
// @Success 200 {object} common.PageDataResponse{list=dto.AlarmItem}
|
// @Success 200 {object} common.PageDataResponse{list=dto.AlarmItem}
|
||||||
// @Router /v1/test/:id<int> [get]
|
// @Router /v1/test/:id<int> [get]
|
||||||
|
|
||||||
|
// @Router /t/:tenant [get]
|
||||||
|
//
|
||||||
|
// @Bind claim local
|
||||||
|
// @Bind tenant query
|
||||||
|
func (c *Controller) Index(ctx fiber.Ctx, tenant string, claim *jwt.Claims) error {
|
||||||
|
_ctx, span := otel.Start(ctx.Context(), "tenants.controller.index")
|
||||||
|
defer span.End()
|
||||||
|
|
||||||
|
tenantModel, err := c.svc.GetTenantBySlug(_ctx, tenant)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.svc.BindUserToTenantIfNotExists(_ctx, tenantModel.ID, claim.UserID); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ package tenants
|
|||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
|
||||||
|
"git.ipao.vip/rogeecn/atom"
|
||||||
"git.ipao.vip/rogeecn/atom/container"
|
"git.ipao.vip/rogeecn/atom/container"
|
||||||
|
"git.ipao.vip/rogeecn/atom/contracts"
|
||||||
"git.ipao.vip/rogeecn/atom/utils/opt"
|
"git.ipao.vip/rogeecn/atom/utils/opt"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -22,6 +24,20 @@ func Provide(opts ...opt.Option) error {
|
|||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := container.Container.Provide(func(
|
||||||
|
controller *Controller,
|
||||||
|
) (contracts.HttpRoute, error) {
|
||||||
|
obj := &Routes{
|
||||||
|
controller: controller,
|
||||||
|
}
|
||||||
|
if err := obj.Prepare(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj, nil
|
||||||
|
}, atom.GroupRoutes); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if err := container.Container.Provide(func(
|
if err := container.Container.Provide(func(
|
||||||
db *sql.DB,
|
db *sql.DB,
|
||||||
) (*Service, error) {
|
) (*Service, error) {
|
||||||
|
|||||||
38
backend/app/http/tenants/routes.gen.go
Normal file
38
backend/app/http/tenants/routes.gen.go
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
// Code generated by the atomctl ; DO NOT EDIT.
|
||||||
|
|
||||||
|
package tenants
|
||||||
|
|
||||||
|
import (
|
||||||
|
. "backend/pkg/f"
|
||||||
|
"backend/providers/jwt"
|
||||||
|
|
||||||
|
_ "git.ipao.vip/rogeecn/atom"
|
||||||
|
_ "git.ipao.vip/rogeecn/atom/contracts"
|
||||||
|
"github.com/gofiber/fiber/v3"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
// @provider contracts.HttpRoute atom.GroupRoutes
|
||||||
|
type Routes struct {
|
||||||
|
log *log.Entry `inject:"false"`
|
||||||
|
controller *Controller
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Routes) Prepare() error {
|
||||||
|
r.log = log.WithField("module", "routes.tenants")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Routes) Name() string {
|
||||||
|
return "tenants"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Routes) Register(router fiber.Router) {
|
||||||
|
// 注册路由组: Controller
|
||||||
|
router.Get("/t/:tenant", Func2(
|
||||||
|
r.controller.Index,
|
||||||
|
QueryParam[string]("tenant"),
|
||||||
|
Local[*jwt.Claims]("claim"),
|
||||||
|
))
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,10 +1,16 @@
|
|||||||
package tenants
|
package tenants
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
|
||||||
|
"backend/database/models/qvyun_v2/public/model"
|
||||||
|
"backend/database/models/qvyun_v2/public/table"
|
||||||
|
"backend/providers/otel"
|
||||||
|
|
||||||
. "github.com/go-jet/jet/v2/postgres"
|
. "github.com/go-jet/jet/v2/postgres"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
semconv "go.opentelemetry.io/otel/semconv/v1.15.0"
|
||||||
)
|
)
|
||||||
|
|
||||||
// @provider:except
|
// @provider:except
|
||||||
@@ -18,3 +24,80 @@ func (svc *Service) Prepare() error {
|
|||||||
_ = Int(1)
|
_ = Int(1)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTenantBySlug
|
||||||
|
func (svc *Service) GetTenantBySlug(ctx context.Context, slug string) (*model.Tenants, error) {
|
||||||
|
ctx, span := otel.Start(ctx, "tenants.service.GetTenantBySlug")
|
||||||
|
defer span.End()
|
||||||
|
|
||||||
|
tbl := table.Tenants
|
||||||
|
stmt := tbl.
|
||||||
|
SELECT(tbl.AllColumns).
|
||||||
|
WHERE(tbl.Slug.EQ(String(slug)))
|
||||||
|
|
||||||
|
var tenant model.Tenants
|
||||||
|
if err := stmt.QueryContext(ctx, svc.db, &tenant); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &tenant, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TenantHasUser
|
||||||
|
func (svc *Service) TenantHasUser(ctx context.Context, tenantID, userID int64) (bool, error) {
|
||||||
|
ctx, span := otel.Start(ctx, "tenants.service.TenantHasUser")
|
||||||
|
defer span.End()
|
||||||
|
|
||||||
|
tbl := table.TenantUsers
|
||||||
|
stmt := tbl.
|
||||||
|
SELECT(COUNT(tbl.ID).AS("cnt")).
|
||||||
|
WHERE(tbl.TenantID.EQ(Int(tenantID))).
|
||||||
|
WHERE(tbl.UserID.EQ(Int(userID)))
|
||||||
|
span.SetAttributes(semconv.DBStatementKey.String(stmt.DebugSql()))
|
||||||
|
|
||||||
|
var count struct {
|
||||||
|
Cnt int64
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := stmt.QueryContext(ctx, svc.db, &count); err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return count.Cnt > 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// BindUserToTenant
|
||||||
|
func (svc *Service) BindUserToTenant(ctx context.Context, tenantID, userID int64) error {
|
||||||
|
ctx, span := otel.Start(ctx, "tenants.service.BindUserToTenant")
|
||||||
|
defer span.End()
|
||||||
|
|
||||||
|
tbl := table.TenantUsers
|
||||||
|
stmt := tbl.
|
||||||
|
INSERT(tbl.TenantID, tbl.UserID).
|
||||||
|
VALUES(Int(tenantID), Int(userID)).
|
||||||
|
ON_CONFLICT().
|
||||||
|
DO_NOTHING()
|
||||||
|
span.SetAttributes(semconv.DBStatementKey.String(stmt.DebugSql()))
|
||||||
|
|
||||||
|
if _, err := stmt.ExecContext(ctx, svc.db); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// BindUserToTenantIfNotExists
|
||||||
|
func (svc *Service) BindUserToTenantIfNotExists(ctx context.Context, tenantID, userID int64) error {
|
||||||
|
ctx, span := otel.Start(ctx, "tenants.service.BindUserToTenantIfNotExists")
|
||||||
|
defer span.End()
|
||||||
|
|
||||||
|
has, err := svc.TenantHasUser(ctx, tenantID, userID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if has {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return svc.BindUserToTenant(ctx, tenantID, userID)
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,6 +5,13 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func Local[T any](key string) func(fiber.Ctx) (T, error) {
|
||||||
|
return func(ctx fiber.Ctx) (T, error) {
|
||||||
|
v := fiber.Locals[T](ctx, key)
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func Path[T fiber.GenericType](key string) func(fiber.Ctx) (T, error) {
|
func Path[T fiber.GenericType](key string) func(fiber.Ctx) (T, error) {
|
||||||
return func(ctx fiber.Ctx) (T, error) {
|
return func(ctx fiber.Ctx) (T, error) {
|
||||||
v := fiber.Params[T](ctx, key)
|
v := fiber.Params[T](ctx, key)
|
||||||
|
|||||||
Reference in New Issue
Block a user