Skip to content

Commit

Permalink
feat(tiphereth): impl RegisterUser
Browse files Browse the repository at this point in the history
  • Loading branch information
MuZhou233 committed Mar 12, 2024
1 parent 4f87179 commit fb70689
Show file tree
Hide file tree
Showing 14 changed files with 235 additions and 10 deletions.
3 changes: 2 additions & 1 deletion app/sephirah/cmd/sephirah/wire_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion app/sephirah/internal/biz/biz.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
// ProviderSet is biz providers.
var ProviderSet = wire.NewSet(
bizangela.ProviderSet,
biztiphereth.NewTiphereth,
biztiphereth.ProviderSet,
bizgebura.NewGebura,
bizbinah.NewBinah,
bizbinah.NewControlBlock,
Expand Down
39 changes: 35 additions & 4 deletions app/sephirah/internal/biz/biztiphereth/tiphereth.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,19 @@ import (
"github.com/tuihub/librarian/app/sephirah/internal/supervisor"
"github.com/tuihub/librarian/internal/lib/libapp"
"github.com/tuihub/librarian/internal/lib/libauth"
"github.com/tuihub/librarian/internal/lib/libcache"
"github.com/tuihub/librarian/internal/lib/libcron"
"github.com/tuihub/librarian/internal/lib/libmq"
"github.com/tuihub/librarian/internal/lib/libtime"
"github.com/tuihub/librarian/internal/lib/logger"
"github.com/tuihub/librarian/internal/model"

"github.com/google/wire"
)

var ProviderSet = wire.NewSet(
NewTiphereth,
NewUserCountCache,
)

type TipherethRepo interface {
Expand All @@ -21,6 +30,7 @@ type TipherethRepo interface {
ListUsers(context.Context, model.Paging, []model.InternalID,
[]libauth.UserType, []modeltiphereth.UserStatus, []model.InternalID,
model.InternalID) ([]*modeltiphereth.User, int64, error)
GetUserCount(context.Context) (int, error)
LinkAccount(context.Context, modeltiphereth.Account, model.InternalID) (model.InternalID, error)
UnLinkAccount(context.Context, modeltiphereth.Account, model.InternalID) error
ListLinkAccounts(context.Context, model.InternalID) ([]*modeltiphereth.Account, error)
Expand Down Expand Up @@ -48,8 +58,9 @@ type Tiphereth struct {
repo TipherethRepo
supv *supervisor.Supervisor
// mapper mapper.LibrarianMapperServiceClient
searcher *client.Searcher
pullAccount *libmq.Topic[modeltiphereth.PullAccountInfo]
searcher *client.Searcher
pullAccount *libmq.Topic[modeltiphereth.PullAccountInfo]
userCountCache *libcache.Key[modeltiphereth.UserCount]
}

func NewTiphereth(
Expand All @@ -61,15 +72,17 @@ func NewTiphereth(
sClient *client.Searcher,
pullAccount *libmq.Topic[modeltiphereth.PullAccountInfo],
cron *libcron.Cron,
userCountCache *libcache.Key[modeltiphereth.UserCount],
) (*Tiphereth, error) {
t := &Tiphereth{
app: app,
auth: auth,
repo: repo,
supv: supv,
//mapper: mClient,
searcher: sClient,
pullAccount: pullAccount,
searcher: sClient,
pullAccount: pullAccount,
userCountCache: userCountCache,
}
err := cron.BySeconds(
"TipherethUpdatePorter",
Expand Down Expand Up @@ -130,3 +143,21 @@ func (t *Tiphereth) CreateConfiguredAdmin() {
return
}
}

func NewUserCountCache(
t TipherethRepo,
store libcache.Store,
) *libcache.Key[modeltiphereth.UserCount] {
return libcache.NewKey[modeltiphereth.UserCount](
store,
"UserCount",
func(ctx context.Context) (*modeltiphereth.UserCount, error) {
res, err := t.GetUserCount(ctx)
if err != nil {
return nil, err
}
return &modeltiphereth.UserCount{Count: res}, nil
},
libcache.WithExpiration(libtime.SevenDays),
)
}
81 changes: 81 additions & 0 deletions app/sephirah/internal/biz/biztiphereth/user.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package biztiphereth

import (
"bytes"
"context"
"strconv"

"github.com/tuihub/librarian/app/sephirah/internal/biz/bizutils"
"github.com/tuihub/librarian/app/sephirah/internal/model/modeltiphereth"
Expand All @@ -11,6 +13,7 @@ import (
"github.com/tuihub/librarian/internal/model"
pb "github.com/tuihub/protos/pkg/librarian/sephirah/v1"

"github.com/dchest/captcha"
"github.com/go-kratos/kratos/v2/errors"
)

Expand Down Expand Up @@ -51,6 +54,7 @@ func (t *Tiphereth) CreateUser(ctx context.Context, user *modeltiphereth.User) (
logger.Infof("repo CreateUser failed: %s", err.Error())
return nil, pb.ErrorErrorReasonUnspecified("%s", err.Error())
}
_ = t.userCountCache.Delete(ctx)
res := user.ID
return &res, nil
}
Expand Down Expand Up @@ -142,3 +146,80 @@ func (t *Tiphereth) GetUser(ctx context.Context, id *model.InternalID) (*modelti
}
return user, nil
}

func (t *Tiphereth) RegisterUser(
ctx context.Context,
username string,
password string,
captchaReq *modeltiphereth.CaptchaAns,
) (*modeltiphereth.CaptchaQue, string, *errors.Error) {
if t.app.EnvExist(libapp.EnvDemoMode) {
return nil, "", pb.ErrorErrorReasonForbidden("server running in demo mode, register user is not allowed")
}
if !t.app.EnvExist(libapp.EnvAllowRegister) {
return nil, "", pb.ErrorErrorReasonForbidden("server not allow register user")
}
if err := t.checkCapacity(ctx); err != nil {
return nil, "", err
}

if captchaReq == nil {
captchaID := captcha.New()
captchaImg := bytes.NewBuffer(nil)
err := captcha.WriteImage(captchaImg, captchaID, 200, 100) //nolint:gomnd // hard code
if err != nil {
return nil, "", pb.ErrorErrorReasonUnspecified("%s", err.Error())
}
return &modeltiphereth.CaptchaQue{
ID: captchaID,
Image: captchaImg.Bytes(),
}, "", nil
}
if !captcha.VerifyString(captchaReq.ID, captchaReq.Value) {
return nil, "", pb.ErrorErrorReasonBadRequest("invalid captcha")
}
passwordParsed, err := t.auth.GeneratePassword(password)
if err != nil {
logger.Infof("generate password failed: %s", err.Error())
return nil, "", pb.ErrorErrorReasonBadRequest("invalid password")
}
id, err := t.searcher.NewID(ctx)
if err != nil {
return nil, "", pb.ErrorErrorReasonUnspecified("%s", err)
}
user := &modeltiphereth.User{
ID: id,
UserName: username,
PassWord: passwordParsed,
Type: libauth.UserTypeNormal,
Status: modeltiphereth.UserStatusActive,
}
if err = t.repo.CreateUser(ctx, user, user.ID); err != nil {
logger.Infof("repo CreateUser failed: %s", err.Error())
return nil, "", pb.ErrorErrorReasonUnspecified("%s", err.Error())
}
_ = t.userCountCache.Delete(ctx)
return nil, "TODO", nil // TODO: return refresh token
}

func (t *Tiphereth) checkCapacity(ctx context.Context) *errors.Error {
if !t.app.EnvExist(libapp.EnvUserCapacity) {
return nil
}
capacityStr, err := t.app.Env(libapp.EnvUserCapacity)
if err != nil {
return pb.ErrorErrorReasonForbidden("server have invalid setting")
}
capacity, err := strconv.Atoi(capacityStr)
if err != nil {
return pb.ErrorErrorReasonForbidden("server have invalid setting")
}
count, err := t.userCountCache.Get(ctx)
if err != nil {
return pb.ErrorErrorReasonUnspecified("%s", err)
}
if count.Count >= capacity {
return pb.ErrorErrorReasonForbidden("server user capacity reached")
}
return nil
}
4 changes: 4 additions & 0 deletions app/sephirah/internal/data/tiphereth.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,10 @@ func (t tipherethRepo) GetUser(ctx context.Context, id model.InternalID) (*model
return converter.ToBizUser(u), nil
}

func (t tipherethRepo) GetUserCount(ctx context.Context) (int, error) {
return t.data.db.User.Query().Count(ctx)
}

func (t tipherethRepo) LinkAccount(
ctx context.Context,
a modeltiphereth.Account,
Expand Down
14 changes: 14 additions & 0 deletions app/sephirah/internal/model/modeltiphereth/modeltiphereth.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,17 @@ const (
SystemTypeLinux
SystemTypeWeb
)

type CaptchaQue struct {
ID string
Image []byte
}

type CaptchaAns struct {
ID string
Value string
}

type UserCount struct {
Count int
}
31 changes: 31 additions & 0 deletions app/sephirah/internal/service/tiphereth.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,37 @@ func (s *LibrarianSephirahServiceService) GainUserPrivilege(ctx context.Context,
AccessToken: string(token),
}, nil
}
func (s *LibrarianSephirahServiceService) RegisterUser(ctx context.Context, req *pb.RegisterUserRequest) (
*pb.RegisterUserResponse, error,
) {
var captchaAns *modeltiphereth.CaptchaAns
if req.GetCaptcha() != nil {
captchaAns = &modeltiphereth.CaptchaAns{
ID: req.GetCaptcha().GetId(),
Value: req.GetCaptcha().GetValue(),
}
}
captchaQue, refreshToken, err := s.t.RegisterUser(
ctx,
req.GetUsername(),
req.GetPassword(),
captchaAns,
)
if err != nil {
return nil, err
}
if len(refreshToken) > 0 {
return &pb.RegisterUserResponse{
Stage: &pb.RegisterUserResponse_RefreshToken{RefreshToken: refreshToken},
}, nil
}
return &pb.RegisterUserResponse{
Stage: &pb.RegisterUserResponse_Captcha{Captcha: &pb.RegisterUserResponse_ImageCaptcha{
Id: captchaQue.ID,
Image: captchaQue.Image,
}},
}, nil
}
func (s *LibrarianSephirahServiceService) RegisterDevice(ctx context.Context, req *pb.RegisterDeviceRequest) (
*pb.RegisterDeviceResponse, error,
) {
Expand Down
3 changes: 2 additions & 1 deletion app/sephirah/pkg/service/wire_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ require (
github.com/bufbuild/protovalidate-go v0.6.0
github.com/cayleygraph/cayley v0.7.7
github.com/cayleygraph/quad v1.2.5
github.com/dchest/captcha v1.0.0
github.com/dgraph-io/ristretto v0.1.1
github.com/fullstorydev/grpchan v1.1.1
github.com/getsentry/sentry-go v0.27.0
Expand All @@ -35,7 +36,7 @@ require (
github.com/redis/go-redis/v9 v9.5.1
github.com/sony/sonyflake v1.2.0
github.com/stretchr/testify v1.8.4
github.com/tuihub/protos v0.4.4
github.com/tuihub/protos v0.4.7
github.com/zhihu/norm v0.1.11
go.opentelemetry.io/otel v1.24.0
go.opentelemetry.io/otel/sdk v1.24.0
Expand Down
6 changes: 4 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dchest/captcha v1.0.0 h1:vw+bm/qMFvTgcjQlYVTuQBJkarm5R0YSsDKhm1HZI2o=
github.com/dchest/captcha v1.0.0/go.mod h1:7zoElIawLp7GUMLcj54K9kbw+jEyvz2K0FDdRRYhvWo=
github.com/dennwc/base v1.0.0/go.mod h1:zaTDIiAcg2oKW9XhjIaRc1kJVteCFXSSW6jwmCedUaI=
github.com/dennwc/graphql v0.0.0-20180603144102-12cfed44bc5d/go.mod h1:lg9KQn0BgRCSCGNpcGvJp/0Ljf1Yxk8TZq9HSYc43fk=
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I=
Expand Down Expand Up @@ -949,8 +951,8 @@ github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+F
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tuihub/protos v0.4.4 h1:C+iZHYVjyXVZvqVF9DqUNudsheLAEyhHRdA5gt43hJw=
github.com/tuihub/protos v0.4.4/go.mod h1:FvaMeevw4RUzHy5kNgbCHWk3fH25ApXEaNmPvDhXozc=
github.com/tuihub/protos v0.4.7 h1:3I16cWt8D4P+kRgkO5xuwVqgyQCWk8sWFsKFRFdgfXY=
github.com/tuihub/protos v0.4.7/go.mod h1:/ilVb9XJASZ7wQg/rnu5L4r451gP6Q3ESMTGQ+OsDHY=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
github.com/tylertreat/BoomFilters v0.0.0-20181028192813-611b3dbe80e8/go.mod h1:OYRfF6eb5wY9VRFkXJH8FFBi3plw2v+giaIu7P054pM=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
Expand Down
2 changes: 2 additions & 0 deletions internal/lib/libapp/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ const (
EnvCreateAdminPassword Env = "CREATE_ADMIN_PASS"
EnvLogLevel Env = "LOG_LEVEL"
EnvDemoMode Env = "DEMO_MODE"
EnvAllowRegister Env = "ALLOW_REGISTER"
EnvUserCapacity Env = "USER_CAPACITY"
)

func NewAppSettings(id, name, version, protoVersion, date string) (*Settings, error) {
Expand Down
1 change: 1 addition & 0 deletions internal/lib/libcache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ func NewStore(c *conf.Cache) (Store, error) {
if err != nil {
return nil, err
}
initCaptchaStore(res)
return res, nil
}

Expand Down
36 changes: 36 additions & 0 deletions internal/lib/libcache/captcha.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package libcache

import (
"context"

"github.com/dchest/captcha"
)

const captchaStoreKey = "captcha"

func initCaptchaStore(store Store) {
captcha.SetCustomStore(&captchaStoreImpl{store})
}

type captchaStoreImpl struct {
store Store
}

func (c *captchaStoreImpl) Set(id string, digits []byte) {
_ = c.store.Set(context.Background(), captchaStoreKey+":"+id, string(digits), WithExpiration(captcha.Expiration))
}

func (c *captchaStoreImpl) Get(id string, clear bool) []byte {
get, err := c.store.Get(context.Background(), captchaStoreKey+":"+id)
if err != nil {
return nil
}
digits, ok := get.(string)
if !ok {
return nil
}
if clear {
_ = c.store.Delete(context.Background(), captchaStoreKey+id)
}
return []byte(digits)
}

0 comments on commit fb70689

Please sign in to comment.