202 lines
8.1 KiB
Go
202 lines
8.1 KiB
Go
package api
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
|
|
"github.com/mayswind/ezbookkeeping/pkg/avatars"
|
|
"github.com/mayswind/ezbookkeeping/pkg/core"
|
|
"github.com/mayswind/ezbookkeeping/pkg/duplicatechecker"
|
|
"github.com/mayswind/ezbookkeeping/pkg/errs"
|
|
"github.com/mayswind/ezbookkeeping/pkg/log"
|
|
"github.com/mayswind/ezbookkeeping/pkg/models"
|
|
"github.com/mayswind/ezbookkeeping/pkg/settings"
|
|
"github.com/mayswind/ezbookkeeping/pkg/utils"
|
|
)
|
|
|
|
const internalTransactionPictureUrlFormat = "%spictures/%d.%s"
|
|
|
|
// ApiUsingConfig represents an api that need to use config
|
|
type ApiUsingConfig struct {
|
|
container *settings.ConfigContainer
|
|
}
|
|
|
|
// CurrentConfig returns the current config
|
|
func (a *ApiUsingConfig) CurrentConfig() *settings.Config {
|
|
return a.container.Current
|
|
}
|
|
|
|
// GetTransactionPictureInfoResponse returns the view-object of transaction picture basic info according to the transaction picture model
|
|
func (a *ApiUsingConfig) GetTransactionPictureInfoResponse(pictureInfo *models.TransactionPictureInfo) *models.TransactionPictureInfoBasicResponse {
|
|
originalUrl := fmt.Sprintf(internalTransactionPictureUrlFormat, a.CurrentConfig().RootUrl, pictureInfo.PictureId, pictureInfo.PictureExtension)
|
|
return pictureInfo.ToTransactionPictureInfoBasicResponse(originalUrl)
|
|
}
|
|
|
|
// GetTransactionPictureInfoResponseList returns the view-object list of transaction picture basic info according to the transaction picture model
|
|
func (a *ApiUsingConfig) GetTransactionPictureInfoResponseList(pictureInfos []*models.TransactionPictureInfo) models.TransactionPictureInfoBasicResponseSlice {
|
|
pictureInfoResps := make(models.TransactionPictureInfoBasicResponseSlice, len(pictureInfos))
|
|
|
|
for i := 0; i < len(pictureInfos); i++ {
|
|
pictureInfoResps[i] = a.GetTransactionPictureInfoResponse(pictureInfos[i])
|
|
}
|
|
|
|
sort.Sort(pictureInfoResps)
|
|
|
|
return pictureInfoResps
|
|
}
|
|
|
|
// GetAfterRegisterNotificationContent returns the notification content displayed each time users register
|
|
func (a *ApiUsingConfig) GetAfterRegisterNotificationContent(userLanguage string, clientLanguage string) string {
|
|
language := userLanguage
|
|
|
|
if language == "" {
|
|
language = clientLanguage
|
|
}
|
|
|
|
if !a.container.Current.AfterRegisterNotification.Enabled {
|
|
return ""
|
|
}
|
|
|
|
if multiLanguageContent, exists := a.container.Current.AfterRegisterNotification.MultiLanguageContent[language]; exists {
|
|
return multiLanguageContent
|
|
}
|
|
|
|
return a.container.Current.AfterRegisterNotification.DefaultContent
|
|
}
|
|
|
|
// GetAfterLoginNotificationContent returns the notification content displayed each time users log in
|
|
func (a *ApiUsingConfig) GetAfterLoginNotificationContent(userLanguage string, clientLanguage string) string {
|
|
language := userLanguage
|
|
|
|
if language == "" {
|
|
language = clientLanguage
|
|
}
|
|
|
|
if !a.container.Current.AfterLoginNotification.Enabled {
|
|
return ""
|
|
}
|
|
|
|
if multiLanguageContent, exists := a.container.Current.AfterLoginNotification.MultiLanguageContent[language]; exists {
|
|
return multiLanguageContent
|
|
}
|
|
|
|
return a.container.Current.AfterLoginNotification.DefaultContent
|
|
}
|
|
|
|
// GetAfterOpenNotificationContent returns the notification content displayed each time users open the app
|
|
func (a *ApiUsingConfig) GetAfterOpenNotificationContent(userLanguage string, clientLanguage string) string {
|
|
language := userLanguage
|
|
|
|
if language == "" {
|
|
language = clientLanguage
|
|
}
|
|
|
|
if !a.container.Current.AfterOpenNotification.Enabled {
|
|
return ""
|
|
}
|
|
|
|
if multiLanguageContent, exists := a.container.Current.AfterOpenNotification.MultiLanguageContent[language]; exists {
|
|
return multiLanguageContent
|
|
}
|
|
|
|
return a.container.Current.AfterOpenNotification.DefaultContent
|
|
}
|
|
|
|
// ApiUsingDuplicateChecker represents an api that need to use duplicate checker
|
|
type ApiUsingDuplicateChecker struct {
|
|
ApiUsingConfig
|
|
container *duplicatechecker.DuplicateCheckerContainer
|
|
}
|
|
|
|
// GetSubmissionRemark returns whether the same submission has been processed and related remark by the current duplicate checker
|
|
func (a *ApiUsingDuplicateChecker) GetSubmissionRemark(checkerType duplicatechecker.DuplicateCheckerType, uid int64, identification string) (bool, string) {
|
|
return a.container.GetSubmissionRemark(checkerType, uid, identification)
|
|
}
|
|
|
|
// SetSubmissionRemark saves the identification and remark to in-memory cache by the current duplicate checker
|
|
func (a *ApiUsingDuplicateChecker) SetSubmissionRemark(checkerType duplicatechecker.DuplicateCheckerType, uid int64, identification string, remark string) {
|
|
a.container.SetSubmissionRemark(checkerType, uid, identification, remark)
|
|
}
|
|
|
|
// CheckFailureCount returns whether the failure count of the specified IP and user has reached the limit and increases the failure count
|
|
func (a *ApiUsingDuplicateChecker) CheckFailureCount(c *core.WebContext, uid int64) error {
|
|
if a.CurrentConfig().MaxFailuresPerIpPerMinute > 0 {
|
|
clientIp := c.ClientIP()
|
|
ipFailureCount := a.container.GetFailureCount(clientIp)
|
|
|
|
if ipFailureCount >= a.CurrentConfig().MaxFailuresPerIpPerMinute {
|
|
log.Warnf(c, "[base.CheckFailureCount] operation failure via IP \"%s\", current failure count: %d reached the limit", clientIp, ipFailureCount)
|
|
return errs.ErrFailureCountLimitReached
|
|
}
|
|
}
|
|
|
|
if a.CurrentConfig().MaxFailuresPerUserPerMinute > 0 && uid > 0 {
|
|
uidFailureCount := a.container.GetFailureCount(utils.Int64ToString(uid))
|
|
|
|
if uidFailureCount >= a.CurrentConfig().MaxFailuresPerUserPerMinute {
|
|
log.Warnf(c, "[base.CheckFailureCount] operation failure via uid \"%d\", current failure count: %d reached the limit", uid, uidFailureCount)
|
|
return errs.ErrFailureCountLimitReached
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// CheckAndIncreaseFailureCount returns whether the failure count of the specified IP and user has reached the limit and increases the failure count
|
|
func (a *ApiUsingDuplicateChecker) CheckAndIncreaseFailureCount(c *core.WebContext, uid int64) error {
|
|
clientIp := c.ClientIP()
|
|
ipFailureCount := uint32(0)
|
|
uidFailureCount := uint32(0)
|
|
|
|
if a.CurrentConfig().MaxFailuresPerIpPerMinute > 0 {
|
|
ipFailureCount = a.container.GetFailureCount(clientIp)
|
|
}
|
|
|
|
if a.CurrentConfig().MaxFailuresPerUserPerMinute > 0 && uid > 0 {
|
|
uidFailureCount = a.container.GetFailureCount(utils.Int64ToString(uid))
|
|
}
|
|
|
|
if a.CurrentConfig().MaxFailuresPerIpPerMinute > 0 && ipFailureCount < a.CurrentConfig().MaxFailuresPerIpPerMinute {
|
|
log.Warnf(c, "[base.CheckAndIncreaseFailureCount] operation failure via IP \"%s\", previous failure count: %d", clientIp, ipFailureCount)
|
|
a.container.IncreaseFailureCount(clientIp)
|
|
}
|
|
|
|
if a.CurrentConfig().MaxFailuresPerUserPerMinute > 0 && uid > 0 && uidFailureCount < a.CurrentConfig().MaxFailuresPerUserPerMinute {
|
|
log.Warnf(c, "[base.CheckAndIncreaseFailureCount] operation failure via uid \"%d\", previous failure count: %d", uid, uidFailureCount)
|
|
a.container.IncreaseFailureCount(utils.Int64ToString(uid))
|
|
}
|
|
|
|
if a.CurrentConfig().MaxFailuresPerIpPerMinute > 0 && ipFailureCount >= a.CurrentConfig().MaxFailuresPerIpPerMinute {
|
|
log.Warnf(c, "[base.CheckAndIncreaseFailureCount] operation failure via IP \"%s\", current failure count: %d reached the limit", clientIp, ipFailureCount)
|
|
return errs.ErrFailureCountLimitReached
|
|
}
|
|
|
|
if a.CurrentConfig().MaxFailuresPerUserPerMinute > 0 && uid > 0 && uidFailureCount >= a.CurrentConfig().MaxFailuresPerUserPerMinute {
|
|
log.Warnf(c, "[base.CheckAndIncreaseFailureCount] operation failure via uid \"%d\", current failure count: %d reached the limit", uid, uidFailureCount)
|
|
return errs.ErrFailureCountLimitReached
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// 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))
|
|
}
|