feat: update
This commit is contained in:
@@ -6,16 +6,15 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"go.ipao.vip/atom"
|
|
||||||
"go.ipao.vip/atom/container"
|
|
||||||
"go.ipao.vip/atom/contracts"
|
|
||||||
"quyun/v2/app/commands"
|
"quyun/v2/app/commands"
|
||||||
"quyun/v2/app/errorx"
|
"quyun/v2/app/errorx"
|
||||||
"quyun/v2/app/http/api"
|
"quyun/v2/app/http/api"
|
||||||
"quyun/v2/app/http/super"
|
"quyun/v2/app/http/super"
|
||||||
"quyun/v2/app/http/web"
|
"quyun/v2/app/http/web"
|
||||||
"quyun/v2/app/jobs"
|
"quyun/v2/app/jobs"
|
||||||
|
"quyun/v2/app/services"
|
||||||
"quyun/v2/app/tenancy"
|
"quyun/v2/app/tenancy"
|
||||||
|
"quyun/v2/database"
|
||||||
_ "quyun/v2/docs"
|
_ "quyun/v2/docs"
|
||||||
"quyun/v2/providers/app"
|
"quyun/v2/providers/app"
|
||||||
"quyun/v2/providers/http"
|
"quyun/v2/providers/http"
|
||||||
@@ -24,6 +23,10 @@ import (
|
|||||||
"quyun/v2/providers/jwt"
|
"quyun/v2/providers/jwt"
|
||||||
"quyun/v2/providers/postgres"
|
"quyun/v2/providers/postgres"
|
||||||
|
|
||||||
|
"go.ipao.vip/atom"
|
||||||
|
"go.ipao.vip/atom/container"
|
||||||
|
"go.ipao.vip/atom/contracts"
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v3/middleware/favicon"
|
"github.com/gofiber/fiber/v3/middleware/favicon"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
@@ -36,6 +39,8 @@ func defaultProviders() container.Providers {
|
|||||||
postgres.DefaultProvider(),
|
postgres.DefaultProvider(),
|
||||||
jwt.DefaultProvider(),
|
jwt.DefaultProvider(),
|
||||||
job.DefaultProvider(),
|
job.DefaultProvider(),
|
||||||
|
database.DefaultProvider(),
|
||||||
|
{Provider: services.Provide},
|
||||||
{Provider: api.Provide},
|
{Provider: api.Provide},
|
||||||
{Provider: super.Provide},
|
{Provider: super.Provide},
|
||||||
{Provider: web.Provide},
|
{Provider: web.Provide},
|
||||||
|
|||||||
@@ -40,6 +40,11 @@ func (e *AppError) WithMsg(msg string) *AppError {
|
|||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *AppError) WithMsgf(format string, args ...any) *AppError {
|
||||||
|
msg := fmt.Sprintf(format, args...)
|
||||||
|
return e.WithMsg(msg)
|
||||||
|
}
|
||||||
|
|
||||||
// WithSQL 记录SQL信息
|
// WithSQL 记录SQL信息
|
||||||
func (e *AppError) WithSQL(sql string) *AppError {
|
func (e *AppError) WithSQL(sql string) *AppError {
|
||||||
e.sql = sql
|
e.sql = sql
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
package super
|
package super
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"quyun/v2/app/errorx"
|
||||||
|
"quyun/v2/app/http/super/dto"
|
||||||
|
"quyun/v2/app/services"
|
||||||
"quyun/v2/providers/app"
|
"quyun/v2/providers/app"
|
||||||
|
"quyun/v2/providers/jwt"
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v3"
|
"github.com/gofiber/fiber/v3"
|
||||||
)
|
)
|
||||||
@@ -9,9 +13,27 @@ import (
|
|||||||
// @provider
|
// @provider
|
||||||
type authController struct {
|
type authController struct {
|
||||||
app *app.Config
|
app *app.Config
|
||||||
|
jwt *jwt.JWT
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *authController) auth(ctx fiber.Ctx) error {
|
// @Router /super/v1/auth/login [post]
|
||||||
// user,err:=
|
// @Bind form body
|
||||||
return nil
|
func (ctl *authController) login(ctx fiber.Ctx, form *dto.LoginForm) (*dto.LoginResponse, error) {
|
||||||
|
m, err := services.User.FindByUsername(ctx, form.Username)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errorx.Wrap(err).WithMsg("用户名或密码错误")
|
||||||
|
}
|
||||||
|
|
||||||
|
if ok := m.ComparePassword(ctx, form.Password); !ok {
|
||||||
|
return nil, errorx.Wrap(err).WithMsg("用户名或密码错误")
|
||||||
|
}
|
||||||
|
|
||||||
|
token, err := ctl.jwt.CreateToken(ctl.jwt.CreateClaims(jwt.BaseClaims{
|
||||||
|
UserID: m.ID,
|
||||||
|
}))
|
||||||
|
if err != nil {
|
||||||
|
return nil, errorx.Wrap(err).WithMsg("登录凭证生成失败")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &dto.LoginResponse{Token: token}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,345 +0,0 @@
|
|||||||
package super
|
|
||||||
|
|
||||||
import (
|
|
||||||
"database/sql"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"quyun/v2/app/errorx"
|
|
||||||
"quyun/v2/providers/app"
|
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v3"
|
|
||||||
)
|
|
||||||
|
|
||||||
// @provider
|
|
||||||
type SuperController struct {
|
|
||||||
DB *sql.DB
|
|
||||||
App *app.Config
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SuperController) auth(ctx fiber.Ctx) error {
|
|
||||||
token := ""
|
|
||||||
if s.App != nil && s.App.Super != nil {
|
|
||||||
token = strings.TrimSpace(s.App.Super.Token)
|
|
||||||
}
|
|
||||||
|
|
||||||
if token == "" {
|
|
||||||
if s.App != nil && s.App.IsDevMode() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return errorx.ErrUnauthorized.WithMsg("missing super admin token")
|
|
||||||
}
|
|
||||||
|
|
||||||
auth := strings.TrimSpace(ctx.Get(fiber.HeaderAuthorization))
|
|
||||||
const prefix = "Bearer "
|
|
||||||
if !strings.HasPrefix(auth, prefix) {
|
|
||||||
return errorx.ErrUnauthorized.WithMsg("invalid authorization")
|
|
||||||
}
|
|
||||||
if strings.TrimSpace(strings.TrimPrefix(auth, prefix)) != token {
|
|
||||||
return errorx.ErrUnauthorized.WithMsg("invalid token")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type SuperStatisticsResp struct {
|
|
||||||
TenantsTotal int64 `json:"tenants_total"`
|
|
||||||
TenantsEnabled int64 `json:"tenants_enabled"`
|
|
||||||
TenantAdminsTotal int64 `json:"tenant_admins_total"`
|
|
||||||
TenantAdminsExpired int64 `json:"tenant_admins_expired"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Statistics
|
|
||||||
//
|
|
||||||
// @Router /super/v1/statistics [get]
|
|
||||||
func (s *SuperController) Statistics(ctx fiber.Ctx) error {
|
|
||||||
if err := s.auth(ctx); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var out SuperStatisticsResp
|
|
||||||
|
|
||||||
if err := s.DB.QueryRowContext(ctx.Context(), `SELECT count(*) FROM tenants`).Scan(&out.TenantsTotal); err != nil {
|
|
||||||
return errorx.ErrDatabaseError.WithMsg("database error").WithParams(err.Error())
|
|
||||||
}
|
|
||||||
if err := s.DB.QueryRowContext(ctx.Context(), `SELECT count(*) FROM tenants WHERE status = 0`).Scan(&out.TenantsEnabled); err != nil {
|
|
||||||
return errorx.ErrDatabaseError.WithMsg("database error").WithParams(err.Error())
|
|
||||||
}
|
|
||||||
if err := s.DB.QueryRowContext(ctx.Context(), `SELECT count(*) FROM user_roles WHERE role_code = 'tenant_admin'`).Scan(&out.TenantAdminsTotal); err != nil {
|
|
||||||
return errorx.ErrDatabaseError.WithMsg("database error").WithParams(err.Error())
|
|
||||||
}
|
|
||||||
if err := s.DB.QueryRowContext(ctx.Context(), `SELECT count(*) FROM user_roles WHERE role_code = 'tenant_admin' AND expires_at IS NOT NULL AND expires_at <= now()`).Scan(&out.TenantAdminsExpired); err != nil {
|
|
||||||
return errorx.ErrDatabaseError.WithMsg("database error").WithParams(err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
return ctx.JSON(out)
|
|
||||||
}
|
|
||||||
|
|
||||||
type TenantsQuery struct {
|
|
||||||
Page int `query:"page"`
|
|
||||||
Limit int `query:"limit"`
|
|
||||||
Keyword string `query:"keyword"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type SuperTenantRow struct {
|
|
||||||
ID int64 `json:"id"`
|
|
||||||
TenantCode string `json:"tenant_code"`
|
|
||||||
TenantUUID string `json:"tenant_uuid"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Status int16 `json:"status"`
|
|
||||||
CreatedAt time.Time `json:"created_at"`
|
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
|
||||||
TenantAdminCount int64 `json:"tenant_admin_count"`
|
|
||||||
TenantAdminExpireAt *time.Time `json:"tenant_admin_expire_at,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tenants
|
|
||||||
//
|
|
||||||
// @Router /super/v1/tenants [get]
|
|
||||||
// @Bind query query
|
|
||||||
func (s *SuperController) Tenants(ctx fiber.Ctx, query *TenantsQuery) error {
|
|
||||||
if err := s.auth(ctx); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
page := 1
|
|
||||||
limit := 20
|
|
||||||
keyword := ""
|
|
||||||
if query != nil {
|
|
||||||
if query.Page > 0 {
|
|
||||||
page = query.Page
|
|
||||||
}
|
|
||||||
if query.Limit > 0 {
|
|
||||||
limit = query.Limit
|
|
||||||
}
|
|
||||||
keyword = strings.TrimSpace(query.Keyword)
|
|
||||||
}
|
|
||||||
if limit > 200 {
|
|
||||||
limit = 200
|
|
||||||
}
|
|
||||||
offset := (page - 1) * limit
|
|
||||||
|
|
||||||
where := "1=1"
|
|
||||||
args := []any{}
|
|
||||||
if keyword != "" {
|
|
||||||
where += " AND (lower(t.tenant_code) LIKE $1 OR lower(t.name) LIKE $1)"
|
|
||||||
args = append(args, "%"+strings.ToLower(keyword)+"%")
|
|
||||||
}
|
|
||||||
|
|
||||||
countSQL := "SELECT count(*) FROM tenants t WHERE " + where
|
|
||||||
var total int64
|
|
||||||
if err := s.DB.QueryRowContext(ctx.Context(), countSQL, args...).Scan(&total); err != nil {
|
|
||||||
return errorx.ErrDatabaseError.WithMsg("database error").WithParams(err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
args = append(args, limit, offset)
|
|
||||||
limitArg := "$" + strconv.Itoa(len(args)-1)
|
|
||||||
offsetArg := "$" + strconv.Itoa(len(args))
|
|
||||||
|
|
||||||
sqlStr := `
|
|
||||||
SELECT
|
|
||||||
t.id, t.tenant_code, t.tenant_uuid, t.name, t.status, t.created_at, t.updated_at,
|
|
||||||
COALESCE(a.admin_count, 0) AS admin_count,
|
|
||||||
a.max_expires_at
|
|
||||||
FROM tenants t
|
|
||||||
LEFT JOIN (
|
|
||||||
SELECT tenant_id,
|
|
||||||
count(*) AS admin_count,
|
|
||||||
max(expires_at) AS max_expires_at
|
|
||||||
FROM user_roles
|
|
||||||
WHERE role_code = 'tenant_admin' AND tenant_id IS NOT NULL
|
|
||||||
GROUP BY tenant_id
|
|
||||||
) a ON a.tenant_id = t.id
|
|
||||||
WHERE ` + where + `
|
|
||||||
ORDER BY t.id DESC
|
|
||||||
LIMIT ` + limitArg + ` OFFSET ` + offsetArg
|
|
||||||
|
|
||||||
rows, err := s.DB.QueryContext(ctx.Context(), sqlStr, args...)
|
|
||||||
if err != nil {
|
|
||||||
return errorx.ErrDatabaseError.WithMsg("database error").WithParams(err.Error())
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
|
|
||||||
items := make([]SuperTenantRow, 0, limit)
|
|
||||||
for rows.Next() {
|
|
||||||
var (
|
|
||||||
it SuperTenantRow
|
|
||||||
uuidStr string
|
|
||||||
)
|
|
||||||
if err := rows.Scan(
|
|
||||||
&it.ID,
|
|
||||||
&it.TenantCode,
|
|
||||||
&uuidStr,
|
|
||||||
&it.Name,
|
|
||||||
&it.Status,
|
|
||||||
&it.CreatedAt,
|
|
||||||
&it.UpdatedAt,
|
|
||||||
&it.TenantAdminCount,
|
|
||||||
&it.TenantAdminExpireAt,
|
|
||||||
); err != nil {
|
|
||||||
return errorx.ErrDatabaseError.WithMsg("database error").WithParams(err.Error())
|
|
||||||
}
|
|
||||||
it.TenantUUID = uuidStr
|
|
||||||
items = append(items, it)
|
|
||||||
}
|
|
||||||
if err := rows.Err(); err != nil {
|
|
||||||
return errorx.ErrDatabaseError.WithMsg("database error").WithParams(err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
return ctx.JSON(fiber.Map{
|
|
||||||
"items": items,
|
|
||||||
"total": total,
|
|
||||||
"page": page,
|
|
||||||
"limit": limit,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
type RoleRow struct {
|
|
||||||
Code string `json:"code"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Status int16 `json:"status"`
|
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Roles
|
|
||||||
//
|
|
||||||
// @Router /super/v1/roles [get]
|
|
||||||
func (s *SuperController) Roles(ctx fiber.Ctx) error {
|
|
||||||
if err := s.auth(ctx); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
rows, err := s.DB.QueryContext(ctx.Context(), `SELECT code, name, status, updated_at FROM roles ORDER BY code`)
|
|
||||||
if err != nil {
|
|
||||||
return errorx.ErrDatabaseError.WithMsg("database error").WithParams(err.Error())
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
|
|
||||||
items := make([]RoleRow, 0, 8)
|
|
||||||
for rows.Next() {
|
|
||||||
var it RoleRow
|
|
||||||
if err := rows.Scan(&it.Code, &it.Name, &it.Status, &it.UpdatedAt); err != nil {
|
|
||||||
return errorx.ErrDatabaseError.WithMsg("database error").WithParams(err.Error())
|
|
||||||
}
|
|
||||||
items = append(items, it)
|
|
||||||
}
|
|
||||||
if err := rows.Err(); err != nil {
|
|
||||||
return errorx.ErrDatabaseError.WithMsg("database error").WithParams(err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
return ctx.JSON(fiber.Map{"items": items})
|
|
||||||
}
|
|
||||||
|
|
||||||
type UpdateRoleReq struct {
|
|
||||||
Name *string `json:"name"`
|
|
||||||
Status *int16 `json:"status"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateRole
|
|
||||||
//
|
|
||||||
// @Router /super/v1/roles/:code [put]
|
|
||||||
// @Bind code path
|
|
||||||
// @Bind req body
|
|
||||||
func (s *SuperController) UpdateRole(ctx fiber.Ctx, code string, req *UpdateRoleReq) error {
|
|
||||||
if err := s.auth(ctx); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
code = strings.TrimSpace(code)
|
|
||||||
if code == "" {
|
|
||||||
return errorx.ErrInvalidParameter.WithMsg("missing code")
|
|
||||||
}
|
|
||||||
if req == nil {
|
|
||||||
return errorx.ErrInvalidJSON
|
|
||||||
}
|
|
||||||
|
|
||||||
switch code {
|
|
||||||
case "user", "tenant_admin", "super_admin":
|
|
||||||
default:
|
|
||||||
return errorx.ErrInvalidParameter.WithMsg("unknown role code")
|
|
||||||
}
|
|
||||||
|
|
||||||
set := make([]string, 0, 2)
|
|
||||||
args := make([]any, 0, 3)
|
|
||||||
i := 1
|
|
||||||
|
|
||||||
if req.Name != nil {
|
|
||||||
set = append(set, "name = $"+strconv.Itoa(i))
|
|
||||||
args = append(args, strings.TrimSpace(*req.Name))
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
if req.Status != nil {
|
|
||||||
set = append(set, "status = $"+strconv.Itoa(i))
|
|
||||||
args = append(args, *req.Status)
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
if len(set) == 0 {
|
|
||||||
return ctx.JSON(fiber.Map{"ok": true})
|
|
||||||
}
|
|
||||||
|
|
||||||
set = append(set, "updated_at = now()")
|
|
||||||
args = append(args, code)
|
|
||||||
|
|
||||||
sqlStr := "UPDATE roles SET " + strings.Join(set, ", ") + " WHERE code = $" + strconv.Itoa(i)
|
|
||||||
res, err := s.DB.ExecContext(ctx.Context(), sqlStr, args...)
|
|
||||||
if err != nil {
|
|
||||||
return errorx.ErrDatabaseError.WithMsg("database error").WithParams(err.Error())
|
|
||||||
}
|
|
||||||
aff, _ := res.RowsAffected()
|
|
||||||
if aff == 0 {
|
|
||||||
return fiber.ErrNotFound
|
|
||||||
}
|
|
||||||
return ctx.JSON(fiber.Map{"ok": true})
|
|
||||||
}
|
|
||||||
|
|
||||||
func resolveDistDir(primary, fallback string) string {
|
|
||||||
if st, err := os.Stat(primary); err == nil && st.IsDir() {
|
|
||||||
return primary
|
|
||||||
}
|
|
||||||
return fallback
|
|
||||||
}
|
|
||||||
|
|
||||||
func sendIndex(ctx fiber.Ctx, distDir string) error {
|
|
||||||
indexPath := filepath.Join(distDir, "index.html")
|
|
||||||
if st, err := os.Stat(indexPath); err == nil && !st.IsDir() {
|
|
||||||
return ctx.SendFile(indexPath)
|
|
||||||
}
|
|
||||||
return fiber.ErrNotFound
|
|
||||||
}
|
|
||||||
|
|
||||||
func sendAssetOrIndex(ctx fiber.Ctx, distDir, rel string) error {
|
|
||||||
rel = filepath.Clean(strings.TrimSpace(rel))
|
|
||||||
if rel == "." || rel == "/" {
|
|
||||||
rel = ""
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(rel, "..") {
|
|
||||||
return fiber.ErrBadRequest
|
|
||||||
}
|
|
||||||
|
|
||||||
if rel != "" {
|
|
||||||
assetPath := filepath.Join(distDir, rel)
|
|
||||||
if st, err := os.Stat(assetPath); err == nil && !st.IsDir() {
|
|
||||||
return ctx.SendFile(assetPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return sendIndex(ctx, distDir)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SuperIndex
|
|
||||||
//
|
|
||||||
// @Router /super [get]
|
|
||||||
func (s *SuperController) SuperIndex(ctx fiber.Ctx) error {
|
|
||||||
dist := resolveDistDir("frontend/superadmin/dist", "../frontend/superadmin/dist")
|
|
||||||
return sendIndex(ctx, dist)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SuperWildcard
|
|
||||||
//
|
|
||||||
// @Router /super/* [get]
|
|
||||||
func (s *SuperController) SuperWildcard(ctx fiber.Ctx) error {
|
|
||||||
dist := resolveDistDir("frontend/superadmin/dist", "../frontend/superadmin/dist")
|
|
||||||
return sendAssetOrIndex(ctx, dist, ctx.Params("*"))
|
|
||||||
}
|
|
||||||
10
backend/app/http/super/dto/auth.go
Normal file
10
backend/app/http/super/dto/auth.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package dto
|
||||||
|
|
||||||
|
type LoginForm struct {
|
||||||
|
Username string `json:"username,omitempty"`
|
||||||
|
Password string `json:"password,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type LoginResponse struct {
|
||||||
|
Token string `json:"token,omitempty"`
|
||||||
|
}
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
package super
|
package super
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
|
||||||
|
|
||||||
"quyun/v2/providers/app"
|
"quyun/v2/providers/app"
|
||||||
|
"quyun/v2/providers/jwt"
|
||||||
|
|
||||||
"go.ipao.vip/atom"
|
"go.ipao.vip/atom"
|
||||||
"go.ipao.vip/atom/container"
|
"go.ipao.vip/atom/container"
|
||||||
@@ -14,9 +13,11 @@ import (
|
|||||||
func Provide(opts ...opt.Option) error {
|
func Provide(opts ...opt.Option) error {
|
||||||
if err := container.Container.Provide(func(
|
if err := container.Container.Provide(func(
|
||||||
app *app.Config,
|
app *app.Config,
|
||||||
|
jwt *jwt.JWT,
|
||||||
) (*authController, error) {
|
) (*authController, error) {
|
||||||
obj := &authController{
|
obj := &authController{
|
||||||
app: app,
|
app: app,
|
||||||
|
jwt: jwt,
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj, nil
|
return obj, nil
|
||||||
@@ -24,23 +25,10 @@ func Provide(opts ...opt.Option) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := container.Container.Provide(func(
|
if err := container.Container.Provide(func(
|
||||||
App *app.Config,
|
authController *authController,
|
||||||
DB *sql.DB,
|
|
||||||
) (*SuperController, error) {
|
|
||||||
obj := &SuperController{
|
|
||||||
App: App,
|
|
||||||
DB: DB,
|
|
||||||
}
|
|
||||||
|
|
||||||
return obj, nil
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := container.Container.Provide(func(
|
|
||||||
superController *SuperController,
|
|
||||||
) (contracts.HttpRoute, error) {
|
) (contracts.HttpRoute, error) {
|
||||||
obj := &Routes{
|
obj := &Routes{
|
||||||
superController: superController,
|
authController: authController,
|
||||||
}
|
}
|
||||||
if err := obj.Prepare(); err != nil {
|
if err := obj.Prepare(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
_ "go.ipao.vip/atom"
|
_ "go.ipao.vip/atom"
|
||||||
_ "go.ipao.vip/atom/contracts"
|
_ "go.ipao.vip/atom/contracts"
|
||||||
. "go.ipao.vip/atom/fen"
|
. "go.ipao.vip/atom/fen"
|
||||||
|
"quyun/v2/app/http/super/dto"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Routes implements the HttpRoute contract and provides route registration
|
// Routes implements the HttpRoute contract and provides route registration
|
||||||
@@ -19,7 +20,7 @@ import (
|
|||||||
type Routes struct {
|
type Routes struct {
|
||||||
log *log.Entry `inject:"false"`
|
log *log.Entry `inject:"false"`
|
||||||
// Controller instances
|
// Controller instances
|
||||||
superController *SuperController
|
authController *authController
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare initializes the routes provider with logging configuration.
|
// Prepare initializes the routes provider with logging configuration.
|
||||||
@@ -37,33 +38,11 @@ func (r *Routes) Name() string {
|
|||||||
// Register registers all HTTP routes with the provided fiber router.
|
// Register registers all HTTP routes with the provided fiber router.
|
||||||
// Each route is registered with its corresponding controller action and parameter bindings.
|
// Each route is registered with its corresponding controller action and parameter bindings.
|
||||||
func (r *Routes) Register(router fiber.Router) {
|
func (r *Routes) Register(router fiber.Router) {
|
||||||
// Register routes for controller: SuperController
|
// Register routes for controller: authController
|
||||||
r.log.Debugf("Registering route: Get /super -> superController.SuperIndex")
|
r.log.Debugf("Registering route: Post /super/v1/auth/login -> authController.login")
|
||||||
router.Get("/super", Func0(
|
router.Post("/super/v1/auth/login", DataFunc1(
|
||||||
r.superController.SuperIndex,
|
r.authController.login,
|
||||||
))
|
Body[dto.LoginForm]("form"),
|
||||||
r.log.Debugf("Registering route: Get /super/* -> superController.SuperWildcard")
|
|
||||||
router.Get("/super/*", Func0(
|
|
||||||
r.superController.SuperWildcard,
|
|
||||||
))
|
|
||||||
r.log.Debugf("Registering route: Get /super/v1/roles -> superController.Roles")
|
|
||||||
router.Get("/super/v1/roles", Func0(
|
|
||||||
r.superController.Roles,
|
|
||||||
))
|
|
||||||
r.log.Debugf("Registering route: Get /super/v1/statistics -> superController.Statistics")
|
|
||||||
router.Get("/super/v1/statistics", Func0(
|
|
||||||
r.superController.Statistics,
|
|
||||||
))
|
|
||||||
r.log.Debugf("Registering route: Get /super/v1/tenants -> superController.Tenants")
|
|
||||||
router.Get("/super/v1/tenants", Func1(
|
|
||||||
r.superController.Tenants,
|
|
||||||
Query[TenantsQuery]("query"),
|
|
||||||
))
|
|
||||||
r.log.Debugf("Registering route: Put /super/v1/roles/:code -> superController.UpdateRole")
|
|
||||||
router.Put("/super/v1/roles/:code", Func2(
|
|
||||||
r.superController.UpdateRole,
|
|
||||||
PathParam[string]("code"),
|
|
||||||
Body[UpdateRoleReq]("req"),
|
|
||||||
))
|
))
|
||||||
|
|
||||||
r.log.Info("Successfully registered all routes")
|
r.log.Info("Successfully registered all routes")
|
||||||
|
|||||||
12
backend/super.http
Normal file
12
backend/super.http
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
@host = http://localhost:8080
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Login
|
||||||
|
POST {{ host }}/super/v1/auth/login
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"username":"aa",
|
||||||
|
"password":"bb"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user