mirror of
https://github.com/muety/wakapi.git
synced 2023-08-10 21:12:56 +03:00
refactor: minor code refactorings
This commit is contained in:
parent
8ca1404f8b
commit
bafbc34706
@ -18,9 +18,7 @@ import (
|
|||||||
"github.com/gorilla/securecookie"
|
"github.com/gorilla/securecookie"
|
||||||
"github.com/jinzhu/configor"
|
"github.com/jinzhu/configor"
|
||||||
"github.com/muety/wakapi/data"
|
"github.com/muety/wakapi/data"
|
||||||
"github.com/muety/wakapi/models"
|
|
||||||
uuid "github.com/satori/go.uuid"
|
uuid "github.com/satori/go.uuid"
|
||||||
"gorm.io/gorm"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -205,45 +203,6 @@ func (c *Config) UseTLS() bool {
|
|||||||
return c.Server.TlsCertPath != "" && c.Server.TlsKeyPath != ""
|
return c.Server.TlsCertPath != "" && c.Server.TlsKeyPath != ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetMigrationFunc(dbDialect string) models.MigrationFunc {
|
|
||||||
switch dbDialect {
|
|
||||||
default:
|
|
||||||
return func(db *gorm.DB) error {
|
|
||||||
if err := db.AutoMigrate(&models.User{}); err != nil && !c.Db.AutoMigrateFailSilently {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := db.AutoMigrate(&models.KeyStringValue{}); err != nil && !c.Db.AutoMigrateFailSilently {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := db.AutoMigrate(&models.Alias{}); err != nil && !c.Db.AutoMigrateFailSilently {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := db.AutoMigrate(&models.Heartbeat{}); err != nil && !c.Db.AutoMigrateFailSilently {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := db.AutoMigrate(&models.Summary{}); err != nil && !c.Db.AutoMigrateFailSilently {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := db.AutoMigrate(&models.SummaryItem{}); err != nil && !c.Db.AutoMigrateFailSilently {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := db.AutoMigrate(&models.LanguageMapping{}); err != nil && !c.Db.AutoMigrateFailSilently {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := db.AutoMigrate(&models.ProjectLabel{}); err != nil && !c.Db.AutoMigrateFailSilently {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := db.AutoMigrate(&models.Diagnostics{}); err != nil && !c.Db.AutoMigrateFailSilently {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := db.AutoMigrate(&models.LeaderboardItem{}); err != nil && !c.Db.AutoMigrateFailSilently {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *appConfig) GetCustomLanguages() map[string]string {
|
func (c *appConfig) GetCustomLanguages() map[string]string {
|
||||||
return utils.CloneStringMap(c.CustomLanguages, false)
|
return utils.CloneStringMap(c.CustomLanguages, false)
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ package config
|
|||||||
import (
|
import (
|
||||||
"github.com/emvi/logbuch"
|
"github.com/emvi/logbuch"
|
||||||
"github.com/getsentry/sentry-go"
|
"github.com/getsentry/sentry-go"
|
||||||
"github.com/muety/wakapi/models"
|
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
@ -89,8 +88,8 @@ func (l *SentryWrapperLogger) log(msg string, level sentry.Level) {
|
|||||||
if h := l.req.Context().Value(sentry.HubContextKey); h != nil {
|
if h := l.req.Context().Value(sentry.HubContextKey); h != nil {
|
||||||
hub := h.(*sentry.Hub)
|
hub := h.(*sentry.Hub)
|
||||||
hub.Scope().SetRequest(l.req)
|
hub.Scope().SetRequest(l.req)
|
||||||
if u := getPrincipal(l.req); u != nil {
|
if uid := getPrincipal(l.req); uid != "" {
|
||||||
hub.Scope().SetUser(sentry.User{ID: u.ID})
|
hub.Scope().SetUser(sentry.User{ID: uid})
|
||||||
}
|
}
|
||||||
hub.CaptureEvent(event)
|
hub.CaptureEvent(event)
|
||||||
return
|
return
|
||||||
@ -133,8 +132,8 @@ func initSentry(config sentryConfig, debug bool) {
|
|||||||
BeforeSend: func(event *sentry.Event, hint *sentry.EventHint) *sentry.Event {
|
BeforeSend: func(event *sentry.Event, hint *sentry.EventHint) *sentry.Event {
|
||||||
if hint.Context != nil {
|
if hint.Context != nil {
|
||||||
if req, ok := hint.Context.Value(sentry.RequestContextKey).(*http.Request); ok {
|
if req, ok := hint.Context.Value(sentry.RequestContextKey).(*http.Request); ok {
|
||||||
if u := getPrincipal(req); u != nil {
|
if uid := getPrincipal(req); uid != "" {
|
||||||
event.User.ID = u.ID
|
event.User.ID = uid
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -145,12 +144,17 @@ func initSentry(config sentryConfig, debug bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getPrincipal(r *http.Request) *models.User {
|
// returns a user id
|
||||||
|
func getPrincipal(r *http.Request) string {
|
||||||
|
type identifiable interface {
|
||||||
|
Identity() string
|
||||||
|
}
|
||||||
type principalGetter interface {
|
type principalGetter interface {
|
||||||
GetPrincipal() *models.User
|
GetPrincipal() *identifiable
|
||||||
}
|
}
|
||||||
|
|
||||||
if p := r.Context().Value("principal"); p != nil {
|
if p := r.Context().Value("principal"); p != nil {
|
||||||
return p.(principalGetter).GetPrincipal()
|
return (*p.(principalGetter).GetPrincipal()).Identity()
|
||||||
}
|
}
|
||||||
return nil
|
return ""
|
||||||
}
|
}
|
||||||
|
@ -3,11 +3,14 @@ package migrations
|
|||||||
import (
|
import (
|
||||||
"github.com/emvi/logbuch"
|
"github.com/emvi/logbuch"
|
||||||
"github.com/muety/wakapi/config"
|
"github.com/muety/wakapi/config"
|
||||||
|
"github.com/muety/wakapi/models"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type gormMigrationFunc func(db *gorm.DB) error
|
||||||
|
|
||||||
type migrationFunc struct {
|
type migrationFunc struct {
|
||||||
f func(db *gorm.DB, cfg *config.Config) error
|
f func(db *gorm.DB, cfg *config.Config) error
|
||||||
name string
|
name string
|
||||||
@ -20,6 +23,45 @@ var (
|
|||||||
postMigrations migrationFuncs
|
postMigrations migrationFuncs
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func GetMigrationFunc(cfg *config.Config) gormMigrationFunc {
|
||||||
|
switch cfg.Db.Dialect {
|
||||||
|
default:
|
||||||
|
return func(db *gorm.DB) error {
|
||||||
|
if err := db.AutoMigrate(&models.User{}); err != nil && !cfg.Db.AutoMigrateFailSilently {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := db.AutoMigrate(&models.KeyStringValue{}); err != nil && !cfg.Db.AutoMigrateFailSilently {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := db.AutoMigrate(&models.Alias{}); err != nil && !cfg.Db.AutoMigrateFailSilently {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := db.AutoMigrate(&models.Heartbeat{}); err != nil && !cfg.Db.AutoMigrateFailSilently {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := db.AutoMigrate(&models.Summary{}); err != nil && !cfg.Db.AutoMigrateFailSilently {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := db.AutoMigrate(&models.SummaryItem{}); err != nil && !cfg.Db.AutoMigrateFailSilently {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := db.AutoMigrate(&models.LanguageMapping{}); err != nil && !cfg.Db.AutoMigrateFailSilently {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := db.AutoMigrate(&models.ProjectLabel{}); err != nil && !cfg.Db.AutoMigrateFailSilently {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := db.AutoMigrate(&models.Diagnostics{}); err != nil && !cfg.Db.AutoMigrateFailSilently {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := db.AutoMigrate(&models.LeaderboardItem{}); err != nil && !cfg.Db.AutoMigrateFailSilently {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func registerPreMigration(f migrationFunc) {
|
func registerPreMigration(f migrationFunc) {
|
||||||
preMigrations = append(preMigrations, f)
|
preMigrations = append(preMigrations, f)
|
||||||
}
|
}
|
||||||
@ -35,7 +77,7 @@ func Run(db *gorm.DB, cfg *config.Config) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func RunSchemaMigrations(db *gorm.DB, cfg *config.Config) {
|
func RunSchemaMigrations(db *gorm.DB, cfg *config.Config) {
|
||||||
if err := cfg.GetMigrationFunc(cfg.Db.Dialect)(db); err != nil {
|
if err := GetMigrationFunc(cfg)(db); err != nil {
|
||||||
logbuch.Fatal(err.Error())
|
logbuch.Fatal(err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"gorm.io/gorm"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -18,8 +17,6 @@ const (
|
|||||||
PersistentIntervalKey = "wakapi_summary_interval"
|
PersistentIntervalKey = "wakapi_summary_interval"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MigrationFunc func(db *gorm.DB) error
|
|
||||||
|
|
||||||
type KeyStringValue struct {
|
type KeyStringValue struct {
|
||||||
Key string `gorm:"primary_key"`
|
Key string `gorm:"primary_key"`
|
||||||
Value string `gorm:"type:text"`
|
Value string `gorm:"type:text"`
|
||||||
@ -35,11 +32,6 @@ type KeyedInterval struct {
|
|||||||
Key *IntervalKey
|
Key *IntervalKey
|
||||||
}
|
}
|
||||||
|
|
||||||
type PageParams struct {
|
|
||||||
Page int `json:"page"`
|
|
||||||
PageSize int `json:"page_size"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// CustomTime is a wrapper type around time.Time, mainly used for the purpose of transparently unmarshalling Python timestamps in the format <sec>.<nsec> (e.g. 1619335137.3324468)
|
// CustomTime is a wrapper type around time.Time, mainly used for the purpose of transparently unmarshalling Python timestamps in the format <sec>.<nsec> (e.g. 1619335137.3324468)
|
||||||
type CustomTime time.Time
|
type CustomTime time.Time
|
||||||
|
|
||||||
@ -105,17 +97,3 @@ func (j CustomTime) T() time.Time {
|
|||||||
func (j CustomTime) Valid() bool {
|
func (j CustomTime) Valid() bool {
|
||||||
return j.T().Unix() >= 0
|
return j.T().Unix() >= 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PageParams) Limit() int {
|
|
||||||
if p.PageSize < 0 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return p.PageSize
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *PageParams) Offset() int {
|
|
||||||
if p.PageSize <= 0 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return (p.Page - 1) * p.PageSize
|
|
||||||
}
|
|
||||||
|
@ -3,6 +3,7 @@ package models
|
|||||||
import (
|
import (
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
conf "github.com/muety/wakapi/config"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -83,6 +84,10 @@ type CountByUser struct {
|
|||||||
Count int64
|
Count int64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *User) Identity() string {
|
||||||
|
return u.ID
|
||||||
|
}
|
||||||
|
|
||||||
func (u *User) TZ() *time.Location {
|
func (u *User) TZ() *time.Location {
|
||||||
if u.Location == "" {
|
if u.Location == "" {
|
||||||
u.Location = "Local"
|
u.Location = "Local"
|
||||||
@ -125,6 +130,15 @@ func (u *User) HasActiveSubscription() bool {
|
|||||||
return u.SubscribedUntil != nil && u.SubscribedUntil.T().After(time.Now())
|
return u.SubscribedUntil != nil && u.SubscribedUntil.T().After(time.Now())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *User) MinDataAge() time.Time {
|
||||||
|
retentionMonths := conf.Get().App.DataRetentionMonths
|
||||||
|
if retentionMonths <= 0 || u.HasActiveSubscription() {
|
||||||
|
return time.Time{}
|
||||||
|
}
|
||||||
|
// this is not exactly precise, because of summer / winter time, etc.
|
||||||
|
return time.Now().AddDate(0, -retentionMonths, 0)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *CredentialsReset) IsValid() bool {
|
func (c *CredentialsReset) IsValid() bool {
|
||||||
return ValidatePassword(c.PasswordNew) &&
|
return ValidatePassword(c.PasswordNew) &&
|
||||||
c.PasswordNew == c.PasswordRepeat
|
c.PasswordNew == c.PasswordRepeat
|
||||||
|
@ -2,6 +2,7 @@ package view
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/muety/wakapi/models"
|
"github.com/muety/wakapi/models"
|
||||||
|
"github.com/muety/wakapi/utils"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -14,7 +15,7 @@ type LeaderboardViewModel struct {
|
|||||||
TopKeys []string
|
TopKeys []string
|
||||||
UserLanguages map[string][]string
|
UserLanguages map[string][]string
|
||||||
ApiKey string
|
ApiKey string
|
||||||
PageParams *models.PageParams
|
PageParams *utils.PageParams
|
||||||
Success string
|
Success string
|
||||||
Error string
|
Error string
|
||||||
}
|
}
|
||||||
|
@ -181,7 +181,7 @@ func (h *SettingsHandler) actionUpdateUser(w http.ResponseWriter, r *http.Reques
|
|||||||
return http.StatusBadRequest, "", "invalid parameters"
|
return http.StatusBadRequest, "", "invalid parameters"
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.Email == "" && user.HasActiveSubscription() {
|
if user.Email == "" && h.config.Subscriptions.Enabled && user.HasActiveSubscription() {
|
||||||
return http.StatusBadRequest, "", "cannot unset email while subscription is active"
|
return http.StatusBadRequest, "", "cannot unset email while subscription is active"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package routes
|
package routes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
conf "github.com/muety/wakapi/config"
|
conf "github.com/muety/wakapi/config"
|
||||||
"github.com/muety/wakapi/helpers"
|
"github.com/muety/wakapi/helpers"
|
||||||
@ -9,8 +10,6 @@ import (
|
|||||||
"github.com/muety/wakapi/models/view"
|
"github.com/muety/wakapi/models/view"
|
||||||
su "github.com/muety/wakapi/routes/utils"
|
su "github.com/muety/wakapi/routes/utils"
|
||||||
"github.com/muety/wakapi/services"
|
"github.com/muety/wakapi/services"
|
||||||
"github.com/muety/wakapi/utils"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -80,9 +79,9 @@ func (h *SummaryHandler) GetIndex(w http.ResponseWriter, r *http.Request) {
|
|||||||
Summary: summary,
|
Summary: summary,
|
||||||
SummaryParams: summaryParams,
|
SummaryParams: summaryParams,
|
||||||
User: user,
|
User: user,
|
||||||
EditorColors: utils.FilterColors(h.config.App.GetEditorColors(), summary.Editors),
|
EditorColors: su.FilterColors(h.config.App.GetEditorColors(), summary.Editors),
|
||||||
LanguageColors: utils.FilterColors(h.config.App.GetLanguageColors(), summary.Languages),
|
LanguageColors: su.FilterColors(h.config.App.GetLanguageColors(), summary.Languages),
|
||||||
OSColors: utils.FilterColors(h.config.App.GetOSColors(), summary.OperatingSystems),
|
OSColors: su.FilterColors(h.config.App.GetOSColors(), summary.OperatingSystems),
|
||||||
ApiKey: user.ApiKey,
|
ApiKey: user.ApiKey,
|
||||||
RawQuery: rawQuery,
|
RawQuery: rawQuery,
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
"github.com/muety/wakapi/models"
|
"github.com/muety/wakapi/models"
|
||||||
"github.com/muety/wakapi/services"
|
"github.com/muety/wakapi/services"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func LoadUserSummary(ss services.ISummaryService, r *http.Request) (*models.Summary, error, int) {
|
func LoadUserSummary(ss services.ISummaryService, r *http.Request) (*models.Summary, error, int) {
|
||||||
@ -38,3 +39,13 @@ func LoadUserSummaryByParams(ss services.ISummaryService, params *models.Summary
|
|||||||
|
|
||||||
return summary, nil, http.StatusOK
|
return summary, nil, http.StatusOK
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func FilterColors(all map[string]string, haystack models.SummaryItems) map[string]string {
|
||||||
|
subset := make(map[string]string)
|
||||||
|
for _, item := range haystack {
|
||||||
|
if c, ok := all[strings.ToLower(item.Key)]; ok {
|
||||||
|
subset[strings.ToLower(item.Key)] = c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return subset
|
||||||
|
}
|
||||||
|
@ -35,9 +35,6 @@ func (s *HousekeepingService) Schedule() {
|
|||||||
|
|
||||||
logbuch.Info("scheduling data cleanup")
|
logbuch.Info("scheduling data cleanup")
|
||||||
|
|
||||||
// this is not exactly precise, because of summer / winter time, etc.
|
|
||||||
retentionDuration := time.Now().Sub(time.Now().AddDate(0, -s.config.App.DataRetentionMonths, 0))
|
|
||||||
|
|
||||||
_, err := s.queueDefault.DispatchCron(func() {
|
_, err := s.queueDefault.DispatchCron(func() {
|
||||||
// fetch all users
|
// fetch all users
|
||||||
users, err := s.userSrvc.GetAll()
|
users, err := s.userSrvc.GetAll()
|
||||||
@ -53,9 +50,13 @@ func (s *HousekeepingService) Schedule() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if u.MinDataAge().IsZero() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
user := *u
|
user := *u
|
||||||
s.queueWorkers.Dispatch(func() {
|
s.queueWorkers.Dispatch(func() {
|
||||||
if err := s.ClearOldUserData(&user, retentionDuration); err != nil {
|
if err := s.CleanUserDataBefore(&user, u.MinDataAge()); err != nil {
|
||||||
config.Log().Error("failed to clear old user data for '%s'", user.ID)
|
config.Log().Error("failed to clear old user data for '%s'", user.ID)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -67,8 +68,7 @@ func (s *HousekeepingService) Schedule() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *HousekeepingService) ClearOldUserData(user *models.User, maxAge time.Duration) error {
|
func (s *HousekeepingService) CleanUserDataBefore(user *models.User, before time.Time) error {
|
||||||
before := time.Now().Add(-maxAge)
|
|
||||||
logbuch.Warn("cleaning up user data for '%s' older than %v", user.ID, before)
|
logbuch.Warn("cleaning up user data for '%s' older than %v", user.ID, before)
|
||||||
|
|
||||||
// clear old heartbeats
|
// clear old heartbeats
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/muety/wakapi/helpers"
|
"github.com/muety/wakapi/helpers"
|
||||||
"github.com/muety/wakapi/models"
|
"github.com/muety/wakapi/models"
|
||||||
"github.com/muety/wakapi/repositories"
|
"github.com/muety/wakapi/repositories"
|
||||||
|
"github.com/muety/wakapi/utils"
|
||||||
"github.com/patrickmn/go-cache"
|
"github.com/patrickmn/go-cache"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -147,7 +148,7 @@ func (srv *LeaderboardService) CountUsers() (int64, error) {
|
|||||||
return count, err
|
return count, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (srv *LeaderboardService) GetByInterval(interval *models.IntervalKey, pageParams *models.PageParams, resolveUsers bool) (models.Leaderboard, error) {
|
func (srv *LeaderboardService) GetByInterval(interval *models.IntervalKey, pageParams *utils.PageParams, resolveUsers bool) (models.Leaderboard, error) {
|
||||||
return srv.GetAggregatedByInterval(interval, nil, pageParams, resolveUsers)
|
return srv.GetAggregatedByInterval(interval, nil, pageParams, resolveUsers)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,7 +156,7 @@ func (srv *LeaderboardService) GetByIntervalAndUser(interval *models.IntervalKey
|
|||||||
return srv.GetAggregatedByIntervalAndUser(interval, userId, nil, resolveUser)
|
return srv.GetAggregatedByIntervalAndUser(interval, userId, nil, resolveUser)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (srv *LeaderboardService) GetAggregatedByInterval(interval *models.IntervalKey, by *uint8, pageParams *models.PageParams, resolveUsers bool) (models.Leaderboard, error) {
|
func (srv *LeaderboardService) GetAggregatedByInterval(interval *models.IntervalKey, by *uint8, pageParams *utils.PageParams, resolveUsers bool) (models.Leaderboard, error) {
|
||||||
// check cache
|
// check cache
|
||||||
cacheKey := srv.getHash(interval, by, "", pageParams)
|
cacheKey := srv.getHash(interval, by, "", pageParams)
|
||||||
if cacheResult, ok := srv.cache.Get(cacheKey); ok {
|
if cacheResult, ok := srv.cache.Get(cacheKey); ok {
|
||||||
@ -259,7 +260,7 @@ func (srv *LeaderboardService) GenerateAggregatedByUser(user *models.User, inter
|
|||||||
return items, nil
|
return items, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (srv *LeaderboardService) getHash(interval *models.IntervalKey, by *uint8, user string, pageParams *models.PageParams) string {
|
func (srv *LeaderboardService) getHash(interval *models.IntervalKey, by *uint8, user string, pageParams *utils.PageParams) string {
|
||||||
k := strings.Join(*interval, "__") + "__" + user
|
k := strings.Join(*interval, "__") + "__" + user
|
||||||
if by != nil && !reflect.ValueOf(by).IsNil() {
|
if by != nil && !reflect.ValueOf(by).IsNil() {
|
||||||
k += "__" + models.GetEntityColumn(*by)
|
k += "__" + models.GetEntityColumn(*by)
|
||||||
|
@ -3,6 +3,7 @@ package services
|
|||||||
import (
|
import (
|
||||||
datastructure "github.com/duke-git/lancet/v2/datastructure/set"
|
datastructure "github.com/duke-git/lancet/v2/datastructure/set"
|
||||||
"github.com/muety/wakapi/models"
|
"github.com/muety/wakapi/models"
|
||||||
|
"github.com/muety/wakapi/utils"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -102,7 +103,7 @@ type IReportService interface {
|
|||||||
|
|
||||||
type IHousekeepingService interface {
|
type IHousekeepingService interface {
|
||||||
Schedule()
|
Schedule()
|
||||||
ClearOldUserData(*models.User, time.Duration) error
|
CleanUserDataBefore(*models.User, time.Time) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type ILeaderboardService interface {
|
type ILeaderboardService interface {
|
||||||
@ -110,9 +111,9 @@ type ILeaderboardService interface {
|
|||||||
ComputeLeaderboard([]*models.User, *models.IntervalKey, []uint8) error
|
ComputeLeaderboard([]*models.User, *models.IntervalKey, []uint8) error
|
||||||
ExistsAnyByUser(string) (bool, error)
|
ExistsAnyByUser(string) (bool, error)
|
||||||
CountUsers() (int64, error)
|
CountUsers() (int64, error)
|
||||||
GetByInterval(*models.IntervalKey, *models.PageParams, bool) (models.Leaderboard, error)
|
GetByInterval(*models.IntervalKey, *utils.PageParams, bool) (models.Leaderboard, error)
|
||||||
GetByIntervalAndUser(*models.IntervalKey, string, bool) (models.Leaderboard, error)
|
GetByIntervalAndUser(*models.IntervalKey, string, bool) (models.Leaderboard, error)
|
||||||
GetAggregatedByInterval(*models.IntervalKey, *uint8, *models.PageParams, bool) (models.Leaderboard, error)
|
GetAggregatedByInterval(*models.IntervalKey, *uint8, *utils.PageParams, bool) (models.Leaderboard, error)
|
||||||
GetAggregatedByIntervalAndUser(*models.IntervalKey, string, *uint8, bool) (models.Leaderboard, error)
|
GetAggregatedByIntervalAndUser(*models.IntervalKey, string, *uint8, bool) (models.Leaderboard, error)
|
||||||
GenerateByUser(*models.User, *models.IntervalKey) (*models.LeaderboardItem, error)
|
GenerateByUser(*models.User, *models.IntervalKey) (*models.LeaderboardItem, error)
|
||||||
GenerateAggregatedByUser(*models.User, *models.IntervalKey, uint8) ([]*models.LeaderboardItem, error)
|
GenerateAggregatedByUser(*models.User, *models.IntervalKey, uint8) ([]*models.LeaderboardItem, error)
|
||||||
|
@ -1,16 +0,0 @@
|
|||||||
package utils
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/muety/wakapi/models"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func FilterColors(all map[string]string, haystack models.SummaryItems) map[string]string {
|
|
||||||
subset := make(map[string]string)
|
|
||||||
for _, item := range haystack {
|
|
||||||
if c, ok := all[strings.ToLower(item.Key)]; ok {
|
|
||||||
subset[strings.ToLower(item.Key)] = c
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return subset
|
|
||||||
}
|
|
@ -2,7 +2,6 @@ package utils
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/muety/wakapi/models"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -22,6 +21,25 @@ func init() {
|
|||||||
cacheMaxAgeRe = regexp.MustCompile(cacheMaxAgePattern)
|
cacheMaxAgeRe = regexp.MustCompile(cacheMaxAgePattern)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PageParams struct {
|
||||||
|
Page int `json:"page"`
|
||||||
|
PageSize int `json:"page_size"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PageParams) Limit() int {
|
||||||
|
if p.PageSize < 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return p.PageSize
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PageParams) Offset() int {
|
||||||
|
if p.PageSize <= 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return (p.Page - 1) * p.PageSize
|
||||||
|
}
|
||||||
|
|
||||||
func IsNoCache(r *http.Request, cacheTtl time.Duration) bool {
|
func IsNoCache(r *http.Request, cacheTtl time.Duration) bool {
|
||||||
cacheControl := r.Header.Get("cache-control")
|
cacheControl := r.Header.Get("cache-control")
|
||||||
if strings.Contains(cacheControl, "no-cache") {
|
if strings.Contains(cacheControl, "no-cache") {
|
||||||
@ -35,8 +53,8 @@ func IsNoCache(r *http.Request, cacheTtl time.Duration) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParsePageParams(r *http.Request) *models.PageParams {
|
func ParsePageParams(r *http.Request) *PageParams {
|
||||||
pageParams := &models.PageParams{}
|
pageParams := &PageParams{}
|
||||||
page := r.URL.Query().Get("page")
|
page := r.URL.Query().Get("page")
|
||||||
pageSize := r.URL.Query().Get("page_size")
|
pageSize := r.URL.Query().Get("page_size")
|
||||||
if p, err := strconv.Atoi(page); err == nil {
|
if p, err := strconv.Atoi(page); err == nil {
|
||||||
@ -48,7 +66,7 @@ func ParsePageParams(r *http.Request) *models.PageParams {
|
|||||||
return pageParams
|
return pageParams
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParsePageParamsWithDefault(r *http.Request, page, size int) *models.PageParams {
|
func ParsePageParamsWithDefault(r *http.Request, page, size int) *PageParams {
|
||||||
pageParams := ParsePageParams(r)
|
pageParams := ParsePageParams(r)
|
||||||
if pageParams.Page == 0 {
|
if pageParams.Page == 0 {
|
||||||
pageParams.Page = page
|
pageParams.Page = page
|
||||||
|
Loading…
x
Reference in New Issue
Block a user