feat add tenant users
This commit is contained in:
@@ -11,13 +11,15 @@ import (
|
||||
func Provide(opts ...opt.Option) error {
|
||||
if err := container.Container.Provide(func(
|
||||
db *gorm.DB,
|
||||
tenant *tenant,
|
||||
test *test,
|
||||
user *user,
|
||||
) (contracts.Initial, error) {
|
||||
obj := &services{
|
||||
db: db,
|
||||
test: test,
|
||||
user: user,
|
||||
db: db,
|
||||
tenant: tenant,
|
||||
test: test,
|
||||
user: user,
|
||||
}
|
||||
if err := obj.Prepare(); err != nil {
|
||||
return nil, err
|
||||
@@ -27,6 +29,13 @@ func Provide(opts ...opt.Option) error {
|
||||
}, atom.GroupInitial); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := container.Container.Provide(func() (*tenant, error) {
|
||||
obj := &tenant{}
|
||||
|
||||
return obj, nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := container.Container.Provide(func() (*test, error) {
|
||||
obj := &test{}
|
||||
|
||||
|
||||
@@ -8,22 +8,25 @@ var _db *gorm.DB
|
||||
|
||||
// exported CamelCase Services
|
||||
var (
|
||||
Test *test
|
||||
User *user
|
||||
Tenant *tenant
|
||||
Test *test
|
||||
User *user
|
||||
)
|
||||
|
||||
// @provider(model)
|
||||
type services struct {
|
||||
db *gorm.DB
|
||||
// define Services
|
||||
test *test
|
||||
user *user
|
||||
tenant *tenant
|
||||
test *test
|
||||
user *user
|
||||
}
|
||||
|
||||
func (svc *services) Prepare() error {
|
||||
_db = svc.db
|
||||
|
||||
// set exported Services here
|
||||
Tenant = svc.tenant
|
||||
Test = svc.test
|
||||
User = svc.user
|
||||
|
||||
|
||||
72
backend/app/services/tenant.go
Normal file
72
backend/app/services/tenant.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"quyun/v2/database/models"
|
||||
"quyun/v2/pkg/consts"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// @provider
|
||||
type tenant struct{}
|
||||
|
||||
func (t *tenant) ContainsUserID(ctx context.Context, tenantID, userID int64) (*models.User, error) {
|
||||
tbl, query := models.TenantUserQuery.QueryContext(ctx)
|
||||
|
||||
_, err := query.Where(tbl.TenantID.Eq(tenantID), tbl.UserID.Eq(userID)).First()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "ContainsUserID failed, tenantID: %d, userID: %d", tenantID, userID)
|
||||
}
|
||||
|
||||
return User.FindByID(ctx, userID)
|
||||
}
|
||||
|
||||
// AddUser
|
||||
func (t *tenant) AddUser(ctx context.Context, tenantID, userID int64) error {
|
||||
tenantUser := &models.TenantUser{
|
||||
TenantID: tenantID,
|
||||
UserID: userID,
|
||||
}
|
||||
|
||||
if err := tenantUser.Create(ctx); err != nil {
|
||||
return errors.Wrapf(err, "AddUser failed, tenantID: %d, userID: %d", tenantID, userID)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveUser
|
||||
func (t *tenant) RemoveUser(ctx context.Context, tenantID, userID int64) error {
|
||||
tbl, query := models.TenantUserQuery.QueryContext(ctx)
|
||||
tenantUser, err := query.Where(tbl.TenantID.Eq(tenantID), tbl.UserID.Eq(userID)).First()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "RemoveUser failed to find, tenantID: %d, userID: %d", tenantID, userID)
|
||||
}
|
||||
|
||||
_, err = tenantUser.Delete(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "RemoveUser failed to delete, tenantID: %d, userID: %d", tenantID, userID)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetUserRole
|
||||
func (t *tenant) SetUserRole(ctx context.Context, tenantID, userID int64, role ...consts.TenantUserRole) error {
|
||||
tbl, query := models.TenantUserQuery.QueryContext(ctx)
|
||||
tenantUser, err := query.Where(tbl.TenantID.Eq(tenantID), tbl.UserID.Eq(userID)).First()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "SetUserRole failed to find, tenantID: %d, userID: %d", tenantID, userID)
|
||||
}
|
||||
|
||||
tenantUser.Role = role
|
||||
if _, err := tenantUser.Update(ctx); err != nil {
|
||||
return errors.Wrapf(err, "SetUserRole failed to update, tenantID: %d, userID: %d", tenantID, userID)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Users
|
||||
func (t *tenant) Users(ctx context.Context, tenantID int64) ([]*models.User, int64, error) {
|
||||
return nil, 0, nil
|
||||
}
|
||||
@@ -3,20 +3,32 @@ package services
|
||||
import (
|
||||
"context"
|
||||
|
||||
"quyun/v2/app/requests"
|
||||
"quyun/v2/database/models"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"go.ipao.vip/gen"
|
||||
)
|
||||
|
||||
// @provider
|
||||
type user struct{}
|
||||
|
||||
func (t *user) FindByID(ctx context.Context, userID int64) (*models.User, error) {
|
||||
tbl, query := models.UserQuery.QueryContext(ctx)
|
||||
|
||||
model, err := query.Where(tbl.ID.Eq(userID)).First()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "FindByID failed, %d", userID)
|
||||
}
|
||||
return model, nil
|
||||
}
|
||||
|
||||
func (t *user) FindByUsername(ctx context.Context, username string) (*models.User, error) {
|
||||
tbl, query := models.UserQuery.QueryContext(ctx)
|
||||
|
||||
model, err := query.Where(tbl.Username.Eq(username)).First()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "FindByusername failed, %s", username)
|
||||
return nil, errors.Wrapf(err, "FindByUsername failed, %s", username)
|
||||
}
|
||||
return model, nil
|
||||
}
|
||||
@@ -31,3 +43,39 @@ func (t *user) Create(ctx context.Context, user *models.User) (*models.User, err
|
||||
}
|
||||
return user, nil
|
||||
}
|
||||
|
||||
type UserPageFilter struct {
|
||||
requests.Pagination
|
||||
requests.SortQueryFilter
|
||||
|
||||
Username *string `query:"username"`
|
||||
TenantID *int64 `query:"tenant_id"`
|
||||
}
|
||||
|
||||
// Page
|
||||
func (t *user) Page(ctx context.Context, filter *UserPageFilter) (*requests.Pager[*models.User], error) {
|
||||
tbl, query := models.UserQuery.QueryContext(ctx)
|
||||
|
||||
conds := []gen.Condition{}
|
||||
if filter.Username != nil {
|
||||
conds = append(conds, tbl.Username.Like("%"+*filter.Username+"%"))
|
||||
}
|
||||
|
||||
if filter.TenantID != nil {
|
||||
tuTbl, _ := models.TenantUserQuery.QueryContext(ctx)
|
||||
query = query.RightJoin(tuTbl, tuTbl.UserID.EqCol(tbl.ID))
|
||||
conds = append(conds, tuTbl.TenantID.Eq(*filter.TenantID))
|
||||
}
|
||||
|
||||
filter.Pagination.Format()
|
||||
items, total, err := query.Where(conds...).Order(tbl.ID.Desc()).FindByPage(int(filter.Offset()), int(filter.Limit))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &requests.Pager[*models.User]{
|
||||
Pagination: requests.Pagination{},
|
||||
Total: total,
|
||||
Items: items,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package services
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"quyun/v2/app/commands/testx"
|
||||
@@ -9,6 +10,7 @@ import (
|
||||
"quyun/v2/database/models"
|
||||
"quyun/v2/pkg/consts"
|
||||
|
||||
"github.com/samber/lo"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
@@ -94,3 +96,107 @@ func (t *UserTestSuite) Test_FindByUsername() {
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// Test_Page
|
||||
func (t *UserTestSuite) Test_Page() {
|
||||
FocusConvey("test page", t.T(), func() {
|
||||
Convey("filter username", func() {
|
||||
database.Truncate(t.T().Context(), t.DB, models.TableNameUser)
|
||||
|
||||
username := "test-user"
|
||||
m := &models.User{
|
||||
Username: username,
|
||||
Password: "test-password",
|
||||
Roles: types.NewArray([]consts.Role{consts.RoleUser}),
|
||||
Status: consts.UserStatusPendingVerify,
|
||||
}
|
||||
|
||||
err := m.Create(t.T().Context())
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
pager, err := User.Page(t.T().Context(), &UserPageFilter{
|
||||
Username: &username,
|
||||
})
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(pager.Total, ShouldEqual, 1)
|
||||
})
|
||||
|
||||
FocusConvey("filter tenant users", func() {
|
||||
database.Truncate(
|
||||
t.T().Context(),
|
||||
t.DB,
|
||||
models.TableNameUser,
|
||||
models.TableNameTenant,
|
||||
models.TableNameTenantUser,
|
||||
)
|
||||
|
||||
username := "test-user"
|
||||
m := &models.User{
|
||||
Username: username,
|
||||
Password: "test-password",
|
||||
Roles: types.NewArray([]consts.Role{consts.RoleUser}),
|
||||
Status: consts.UserStatusPendingVerify,
|
||||
}
|
||||
|
||||
err := m.Create(t.T().Context())
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
m = &models.User{
|
||||
Username: username + "02",
|
||||
Password: "test-password",
|
||||
Roles: types.NewArray([]consts.Role{consts.RoleUser}),
|
||||
Status: consts.UserStatusPendingVerify,
|
||||
}
|
||||
|
||||
err = m.Create(t.T().Context())
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
tenantModel := &models.Tenant{
|
||||
UserID: 1,
|
||||
Code: "abc",
|
||||
UUID: types.NewUUIDv4(),
|
||||
Name: "T01",
|
||||
Status: consts.TenantStatusVerified,
|
||||
}
|
||||
|
||||
err = tenantModel.Create(t.T().Context())
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
tenantModel = &models.Tenant{
|
||||
UserID: 2,
|
||||
Code: "abc01",
|
||||
UUID: types.NewUUIDv4(),
|
||||
Name: "T02",
|
||||
Status: consts.TenantStatusVerified,
|
||||
}
|
||||
|
||||
err = tenantModel.Create(t.T().Context())
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
count := 12
|
||||
for i := 0; i < count; i++ {
|
||||
m = &models.User{
|
||||
Username: fmt.Sprintf("user_%d", i),
|
||||
Password: "test-password",
|
||||
Roles: types.NewArray([]consts.Role{consts.RoleUser}),
|
||||
Status: consts.UserStatusPendingVerify,
|
||||
}
|
||||
|
||||
err = m.Create(t.T().Context())
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
// create tenant user
|
||||
err = Tenant.AddUser(t.T().Context(), int64(i%2+1), m.ID)
|
||||
So(err, ShouldBeNil)
|
||||
}
|
||||
|
||||
pager, err := User.Page(t.T().Context(), &UserPageFilter{
|
||||
TenantID: lo.ToPtr(int64(1)),
|
||||
})
|
||||
|
||||
So(err, ShouldBeNil)
|
||||
So(pager.Total, ShouldEqual, 6)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user