♻️ Rebuilt cache with the new cache system from nexus

This commit is contained in:
2025-03-29 13:15:20 +08:00
parent c8e8104d5d
commit a4c6e9a905
15 changed files with 188 additions and 752 deletions

View File

@ -1,24 +0,0 @@
package cache
import (
"github.com/dgraph-io/ristretto"
"github.com/eko/gocache/lib/v4/store"
ristrettoCache "github.com/eko/gocache/store/ristretto/v4"
)
var S store.StoreInterface
func NewStore() error {
ris, err := ristretto.NewCache(&ristretto.Config{
NumCounters: 1e7,
MaxCost: 1 << 27,
BufferItems: 64,
})
if err != nil {
return err
}
S = ristrettoCache.NewRistretto(ris)
return nil
}

View File

@ -1,18 +1,17 @@
package gap
import (
"errors"
"fmt"
"strings"
"time"
"git.solsynth.dev/hypernet/nexus/pkg/nex/cachekit"
"git.solsynth.dev/hypernet/nexus/pkg/nex/localize"
"git.solsynth.dev/hypernet/nexus/pkg/nex"
"git.solsynth.dev/hypernet/nexus/pkg/nex/rx"
"git.solsynth.dev/hypernet/nexus/pkg/proto"
"git.solsynth.dev/hypernet/pusher/pkg/pushkit/pushcon"
"github.com/nats-io/nats.go"
"github.com/rs/zerolog/log"
"github.com/samber/lo"
@ -23,7 +22,7 @@ var (
Nx *nex.Conn
Px *pushcon.Conn
Rx *rx.MqConn
Jt nats.JetStreamContext
Ca *cachekit.CaConn
)
const (
@ -65,20 +64,9 @@ func InitializeToNexus() error {
if err != nil {
return fmt.Errorf("error during initialize nexus rx module: %v", err)
}
Jt, err = Rx.Nt.JetStream()
Ca, err = cachekit.NewCaConn(Nx, time.Second*3)
if err != nil {
return fmt.Errorf("error during initialize nats jetstream: %v", err)
}
jetstreamCfg := &nats.StreamConfig{
Name: "OTPs",
Subjects: []string{fmt.Sprintf("%s>", FactorOtpPrefix)},
Storage: nats.MemoryStorage,
MaxAge: 30 * time.Minute,
}
_, err = Jt.AddStream(jetstreamCfg)
if err != nil && !errors.Is(err, nats.ErrStreamNameAlreadyInUse) {
return fmt.Errorf("error during initialize jetstream stream: %v", err)
return fmt.Errorf("error during initialize nexus cache module: %v", err)
}
return err

View File

@ -4,81 +4,26 @@ import (
"context"
"fmt"
"maps"
"git.solsynth.dev/hypernet/nexus/pkg/proto"
"git.solsynth.dev/hypernet/passport/pkg/authkit/models"
localCache "git.solsynth.dev/hypernet/passport/pkg/internal/cache"
"git.solsynth.dev/hypernet/passport/pkg/internal/database"
"git.solsynth.dev/hypernet/passport/pkg/internal/services"
"github.com/eko/gocache/lib/v4/cache"
"github.com/eko/gocache/lib/v4/marshaler"
"github.com/samber/lo"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"gorm.io/gorm"
)
func (v *App) GetUser(ctx context.Context, request *proto.GetUserRequest) (*proto.UserInfo, error) {
cacheManager := cache.New[any](localCache.S)
marshal := marshaler.New(cacheManager)
contx := context.Background()
var account models.Account
tx := database.C
hitCache := false
var err error
if request.UserId != nil {
if val, err := marshal.Get(contx, services.GetAccountCacheKey(request.GetUserId()), new(models.Account)); err == nil {
account = *val.(*models.Account)
hitCache = true
} else {
tx = tx.Where("id = ?", uint(request.GetUserId()))
}
}
if request.Name != nil {
if val, err := marshal.Get(contx, services.GetAccountCacheKey(request.GetName()), new(models.Account)); err == nil {
account = *val.(*models.Account)
hitCache = true
} else {
tx = tx.Where("name = ?", request.GetName())
}
account, err = services.GetAccountForEnd(uint(request.GetUserId()))
} else if request.Name != nil {
account, err = services.GetAccountForEnd(request.GetName())
}
if !hitCache {
if err := tx.
Preload("Profile").
Preload("Badges", func(db *gorm.DB) *gorm.DB {
return db.Order("badges.is_active DESC, badges.type DESC")
}).
First(&account).Error; err != nil {
return nil, status.Errorf(codes.NotFound, fmt.Sprintf("requested user with id %d was not found", request.GetUserId()))
}
groups, err := services.GetUserAccountGroup(account)
if err != nil {
return nil, status.Errorf(codes.Internal, fmt.Sprintf("unable to get account groups: %v", err))
}
for _, group := range groups {
for k, v := range group.PermNodes {
if _, ok := account.PermNodes[k]; !ok {
account.PermNodes[k] = v
}
}
}
punishments, err := services.ListPunishments(account)
if err != nil {
return nil, status.Errorf(codes.Internal, fmt.Sprintf("unable to get account punishments: %v", err))
}
account.Punishments = punishments
for _, punishment := range punishments {
if punishment.Type == models.PunishmentTypeLimited && len(punishment.PermNodes) > 0 {
maps.Copy(account.PermNodes, punishment.PermNodes)
}
}
services.CacheAccount(account)
if err != nil {
return nil, status.Errorf(codes.NotFound, fmt.Sprintf("unable to get account punishments: %v", err))
}
return account.EncodeToUserInfo(), nil

View File

@ -3,19 +3,18 @@ package services
import (
"context"
"fmt"
"maps"
"time"
"unicode"
"git.solsynth.dev/hypernet/nexus/pkg/nex"
"git.solsynth.dev/hypernet/nexus/pkg/nex/cachekit"
"git.solsynth.dev/hypernet/nexus/pkg/proto"
"git.solsynth.dev/hypernet/passport/pkg/authkit/models"
localCache "git.solsynth.dev/hypernet/passport/pkg/internal/cache"
"github.com/eko/gocache/lib/v4/cache"
"github.com/eko/gocache/lib/v4/marshaler"
"github.com/eko/gocache/lib/v4/store"
"git.solsynth.dev/hypernet/passport/pkg/internal/gap"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"github.com/rs/zerolog/log"
@ -26,28 +25,24 @@ import (
"github.com/samber/lo"
)
func GetAccountCacheKey(query any) string {
return fmt.Sprintf("account-query#%v", query)
func KgAccountCache(query any) string {
return fmt.Sprintf("account#%v", query)
}
func CacheAccount(account models.Account) {
cacheManager := cache.New[any](localCache.S)
marshal := marshaler.New(cacheManager)
ctx := context.Background()
_ = marshal.Set(
ctx,
GetAccountCacheKey(account.Name),
cachekit.Set[models.Account](
gap.Ca,
KgAccountCache(account.Name),
account,
store.WithExpiration(30*time.Minute),
store.WithTags([]string{"account", fmt.Sprintf("user#%d", account.ID)}),
60*time.Minute,
fmt.Sprintf("user#%d", account.ID),
)
_ = marshal.Set(
ctx,
GetAccountCacheKey(account.ID),
cachekit.Set[models.Account](
gap.Ca,
KgAccountCache(account.ID),
account,
store.WithExpiration(30*time.Minute),
store.WithTags([]string{"account", fmt.Sprintf("user#%d", account.ID)}),
60*time.Minute,
fmt.Sprintf("user#%d", account.ID),
)
}
@ -63,6 +58,58 @@ func ValidateAccountName(val string, min, max int) bool {
return actualLength >= min && max >= actualLength
}
func GetAccountForEnd(id any) (models.Account, error) {
if val, err := cachekit.Get[models.Account](gap.Ca, KgAccountCache(id)); err == nil {
return val, err
}
var account models.Account
tx := database.C
switch id.(type) {
case uint:
tx = tx.Where("id = ?", id)
case string:
tx = tx.Where("name = ?", id)
default:
return account, fmt.Errorf("invalid account id type")
}
if err := tx.
Preload("Profile").
Preload("Badges", func(db *gorm.DB) *gorm.DB {
return db.Order("badges.is_active DESC, badges.type DESC")
}).
First(&account).Error; err != nil {
return account, fmt.Errorf("requested user with id %d was not found", id)
}
groups, err := GetUserAccountGroup(account)
if err != nil {
return account, fmt.Errorf("unable to get account groups: %v", err)
}
for _, group := range groups {
for k, v := range group.PermNodes {
if _, ok := account.PermNodes[k]; !ok {
account.PermNodes[k] = v
}
}
}
punishments, err := ListPunishments(account)
if err != nil {
return account, fmt.Errorf("unable to get account punishments: %v", err)
}
account.Punishments = punishments
for _, punishment := range punishments {
if punishment.Type == models.PunishmentTypeLimited && len(punishment.PermNodes) > 0 {
maps.Copy(account.PermNodes, punishment.PermNodes)
}
}
CacheAccount(account)
return account, nil
}
func GetAccount(id uint) (models.Account, error) {
var account models.Account
if err := database.C.Where(models.Account{
@ -204,7 +251,7 @@ func ForceConfirmAccount(user models.Account) error {
return err
}
InvalidAuthCacheWithUser(user.ID)
InvalidUserAuthCache(user.ID)
return nil
}
@ -341,7 +388,7 @@ func DeleteAccount(id uint) error {
if err := tx.Commit().Error; err != nil {
return err
} else {
InvalidAuthCacheWithUser(id)
InvalidUserAuthCache(id)
conn := gap.Nx.GetNexusGrpcConn()
_, _ = proto.NewDirectoryServiceClient(conn).BroadcastEvent(context.Background(), &proto.EventInfo{
Event: "deletion",

View File

@ -1,19 +1,16 @@
package services
import (
"context"
"fmt"
"time"
"git.solsynth.dev/hypernet/nexus/pkg/nex/cachekit"
"git.solsynth.dev/hypernet/passport/pkg/authkit/models"
"git.solsynth.dev/hypernet/passport/pkg/internal/database"
"git.solsynth.dev/hypernet/passport/pkg/internal/gap"
"github.com/eko/gocache/lib/v4/cache"
"github.com/eko/gocache/lib/v4/marshaler"
"github.com/eko/gocache/lib/v4/store"
jsoniter "github.com/json-iterator/go"
localCache "git.solsynth.dev/hypernet/passport/pkg/internal/cache"
"github.com/gofiber/fiber/v2"
"github.com/rs/zerolog/log"
)
@ -33,7 +30,7 @@ func Authenticate(sessionId uint) (ctx models.AuthTicket, perms map[string]any,
return
}
func GetAuthContextCacheKey(sessionId uint) string {
func KgAuthContextCache(sessionId uint) string {
return fmt.Sprintf("auth-context#%d", sessionId)
}
@ -41,12 +38,9 @@ func GetAuthContext(sessionId uint) (models.AuthTicket, error) {
var err error
var ctx models.AuthTicket
cacheManager := cache.New[any](localCache.S)
marshal := marshaler.New(cacheManager)
key := GetAuthContextCacheKey(sessionId)
if val, err := marshal.Get(context.Background(), key, new(models.AuthTicket)); err == nil {
ctx = *val.(*models.AuthTicket)
key := KgAuthContextCache(sessionId)
if val, err := cachekit.Get[models.AuthTicket](gap.Ca, key); err == nil {
ctx = val
} else {
ctx, err = CacheAuthContext(sessionId)
if err != nil {
@ -90,27 +84,22 @@ func CacheAuthContext(sessionId uint) (models.AuthTicket, error) {
ticket.Account = user
// Put the data into the cache
cacheManager := cache.New[any](localCache.S)
marshal := marshaler.New(cacheManager)
key := GetAuthContextCacheKey(sessionId)
err = marshal.Set(
context.Background(),
key := KgAuthContextCache(sessionId)
err = cachekit.Set[models.AuthTicket](
gap.Ca,
key,
ticket,
store.WithExpiration(10*time.Minute),
store.WithTags([]string{"auth-context", fmt.Sprintf("user#%d", user.ID)}),
time.Minute*10,
"auth-context",
fmt.Sprintf("user#%d", user.ID),
)
if err != nil {
log.Error().Err(err).Msg("Unable to cache auth context...")
}
return ticket, err
}
func InvalidAuthCacheWithUser(userId uint) {
cacheManager := cache.New[any](localCache.S)
ctx := context.Background()
cacheManager.Invalidate(
ctx,
store.WithInvalidateTags([]string{"auth-context", fmt.Sprintf("user#%d", userId)}),
)
func InvalidUserAuthCache(uid uint) {
cachekit.DeleteByTags(gap.Ca, "auth-context", fmt.Sprintf("user#%d", uid))
}

View File

@ -1,17 +1,15 @@
package services
import (
"context"
"fmt"
"git.solsynth.dev/hypernet/passport/pkg/authkit/models"
"github.com/rs/zerolog/log"
"time"
localCache "git.solsynth.dev/hypernet/passport/pkg/internal/cache"
"git.solsynth.dev/hypernet/nexus/pkg/nex/cachekit"
"git.solsynth.dev/hypernet/passport/pkg/authkit/models"
"github.com/rs/zerolog/log"
"git.solsynth.dev/hypernet/passport/pkg/internal/database"
"github.com/eko/gocache/lib/v4/cache"
"github.com/eko/gocache/lib/v4/marshaler"
"github.com/eko/gocache/lib/v4/store"
"git.solsynth.dev/hypernet/passport/pkg/internal/gap"
"github.com/samber/lo"
"gorm.io/datatypes"
)
@ -41,46 +39,39 @@ func UpdateAuthPreference(account models.Account, config models.AuthConfig) (mod
return auth, err
}
func GetNotificationPreferenceCacheKey(accountId uint) string {
func KgNotifyPreferenceCache(accountId uint) string {
return fmt.Sprintf("notification-preference#%d", accountId)
}
func GetNotificationPreference(account models.Account) (models.PreferenceNotification, error) {
func GetNotifyPreference(account models.Account) (models.PreferenceNotification, error) {
var notification models.PreferenceNotification
cacheManager := cache.New[any](localCache.S)
marshal := marshaler.New(cacheManager)
ctx := context.Background()
if val, err := marshal.Get(ctx, GetNotificationPreferenceCacheKey(account.ID), new(models.PreferenceNotification)); err == nil {
notification = *val.(*models.PreferenceNotification)
} else {
if err := database.C.Where("account_id = ?", account.ID).First(&notification).Error; err != nil {
return notification, err
}
CacheNotificationPreference(notification)
if val, err := cachekit.Get[models.PreferenceNotification](
gap.Ca,
KgNotifyPreferenceCache(account.ID),
); err == nil {
return val, nil
}
if err := database.C.Where("account_id = ?", account.ID).First(&notification).Error; err != nil {
return notification, err
}
CacheNotifyPreference(notification)
return notification, nil
}
func CacheNotificationPreference(prefs models.PreferenceNotification) {
cacheManager := cache.New[any](localCache.S)
marshal := marshaler.New(cacheManager)
contx := context.Background()
_ = marshal.Set(
contx,
GetNotificationPreferenceCacheKey(prefs.AccountID),
func CacheNotifyPreference(prefs models.PreferenceNotification) {
cachekit.Set[models.PreferenceNotification](
gap.Ca,
KgNotifyPreferenceCache(prefs.AccountID),
prefs,
store.WithExpiration(60*time.Minute),
store.WithTags([]string{"notification-preference", fmt.Sprintf("user#%d", prefs.AccountID)}),
time.Minute*60,
fmt.Sprintf("user#%d", prefs.AccountID),
)
}
func UpdateNotificationPreference(account models.Account, config map[string]bool) (models.PreferenceNotification, error) {
func UpdateNotifyPreference(account models.Account, config map[string]bool) (models.PreferenceNotification, error) {
var notification models.PreferenceNotification
var err error
if notification, err = GetNotificationPreference(account); err != nil {
if notification, err = GetNotifyPreference(account); err != nil {
notification = models.PreferenceNotification{
AccountID: account.ID,
Config: lo.MapValues(config, func(v bool, k string) any { return v }),
@ -91,7 +82,7 @@ func UpdateNotificationPreference(account models.Account, config map[string]bool
err = database.C.Save(&notification).Error
if err == nil {
CacheNotificationPreference(notification)
CacheNotifyPreference(notification)
}
return notification, err
@ -99,17 +90,16 @@ func UpdateNotificationPreference(account models.Account, config map[string]bool
func CheckNotificationNotifiable(account models.Account, topic string) bool {
var notification models.PreferenceNotification
cacheManager := cache.New[any](localCache.S)
marshal := marshaler.New(cacheManager)
contx := context.Background()
if val, err := marshal.Get(contx, GetNotificationPreferenceCacheKey(account.ID), new(models.PreferenceNotification)); err == nil {
notification = val.(models.PreferenceNotification)
if val, err := cachekit.Get[models.PreferenceNotification](
gap.Ca,
KgNotifyPreferenceCache(account.ID),
); err == nil {
notification = val
} else {
if err := database.C.Where("account_id = ?", account.ID).First(&notification).Error; err != nil {
return true
}
CacheNotificationPreference(notification)
CacheNotifyPreference(notification)
}
if val, ok := notification.Config[topic]; ok {
@ -121,20 +111,15 @@ func CheckNotificationNotifiable(account models.Account, topic string) bool {
}
func CheckNotificationNotifiableBatch(accounts []models.Account, topic string) []bool {
cacheManager := cache.New[any](localCache.S)
marshal := marshaler.New(cacheManager)
ctx := context.Background()
var notifiable = make([]bool, len(accounts))
notifiable := make([]bool, len(accounts))
var queryNeededIdx []uint
notificationMap := make(map[uint]models.PreferenceNotification)
// Check cache for each account
for _, account := range accounts {
cacheKey := GetNotificationPreferenceCacheKey(account.ID)
if val, err := marshal.Get(ctx, cacheKey, new(models.PreferenceNotification)); err == nil {
notification := val.(*models.PreferenceNotification)
notificationMap[account.ID] = *notification
cacheKey := KgNotifyPreferenceCache(account.ID)
if val, err := cachekit.Get[models.PreferenceNotification](gap.Ca, cacheKey); err == nil {
notificationMap[account.ID] = val
} else {
// Add to the list of accounts that need to be queried
queryNeededIdx = append(queryNeededIdx, account.ID)
@ -154,7 +139,7 @@ func CheckNotificationNotifiableBatch(accounts []models.Account, topic string) [
// Cache the newly fetched notifications and add to the notificationMap
for _, notification := range dbNotifications {
notificationMap[notification.AccountID] = notification
CacheNotificationPreference(notification) // Cache the result
CacheNotifyPreference(notification) // Cache the result
}
}

View File

@ -5,35 +5,23 @@ import (
"fmt"
"time"
"git.solsynth.dev/hypernet/nexus/pkg/nex/cachekit"
"git.solsynth.dev/hypernet/nexus/pkg/proto"
"git.solsynth.dev/hypernet/passport/pkg/authkit/models"
localCache "git.solsynth.dev/hypernet/passport/pkg/internal/cache"
"git.solsynth.dev/hypernet/passport/pkg/internal/gap"
"git.solsynth.dev/hypernet/passport/pkg/internal/database"
"github.com/eko/gocache/lib/v4/cache"
"github.com/eko/gocache/lib/v4/marshaler"
"github.com/eko/gocache/lib/v4/store"
"github.com/samber/lo"
)
func GetStatusCacheKey(uid uint) string {
func KgStatusCache(uid uint) string {
return fmt.Sprintf("user-status#%d", uid)
}
func GetStatus(uid uint) (models.Status, error) {
cacheManager := cache.New[any](localCache.S)
marshal := marshaler.New(cacheManager)
contx := context.Background()
if val, err := marshal.Get(contx, GetStatusCacheKey(uid), new(models.Status)); err == nil {
status := val.(*models.Status)
if status.ClearAt != nil && status.ClearAt.Before(time.Now()) {
marshal.Delete(contx, GetStatusCacheKey(uid))
} else {
return *status, nil
}
if val, err := cachekit.Get[models.Status](gap.Ca, KgStatusCache(uid)); err == nil {
return val, nil
}
var status models.Status
if err := database.C.
@ -48,15 +36,12 @@ func GetStatus(uid uint) (models.Status, error) {
}
func CacheUserStatus(uid uint, status models.Status) {
cacheManager := cache.New[any](localCache.S)
marshal := marshaler.New(cacheManager)
contx := context.Background()
marshal.Set(
contx,
GetStatusCacheKey(uid),
cachekit.Set[models.Status](
gap.Ca,
KgStatusCache(uid),
status,
store.WithTags([]string{"user-status", fmt.Sprintf("user#%d", uid)}),
time.Minute*5,
fmt.Sprintf("user#%d", uid),
)
}
@ -124,11 +109,7 @@ func ClearStatus(user models.Account) error {
Updates(models.Status{ClearAt: lo.ToPtr(time.Now())}).Error; err != nil {
return err
} else {
cacheManager := cache.New[any](localCache.S)
marshal := marshaler.New(cacheManager)
contx := context.Background()
marshal.Delete(contx, GetStatusCacheKey(user.ID))
cachekit.Delete(gap.Ca, KgStatusCache(user.ID))
}
return nil

View File

@ -34,7 +34,7 @@ func editUserPermission(c *fiber.Ctx) error {
prev := user.PermNodes
user.PermNodes = data.PermNodes
services.InvalidAuthCacheWithUser(user.ID)
services.InvalidUserAuthCache(user.ID)
if err := database.C.Save(&user).Error; err != nil {
return fiber.NewError(fiber.StatusInternalServerError, err.Error())

View File

@ -172,7 +172,7 @@ func editUserinfo(c *fiber.Ctx) error {
}
services.AddEvent(user.ID, "profile.edit", nil, c.IP(), c.Get(fiber.HeaderUserAgent))
services.InvalidAuthCacheWithUser(account.ID)
services.InvalidUserAuthCache(account.ID)
return c.SendStatus(fiber.StatusOK)
}
@ -197,7 +197,7 @@ func updateAccountLanguage(c *fiber.Ctx) error {
}
services.AddEvent(user.ID, "profile.edit.language", nil, c.IP(), c.Get(fiber.HeaderUserAgent))
services.InvalidAuthCacheWithUser(user.ID)
services.InvalidUserAuthCache(user.ID)
user.Language = data.Language

View File

@ -30,7 +30,7 @@ func setAvatar(c *fiber.Ctx) error {
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
} else {
services.AddEvent(user.ID, "profile.edit.avatar", nil, c.IP(), c.Get(fiber.HeaderUserAgent))
services.InvalidAuthCacheWithUser(user.ID)
services.InvalidUserAuthCache(user.ID)
}
if og != nil && len(*og) > 0 {
@ -66,7 +66,7 @@ func setBanner(c *fiber.Ctx) error {
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
} else {
services.AddEvent(user.ID, "profile.edit.banner", nil, c.IP(), c.Get(fiber.HeaderUserAgent))
services.InvalidAuthCacheWithUser(user.ID)
services.InvalidUserAuthCache(user.ID)
}
if og != nil && len(*og) > 0 {

View File

@ -50,7 +50,7 @@ func getNotificationPreference(c *fiber.Ctx) error {
return err
}
user := c.Locals("user").(models.Account)
notification, err := services.GetNotificationPreference(user)
notification, err := services.GetNotifyPreference(user)
if err != nil {
return fiber.NewError(fiber.StatusNotFound, err.Error())
}
@ -72,7 +72,7 @@ func updateNotificationPreference(c *fiber.Ctx) error {
return err
}
notification, err := services.UpdateNotificationPreference(user, data.Config)
notification, err := services.UpdateNotifyPreference(user, data.Config)
if err != nil {
return fiber.NewError(fiber.StatusBadRequest, err.Error())
} else {

View File

@ -1,18 +1,13 @@
package api
import (
"context"
"fmt"
"strconv"
"strings"
"git.solsynth.dev/hypernet/nexus/pkg/nex/sec"
"git.solsynth.dev/hypernet/passport/pkg/authkit/models"
localCache "git.solsynth.dev/hypernet/passport/pkg/internal/cache"
"git.solsynth.dev/hypernet/passport/pkg/internal/web/exts"
"github.com/eko/gocache/lib/v4/cache"
"github.com/eko/gocache/lib/v4/marshaler"
"gorm.io/gorm"
"git.solsynth.dev/hypernet/passport/pkg/internal/database"
"git.solsynth.dev/hypernet/passport/pkg/internal/services"
@ -22,48 +17,15 @@ import (
func getOtherUserinfo(c *fiber.Ctx) error {
alias := c.Params("alias")
cacheManager := cache.New[any](localCache.S)
marshal := marshaler.New(cacheManager)
ctx := context.Background()
if val, err := marshal.Get(ctx, services.GetAccountCacheKey(alias), new(models.Account)); err == nil {
return c.JSON(*val.(*models.Account))
}
tx := database.C.Where("name = ?", alias)
var account models.Account
var err error
numericId, err := strconv.Atoi(alias)
if err == nil {
if val, err := marshal.Get(ctx, services.GetAccountCacheKey(numericId), new(models.Account)); err == nil {
return c.JSON(*val.(*models.Account))
}
tx = tx.Or("id = ?", numericId)
account, err = services.GetAccountForEnd(uint(numericId))
} else {
account, err = services.GetAccountForEnd(alias)
}
var account models.Account
if err := tx.
Preload("Profile").
Preload("Badges", func(db *gorm.DB) *gorm.DB {
return db.Order("badges.is_active DESC, badges.type DESC")
}).
First(&account).Error; err != nil {
return fiber.NewError(fiber.StatusBadRequest, err.Error())
}
groups, err := services.GetUserAccountGroup(account)
if err != nil {
return fiber.NewError(fiber.StatusInternalServerError, fmt.Sprintf("unable to get account groups: %v", err))
}
for _, group := range groups {
for k, v := range group.PermNodes {
if _, ok := account.PermNodes[k]; !ok {
account.PermNodes[k] = v
}
}
}
services.CacheAccount(account)
return c.JSON(account)
}