diff --git a/internal/account/service.go b/internal/account/service.go index f367c7a..d0e2916 100644 --- a/internal/account/service.go +++ b/internal/account/service.go @@ -4,6 +4,11 @@ import ( "context" "errors" "feedsystem_video_go/internal/auth" + "fmt" + "log" + "time" + + rediscache "feedsystem_video_go/internal/redis" "github.com/go-sql-driver/mysql" "golang.org/x/crypto/bcrypt" @@ -12,6 +17,7 @@ import ( type AccountService struct { accountRepository *AccountRepository + cache *rediscache.Client } var ( @@ -19,8 +25,8 @@ var ( ErrNewUsernameRequired = errors.New("new_username is required") ) -func NewAccountService(accountRepository *AccountRepository) *AccountService { - return &AccountService{accountRepository: accountRepository} +func NewAccountService(accountRepository *AccountRepository, cache *rediscache.Client) *AccountService { + return &AccountService{accountRepository: accountRepository, cache: cache} } func (as *AccountService) CreateAccount(ctx context.Context, account *Account) error { @@ -55,7 +61,14 @@ func (as *AccountService) Rename(ctx context.Context, accountID uint, newUsernam } return "", err } + if as.cache != nil { + cacheCtx, cancel := context.WithTimeout(ctx, 50*time.Millisecond) + defer cancel() + if err := as.cache.SetBytes(cacheCtx, fmt.Sprintf("account:%d", accountID), []byte(token), 24*time.Hour); err != nil { + log.Printf("failed to set cache: %v", err) + } + } return token, nil } @@ -74,7 +87,9 @@ func (as *AccountService) ChangePassword(ctx context.Context, username, oldPassw if err := as.accountRepository.ChangePassword(ctx, account.ID, string(passwordHash)); err != nil { return err } - as.Logout(ctx, account.ID) + if err := as.Logout(ctx, account.ID); err != nil { + return err + } return nil } @@ -110,7 +125,14 @@ func (as *AccountService) Login(ctx context.Context, username, password string) if err := as.accountRepository.Login(ctx, account.ID, token); err != nil { return "", err } + if as.cache != nil { + cacheCtx, cancel := context.WithTimeout(ctx, 50*time.Millisecond) + defer cancel() + if err := as.cache.SetBytes(cacheCtx, fmt.Sprintf("account:%d", account.ID), []byte(token), 24*time.Hour); err != nil { + log.Printf("failed to set cache: %v", err) + } + } return token, nil } @@ -120,7 +142,15 @@ func (as *AccountService) Logout(ctx context.Context, accountID uint) error { return err } if account.Token == "" { - return errors.New("account already logged out") + return nil + } + if as.cache != nil { + cacheCtx, cancel := context.WithTimeout(ctx, 50*time.Millisecond) + defer cancel() + + if err := as.cache.Del(cacheCtx, fmt.Sprintf("account:%d", account.ID)); err != nil { + log.Printf("failed to del cache: %v", err) + } } return as.accountRepository.Logout(ctx, account.ID) } diff --git a/internal/http/router.go b/internal/http/router.go index 3fabb0d..d0407e4 100644 --- a/internal/http/router.go +++ b/internal/http/router.go @@ -16,7 +16,7 @@ func SetRouter(db *gorm.DB, cache *rediscache.Client) *gin.Engine { r := gin.Default() // account accountRepository := account.NewAccountRepository(db) - accountService := account.NewAccountService(accountRepository) + accountService := account.NewAccountService(accountRepository, cache) accountHandler := account.NewAccountHandler(accountService) accountGroup := r.Group("/account") { @@ -27,7 +27,7 @@ func SetRouter(db *gorm.DB, cache *rediscache.Client) *gin.Engine { accountGroup.POST("/findByUsername", accountHandler.FindByUsername) } protectedAccountGroup := accountGroup.Group("") - protectedAccountGroup.Use(middleware.JWTAuth(accountRepository)) + protectedAccountGroup.Use(middleware.JWTAuth(accountRepository, cache)) { protectedAccountGroup.POST("/logout", accountHandler.Logout) protectedAccountGroup.POST("/rename", accountHandler.Rename) @@ -42,7 +42,7 @@ func SetRouter(db *gorm.DB, cache *rediscache.Client) *gin.Engine { videoGroup.POST("/getDetail", videoHandler.GetDetail) } protectedVideoGroup := videoGroup.Group("") - protectedVideoGroup.Use(middleware.JWTAuth(accountRepository)) + protectedVideoGroup.Use(middleware.JWTAuth(accountRepository, cache)) { protectedVideoGroup.POST("/publish", videoHandler.PublishVideo) } @@ -52,7 +52,7 @@ func SetRouter(db *gorm.DB, cache *rediscache.Client) *gin.Engine { likeHandler := video.NewLikeHandler(likeService) likeGroup := r.Group("/like") protectedLikeGroup := likeGroup.Group("") - protectedLikeGroup.Use(middleware.JWTAuth(accountRepository)) + protectedLikeGroup.Use(middleware.JWTAuth(accountRepository, cache)) { protectedLikeGroup.POST("/like", likeHandler.Like) protectedLikeGroup.POST("/unlike", likeHandler.Unlike) @@ -67,7 +67,7 @@ func SetRouter(db *gorm.DB, cache *rediscache.Client) *gin.Engine { commentGroup.POST("/listAll", commentHandler.GetAllComments) } protectedCommentGroup := commentGroup.Group("") - protectedCommentGroup.Use(middleware.JWTAuth(accountRepository)) + protectedCommentGroup.Use(middleware.JWTAuth(accountRepository, cache)) { protectedCommentGroup.POST("/publish", commentHandler.PublishComment) protectedCommentGroup.POST("/delete", commentHandler.DeleteComment) @@ -78,7 +78,7 @@ func SetRouter(db *gorm.DB, cache *rediscache.Client) *gin.Engine { socialHandler := social.NewSocialHandler(socialService) socialGroup := r.Group("/social") protectedSocialGroup := socialGroup.Group("") - protectedSocialGroup.Use(middleware.JWTAuth(accountRepository)) + protectedSocialGroup.Use(middleware.JWTAuth(accountRepository, cache)) { protectedSocialGroup.POST("/follow", socialHandler.Follow) protectedSocialGroup.POST("/unfollow", socialHandler.Unfollow) @@ -90,13 +90,13 @@ func SetRouter(db *gorm.DB, cache *rediscache.Client) *gin.Engine { feedService := feed.NewFeedService(feedRepository, likeRepository, cache) feedHandler := feed.NewFeedHandler(feedService) feedGroup := r.Group("/feed") - feedGroup.Use(middleware.SoftJWTAuth(accountRepository)) + feedGroup.Use(middleware.SoftJWTAuth(accountRepository, cache)) { feedGroup.POST("/listLatest", feedHandler.ListLatest) feedGroup.POST("/listLikesCount", feedHandler.ListLikesCount) } protectedFeedGroup := feedGroup.Group("") - protectedFeedGroup.Use(middleware.JWTAuth(accountRepository)) + protectedFeedGroup.Use(middleware.JWTAuth(accountRepository, cache)) { protectedFeedGroup.POST("/listByFollowing", feedHandler.ListByFollowing) } diff --git a/internal/redis/cache.go b/internal/redis/cache.go index 87fc211..416ce9e 100644 --- a/internal/redis/cache.go +++ b/internal/redis/cache.go @@ -58,6 +58,10 @@ func (c *Client) SetBytes(ctx context.Context, key string, value []byte, ttl tim return c.rdb.Set(ctx, key, value, ttl).Err() } +func (c *Client) Del(ctx context.Context, key string) error { + return c.rdb.Del(ctx, key).Err() +} + func IsMiss(err error) bool { return err == redis.Nil }