Skip to content

Commit

Permalink
code refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
mayswind committed Aug 19, 2024
1 parent 8fa19df commit 4977979
Show file tree
Hide file tree
Showing 16 changed files with 273 additions and 69 deletions.
10 changes: 10 additions & 0 deletions cmd/initializer.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"
"os"

"github.com/mayswind/ezbookkeeping/pkg/avatars"
"github.com/mayswind/ezbookkeeping/pkg/core"
"github.com/mayswind/ezbookkeeping/pkg/datastore"
"github.com/mayswind/ezbookkeeping/pkg/duplicatechecker"
Expand Down Expand Up @@ -107,6 +108,15 @@ func initializeSystem(c *core.CliContext) (*settings.Config, error) {
return nil, err
}

err = avatars.InitializeAvatarProvider(config)

if err != nil {
if !isDisableBootLog {
log.BootErrorf(c, "[initializer.initializeSystem] initializes avatar provider failed, because %s", err.Error())
}
return nil, err
}

err = mail.InitializeMailer(config)

if err != nil {
Expand Down
10 changes: 10 additions & 0 deletions pkg/api/authorizations.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package api
import (
"github.com/pquerna/otp/totp"

"github.com/mayswind/ezbookkeeping/pkg/avatars"
"github.com/mayswind/ezbookkeeping/pkg/core"
"github.com/mayswind/ezbookkeeping/pkg/errs"
"github.com/mayswind/ezbookkeeping/pkg/log"
Expand All @@ -14,6 +15,7 @@ import (
// AuthorizationsApi represents authorization api
type AuthorizationsApi struct {
ApiUsingConfig
ApiWithUserInfo
users *services.UserService
tokens *services.TokenService
twoFactorAuthorizations *services.TwoFactorAuthorizationService
Expand All @@ -25,6 +27,14 @@ var (
ApiUsingConfig: ApiUsingConfig{
container: settings.Container,
},
ApiWithUserInfo: ApiWithUserInfo{
ApiUsingConfig: ApiUsingConfig{
container: settings.Container,
},
ApiUsingAvatarProvider: ApiUsingAvatarProvider{
container: avatars.Container,
},
},
users: services.Users,
tokens: services.Tokens,
twoFactorAuthorizations: services.TwoFactorAuthorizations,
Expand Down
27 changes: 22 additions & 5 deletions pkg/api/base.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package api

import (
"github.com/mayswind/ezbookkeeping/pkg/avatars"
"github.com/mayswind/ezbookkeeping/pkg/duplicatechecker"
"github.com/mayswind/ezbookkeeping/pkg/models"
"github.com/mayswind/ezbookkeeping/pkg/settings"
Expand All @@ -16,11 +17,6 @@ func (a *ApiUsingConfig) CurrentConfig() *settings.Config {
return a.container.Current
}

// GetUserBasicInfo returns the view-object of user basic info according to the user model
func (a *ApiUsingConfig) GetUserBasicInfo(user *models.User) *models.UserBasicInfo {
return user.ToUserBasicInfo(a.CurrentConfig().AvatarProvider, a.CurrentConfig().RootUrl)
}

// GetAfterRegisterNotificationContent returns the notification content displayed each time users register
func (a *ApiUsingConfig) GetAfterRegisterNotificationContent(userLanguage string, clientLanguage string) string {
language := userLanguage
Expand Down Expand Up @@ -92,3 +88,24 @@ func (a *ApiUsingDuplicateChecker) GetSubmissionRemark(checkerType duplicatechec
func (a *ApiUsingDuplicateChecker) SetSubmissionRemark(checkerType duplicatechecker.DuplicateCheckerType, uid int64, identification string, remark string) {
a.container.SetSubmissionRemark(checkerType, uid, identification, remark)
}

// ApiUsingAvatarProvider represents an api that need to use avatar provider
type ApiUsingAvatarProvider struct {
container *avatars.AvatarProviderContainer
}

// GetAvatarUrl returns the avatar url by the current user avatar provider
func (a *ApiUsingAvatarProvider) GetAvatarUrl(user *models.User) string {
return a.container.GetAvatarUrl(user)
}

// ApiWithUserInfo represents an api that can returns user info
type ApiWithUserInfo struct {
ApiUsingConfig
ApiUsingAvatarProvider
}

// GetUserBasicInfo returns the view-object of user basic info according to the user model
func (a *ApiWithUserInfo) GetUserBasicInfo(user *models.User) *models.UserBasicInfo {
return user.ToUserBasicInfo(a.CurrentConfig().AvatarProvider, a.GetAvatarUrl(user))
}
10 changes: 10 additions & 0 deletions pkg/api/tokens.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"sort"
"time"

"github.com/mayswind/ezbookkeeping/pkg/avatars"
"github.com/mayswind/ezbookkeeping/pkg/core"
"github.com/mayswind/ezbookkeeping/pkg/errs"
"github.com/mayswind/ezbookkeeping/pkg/log"
Expand All @@ -16,6 +17,7 @@ import (
// TokensApi represents token api
type TokensApi struct {
ApiUsingConfig
ApiWithUserInfo
tokens *services.TokenService
users *services.UserService
}
Expand All @@ -26,6 +28,14 @@ var (
ApiUsingConfig: ApiUsingConfig{
container: settings.Container,
},
ApiWithUserInfo: ApiWithUserInfo{
ApiUsingConfig: ApiUsingConfig{
container: settings.Container,
},
ApiUsingAvatarProvider: ApiUsingAvatarProvider{
container: avatars.Container,
},
},
tokens: services.Tokens,
users: services.Users,
}
Expand Down
12 changes: 11 additions & 1 deletion pkg/api/users.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/gin-gonic/gin/binding"

"github.com/mayswind/ezbookkeeping/pkg/avatars"
"github.com/mayswind/ezbookkeeping/pkg/core"
"github.com/mayswind/ezbookkeeping/pkg/errs"
"github.com/mayswind/ezbookkeeping/pkg/locales"
Expand All @@ -20,6 +21,7 @@ import (
// UsersApi represents user api
type UsersApi struct {
ApiUsingConfig
ApiWithUserInfo
users *services.UserService
tokens *services.TokenService
accounts *services.AccountService
Expand All @@ -31,6 +33,14 @@ var (
ApiUsingConfig: ApiUsingConfig{
container: settings.Container,
},
ApiWithUserInfo: ApiWithUserInfo{
ApiUsingConfig: ApiUsingConfig{
container: settings.Container,
},
ApiUsingAvatarProvider: ApiUsingAvatarProvider{
container: avatars.Container,
},
},
users: services.Users,
tokens: services.Tokens,
accounts: services.Accounts,
Expand Down Expand Up @@ -721,5 +731,5 @@ func (a *UsersApi) UserGetAvatarHandler(c *core.WebContext) ([]byte, string, *er
}

func (a *UsersApi) getUserProfileResponse(user *models.User) *models.UserProfileResponse {
return user.ToUserProfileResponse(a.CurrentConfig().AvatarProvider, a.CurrentConfig().RootUrl)
return user.ToUserProfileResponse(a.GetUserBasicInfo(user))
}
8 changes: 8 additions & 0 deletions pkg/avatars/avatar_provider.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package avatars

import "github.com/mayswind/ezbookkeeping/pkg/models"

// AvatarProvider is user avatar provider interface
type AvatarProvider interface {
GetAvatarUrl(user *models.User) string
}
39 changes: 39 additions & 0 deletions pkg/avatars/avatar_provider_container.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package avatars

import (
"github.com/mayswind/ezbookkeeping/pkg/core"
"github.com/mayswind/ezbookkeeping/pkg/errs"
"github.com/mayswind/ezbookkeeping/pkg/models"
"github.com/mayswind/ezbookkeeping/pkg/settings"
)

// AvatarProviderContainer contains the current user avatar provider
type AvatarProviderContainer struct {
Current AvatarProvider
}

// Initialize a user avatar provider container singleton instance
var (
Container = &AvatarProviderContainer{}
)

// InitializeAvatarProvider initializes the current user avatar provider according to the config
func InitializeAvatarProvider(config *settings.Config) error {
if config.AvatarProvider == core.USER_AVATAR_PROVIDER_INTERNAL {
Container.Current = NewInternalStorageAvatarProvider(config)
return nil
} else if config.AvatarProvider == core.USER_AVATAR_PROVIDER_GRAVATAR {
Container.Current = NewGravatarAvatarProvider()
return nil
} else if config.AvatarProvider == "" {
Container.Current = NewNullAvatarProvider()
return nil
}

return errs.ErrInvalidAvatarProvider
}

// GetAvatarUrl returns the avatar url by the current user avatar provider
func (p *AvatarProviderContainer) GetAvatarUrl(user *models.User) string {
return p.Current.GetAvatarUrl(user)
}
31 changes: 31 additions & 0 deletions pkg/avatars/gravatar_provider.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package avatars

import (
"fmt"
"strings"

"github.com/mayswind/ezbookkeeping/pkg/models"
"github.com/mayswind/ezbookkeeping/pkg/utils"
)

// Reference: https://en.gravatar.com/site/implement/hash/
const gravatarUrlFormat = "https://www.gravatar.com/avatar/%s"

// GravatarAvatarProvider represents the gravatar avatar provider
type GravatarAvatarProvider struct {
}

// NewGravatarAvatarProvider returns a new gravatar avatar provider
func NewGravatarAvatarProvider() *GravatarAvatarProvider {
return &GravatarAvatarProvider{}
}

// GetAvatarUrl returns the gravatar url
func (p *GravatarAvatarProvider) GetAvatarUrl(user *models.User) string {
email := user.Email
email = strings.TrimSpace(email)
email = strings.ToLower(email)
emailMd5 := utils.MD5EncodeToString([]byte(email))

return fmt.Sprintf(gravatarUrlFormat, emailMd5)
}
20 changes: 20 additions & 0 deletions pkg/avatars/gravatar_provider_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package avatars

import (
"testing"

"github.com/stretchr/testify/assert"

"github.com/mayswind/ezbookkeeping/pkg/models"
)

func TestGravatarAvatarProvider_GetGravatarUrl(t *testing.T) {
avatarProvider := NewGravatarAvatarProvider()

expectedValue := "https://www.gravatar.com/avatar/0bc83cb571cd1c50ba6f3e8a78ef1346"
actualValue := avatarProvider.GetAvatarUrl(&models.User{
Email: "MyEmailAddress@example.com",
})

assert.Equal(t, expectedValue, actualValue)
}
31 changes: 31 additions & 0 deletions pkg/avatars/internal_storage_provider.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package avatars

import (
"fmt"

"github.com/mayswind/ezbookkeeping/pkg/models"
"github.com/mayswind/ezbookkeeping/pkg/settings"
)

const internalAvatarUrlFormat = "%savatar/%d.%s"

// InternalStorageAvatarProvider represents the internal storage avatar provider
type InternalStorageAvatarProvider struct {
webRootUrl string
}

// NewInternalStorageAvatarProvider returns a new internal storage avatar provider
func NewInternalStorageAvatarProvider(config *settings.Config) *InternalStorageAvatarProvider {
return &InternalStorageAvatarProvider{
webRootUrl: config.RootUrl,
}
}

// GetAvatarUrl returns the built-in avatar url
func (p *InternalStorageAvatarProvider) GetAvatarUrl(user *models.User) string {
if user.CustomAvatarType == "" {
return ""
}

return fmt.Sprintf(internalAvatarUrlFormat, p.webRootUrl, user.Uid, user.CustomAvatarType)
}
38 changes: 38 additions & 0 deletions pkg/avatars/internal_storage_provider_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package avatars

import (
"testing"

"github.com/stretchr/testify/assert"

"github.com/mayswind/ezbookkeeping/pkg/models"
"github.com/mayswind/ezbookkeeping/pkg/settings"
)

func TestInternalStorageAvatarProvider_GetAvatarUrl(t *testing.T) {
avatarProvider := NewInternalStorageAvatarProvider(&settings.Config{
RootUrl: "https://foo.bar/",
})

expectedValue := "https://foo.bar/avatar/1234567890.jpg"
actualValue := avatarProvider.GetAvatarUrl(&models.User{
Uid: 1234567890,
CustomAvatarType: "jpg",
})

assert.Equal(t, expectedValue, actualValue)
}

func TestInternalStorageAvatarProvider_GetAvatarUrl_EmptyCustomAvatarType(t *testing.T) {
avatarProvider := NewInternalStorageAvatarProvider(&settings.Config{
RootUrl: "https://foo.bar/",
})

expectedValue := ""
actualValue := avatarProvider.GetAvatarUrl(&models.User{
Uid: 1234567890,
CustomAvatarType: "",
})

assert.Equal(t, expectedValue, actualValue)
}
19 changes: 19 additions & 0 deletions pkg/avatars/null_avatar_provider.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package avatars

import (
"github.com/mayswind/ezbookkeeping/pkg/models"
)

// NullAvatarProvider represents the null avatar provider
type NullAvatarProvider struct {
}

// NewNullAvatarProvider returns a new null avatar provider
func NewNullAvatarProvider() *NullAvatarProvider {
return &NullAvatarProvider{}
}

// GetAvatarUrl returns an empty url
func (p *NullAvatarProvider) GetAvatarUrl(user *models.User) string {
return ""
}
20 changes: 20 additions & 0 deletions pkg/avatars/null_avatar_provider_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package avatars

import (
"testing"

"github.com/stretchr/testify/assert"

"github.com/mayswind/ezbookkeeping/pkg/models"
)

func TestNullAvatarProvider_GetGravatarUrl(t *testing.T) {
avatarProvider := NewNullAvatarProvider()

expectedValue := ""
actualValue := avatarProvider.GetAvatarUrl(&models.User{
Email: "MyEmailAddress@example.com",
})

assert.Equal(t, expectedValue, actualValue)
}
Loading

0 comments on commit 4977979

Please sign in to comment.