fix: issues

This commit is contained in:
Rogee
2025-01-10 11:42:12 +08:00
parent 1c7b603769
commit 0d35aa15de
46 changed files with 1822 additions and 113 deletions

View 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]

View File

@@ -0,0 +1 @@
package users

View 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
}

View 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
}

View 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)
})
})
}