fix: issues
This commit is contained in:
30
backend/app/http/users/controller.go
Normal file
30
backend/app/http/users/controller.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package users
|
||||
|
||||
import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// @provider
|
||||
type Controller struct {
|
||||
svc *Service
|
||||
log *log.Entry `inject:"false"`
|
||||
}
|
||||
|
||||
func (c *Controller) Prepare() error {
|
||||
c.log = log.WithField("module", "users.Controller")
|
||||
return nil
|
||||
}
|
||||
|
||||
// Test godoc
|
||||
//
|
||||
// @Summary Test
|
||||
// @Description Test
|
||||
// @Tags Test
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path int true "AccountID"
|
||||
// @Param queryFilter query dto.AlarmListQuery true "AlarmListQueryFilter"
|
||||
// @Param pageFilter query common.PageQueryFilter true "PageQueryFilter"
|
||||
// @Param sortFilter query common.SortQueryFilter true "SortQueryFilter"
|
||||
// @Success 200 {object} common.PageDataResponse{list=dto.AlarmItem}
|
||||
// @Router /v1/test/:id<int> [get]
|
||||
1
backend/app/http/users/dto.go
Normal file
1
backend/app/http/users/dto.go
Normal file
@@ -0,0 +1 @@
|
||||
package users
|
||||
40
backend/app/http/users/provider.gen.go
Executable file
40
backend/app/http/users/provider.gen.go
Executable file
@@ -0,0 +1,40 @@
|
||||
package users
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
"git.ipao.vip/rogeecn/atom/container"
|
||||
"git.ipao.vip/rogeecn/atom/utils/opt"
|
||||
)
|
||||
|
||||
func Provide(opts ...opt.Option) error {
|
||||
if err := container.Container.Provide(func(
|
||||
svc *Service,
|
||||
) (*Controller, error) {
|
||||
obj := &Controller{
|
||||
svc: svc,
|
||||
}
|
||||
if err := obj.Prepare(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return obj, nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := container.Container.Provide(func(
|
||||
db *sql.DB,
|
||||
) (*Service, error) {
|
||||
obj := &Service{
|
||||
db: db,
|
||||
}
|
||||
if err := obj.Prepare(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return obj, nil
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
201
backend/app/http/users/service.go
Normal file
201
backend/app/http/users/service.go
Normal file
@@ -0,0 +1,201 @@
|
||||
package users
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"time"
|
||||
|
||||
"backend/app/events"
|
||||
"backend/database/fields"
|
||||
"backend/database/models/qvyun_v2/public/model"
|
||||
"backend/database/models/qvyun_v2/public/table"
|
||||
"backend/pkg/oauth"
|
||||
"backend/providers/event"
|
||||
"backend/providers/otel"
|
||||
|
||||
. "github.com/go-jet/jet/v2/postgres"
|
||||
"github.com/samber/lo"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.15.0"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
// @provider:except
|
||||
type Service struct {
|
||||
db *sql.DB
|
||||
event *event.PubSub
|
||||
log *log.Entry `inject:"false"`
|
||||
}
|
||||
|
||||
func (svc *Service) Prepare() error {
|
||||
svc.log = log.WithField("module", "users.service")
|
||||
_ = Int(1)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetUsersByOpenID Get user by open id
|
||||
func (svc *Service) GetUserByOpenID(ctx context.Context, channel fields.AuthChannel, openID string) (*model.Users, error) {
|
||||
_, span := otel.Start(ctx, "users.service.GetUsersByOpenID")
|
||||
defer span.End()
|
||||
|
||||
userId, err := svc.GetUserIDByOpenID(ctx, channel, openID)
|
||||
if err != nil {
|
||||
// span 添加用户不存在事件
|
||||
span.AddEvent("user not found")
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tbl := table.Users
|
||||
stmt := tbl.SELECT(tbl.AllColumns).WHERE(tbl.ID.EQ(Int64(userId)))
|
||||
span.SetAttributes(semconv.DBStatementKey.String(stmt.DebugSql()))
|
||||
|
||||
var user model.Users
|
||||
if err := stmt.QueryContext(ctx, svc.db, &user); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &user, nil
|
||||
}
|
||||
|
||||
func (svc *Service) GetUserIDByOpenID(ctx context.Context, channel fields.AuthChannel, openID string) (int64, error) {
|
||||
_, span := otel.Start(ctx, "users.service.GetUserIDByOpenID")
|
||||
defer span.End()
|
||||
|
||||
span.SetAttributes(
|
||||
attribute.String("channel", channel.String()),
|
||||
attribute.String("openID", openID),
|
||||
)
|
||||
|
||||
tbl := table.UserOauths
|
||||
|
||||
stmt := tbl.
|
||||
SELECT(tbl.UserID.AS("user_id")).
|
||||
WHERE(
|
||||
tbl.Channel.EQ(Int16(int16(channel))).
|
||||
AND(tbl.OpenID.EQ(String(openID))),
|
||||
)
|
||||
span.SetAttributes(semconv.DBStatementKey.String(stmt.DebugSql()))
|
||||
|
||||
var result struct {
|
||||
UserID int64
|
||||
}
|
||||
|
||||
if err := stmt.QueryContext(ctx, svc.db, &result); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return result.UserID, nil
|
||||
}
|
||||
|
||||
// CreateUser
|
||||
func (svc *Service) CreateUser(ctx context.Context, user *model.Users) (*model.Users, error) {
|
||||
_, span := otel.Start(ctx, "users.service.CreateUser")
|
||||
defer span.End()
|
||||
span.SetAttributes(
|
||||
attribute.String("user.username", user.Username),
|
||||
attribute.String("user.email", user.Email),
|
||||
attribute.String("user.phone", user.Phone),
|
||||
)
|
||||
|
||||
if user.CreatedAt.IsZero() {
|
||||
user.CreatedAt = time.Now()
|
||||
}
|
||||
|
||||
if user.UpdatedAt.IsZero() {
|
||||
user.UpdatedAt = time.Now()
|
||||
}
|
||||
|
||||
user.Status = int16(fields.UserStatusPending)
|
||||
|
||||
// use bcrypt to hash password
|
||||
pwd, err := bcrypt.GenerateFromPassword([]byte(user.Password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
user.Password = string(pwd)
|
||||
|
||||
tbl := table.Users
|
||||
stmt := tbl.INSERT(tbl.MutableColumns).MODEL(user).ON_CONFLICT(tbl.Email, tbl.Phone, tbl.Username).DO_NOTHING().RETURNING(tbl.AllColumns)
|
||||
span.SetAttributes(semconv.DBStatementKey.String(stmt.DebugSql()))
|
||||
|
||||
var m model.Users
|
||||
if err = stmt.QueryContext(ctx, svc.db, &m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// if user created successfully, trigger event
|
||||
span.AddEvent("user created")
|
||||
svc.event.Publish(&events.UserRegister{ID: m.ID})
|
||||
|
||||
return &m, err
|
||||
}
|
||||
|
||||
// GetUserByID
|
||||
func (svc *Service) GetUserByID(ctx context.Context, userID int64) (*model.Users, error) {
|
||||
_, span := otel.Start(ctx, "users.service.GetUserByID")
|
||||
defer span.End()
|
||||
span.SetAttributes(
|
||||
attribute.Int64("user.id", userID),
|
||||
)
|
||||
|
||||
tbl := table.Users
|
||||
stmt := tbl.SELECT(tbl.AllColumns).WHERE(tbl.ID.EQ(Int64(userID)))
|
||||
span.SetAttributes(semconv.DBStatementKey.String(stmt.DebugSql()))
|
||||
|
||||
var user model.Users
|
||||
if err := stmt.QueryContext(ctx, svc.db, &user); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &user, nil
|
||||
}
|
||||
|
||||
// AttachUserOAuth
|
||||
func (svc *Service) AttachUserOAuth(ctx context.Context, user *model.Users, channel fields.AuthChannel, oauthInfo oauth.OAuthInfo) error {
|
||||
_, span := otel.Start(ctx, "users.service.AttachUserOAuth")
|
||||
defer span.End()
|
||||
span.SetAttributes(
|
||||
attribute.Int64("user.id", user.ID),
|
||||
attribute.String("channel", channel.String()),
|
||||
attribute.String("openID", oauthInfo.GetOpenID()),
|
||||
)
|
||||
|
||||
m := &model.UserOauths{
|
||||
ID: 0,
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
DeletedAt: nil,
|
||||
Channel: channel,
|
||||
UserID: user.ID,
|
||||
UnionID: lo.ToPtr(oauthInfo.GetUnionID()),
|
||||
OpenID: oauthInfo.GetOpenID(),
|
||||
AccessToken: oauthInfo.GetAccessToken(),
|
||||
RefreshToken: oauthInfo.GetRefreshToken(),
|
||||
ExpireAt: oauthInfo.GetExpiredAt(),
|
||||
Meta: new(string),
|
||||
}
|
||||
|
||||
tbl := table.UserOauths
|
||||
stmt := tbl.
|
||||
INSERT(tbl.MutableColumns).
|
||||
MODEL(m).
|
||||
ON_CONFLICT(tbl.Channel, tbl.UserID).
|
||||
DO_UPDATE(
|
||||
SET(
|
||||
tbl.UnionID.SET(String(oauthInfo.GetUnionID())),
|
||||
tbl.OpenID.SET(String(oauthInfo.GetOpenID())),
|
||||
tbl.AccessToken.SET(String(oauthInfo.GetAccessToken())),
|
||||
tbl.RefreshToken.SET(String(oauthInfo.GetRefreshToken())),
|
||||
tbl.ExpireAt.SET(TimestampT(oauthInfo.GetExpiredAt())),
|
||||
),
|
||||
)
|
||||
|
||||
span.SetAttributes(semconv.DBStatementKey.String(stmt.DebugSql()))
|
||||
|
||||
if _, err := stmt.ExecContext(ctx, svc.db); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
109
backend/app/http/users/service_test.go
Normal file
109
backend/app/http/users/service_test.go
Normal file
@@ -0,0 +1,109 @@
|
||||
package users
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"backend/app/service/testx"
|
||||
"backend/database"
|
||||
"backend/database/fields"
|
||||
"backend/database/models/qvyun_v2/public/model"
|
||||
"backend/database/models/qvyun_v2/public/table"
|
||||
|
||||
"git.ipao.vip/rogeecn/atom/contracts"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"go.uber.org/dig"
|
||||
)
|
||||
|
||||
type ServiceInjectParams struct {
|
||||
dig.In
|
||||
Initials []contracts.Initial `group:"initials"`
|
||||
|
||||
Svc *Service
|
||||
}
|
||||
|
||||
type ServiceTestSuite struct {
|
||||
suite.Suite
|
||||
ServiceInjectParams
|
||||
}
|
||||
|
||||
func Test_DiscoverMedias(t *testing.T) {
|
||||
providers := testx.Default().With(
|
||||
Provide,
|
||||
)
|
||||
|
||||
testx.Serve(providers, t, func(params ServiceInjectParams) {
|
||||
suite.Run(t, &ServiceTestSuite{ServiceInjectParams: params})
|
||||
})
|
||||
}
|
||||
|
||||
func (s *ServiceTestSuite) Test_GetUserIDByOpenID() {
|
||||
Convey("Test GetUserIDByOpenID", s.T(), func() {
|
||||
v, err := fields.AuthChannelWeChat.Value()
|
||||
So(err, ShouldBeNil)
|
||||
So(v, ShouldEqual, 1)
|
||||
|
||||
Convey("truncate tables", func() {
|
||||
err := database.Truncate(context.Background(), s.Svc.db, table.UserOauths.TableName())
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("insert data", func() {
|
||||
m := model.UserOauths{
|
||||
Channel: fields.AuthChannelWeChat,
|
||||
UserID: 1,
|
||||
OpenID: "test_open_id",
|
||||
AccessKey: "test_access_key",
|
||||
AccessToken: "test_access_token",
|
||||
RefreshToken: "test_refresh_token",
|
||||
ExpireAt: time.Now().Add(time.Hour),
|
||||
}
|
||||
|
||||
tbl := table.UserOauths
|
||||
stmt := tbl.INSERT(
|
||||
tbl.MutableColumns.Except(
|
||||
tbl.CreatedAt,
|
||||
tbl.UpdatedAt,
|
||||
tbl.DeletedAt,
|
||||
tbl.UnionID,
|
||||
tbl.Meta,
|
||||
),
|
||||
).MODEL(m)
|
||||
s.T().Log(stmt.Sql())
|
||||
|
||||
_, err := stmt.ExecContext(context.Background(), s.Svc.db)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("get user id by open id", func() {
|
||||
userID, err := s.Svc.GetUserIDByOpenID(context.Background(), fields.AuthChannelWeChat, "test_open_id")
|
||||
So(err, ShouldBeNil)
|
||||
So(userID, ShouldEqual, 1)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// CreateUser
|
||||
func (s *ServiceTestSuite) Test_CreateUser() {
|
||||
Convey("Test CreateUser", s.T(), func() {
|
||||
Convey("truncate tables", func() {
|
||||
err := database.Truncate(context.Background(), s.Svc.db, table.Users.TableName())
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("create user", func() {
|
||||
user := &model.Users{
|
||||
Email: "test@qq.com",
|
||||
Phone: "12345678901",
|
||||
Username: "test",
|
||||
Password: "test",
|
||||
Age: 18,
|
||||
}
|
||||
|
||||
_, err := s.Svc.CreateUser(context.Background(), user)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user