diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 809da87..fb0e00c 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -4,9 +4,13 @@
-
+
-
+
+
+
+
+
@@ -159,7 +163,6 @@
-
@@ -184,7 +187,8 @@
-
+
+
diff --git a/pkg/internal/grpc/user.go b/pkg/internal/grpc/user.go
index 318639e..87beac7 100644
--- a/pkg/internal/grpc/user.go
+++ b/pkg/internal/grpc/user.go
@@ -5,25 +5,68 @@ import (
"fmt"
"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) {
- tx := database.C
- if request.UserId != nil {
- tx = tx.Where("id = ?", uint(request.GetUserId()))
- }
- if request.Name != nil {
- tx = tx.Where("name = ?", request.GetName())
- }
+ cacheManager := cache.New[any](localCache.S)
+ marshal := marshaler.New(cacheManager)
+ contx := context.Background()
var account models.Account
- if err := tx.First(&account).Error; err != nil {
- return nil, status.Errorf(codes.NotFound, fmt.Sprintf("requested user with id %d was not found", request.GetUserId()))
+
+ tx := database.C
+ hitCache := false
+ 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())
+ }
+ }
+
+ if !hitCache {
+ if err := tx.
+ Preload("Profile").
+ Preload("Badges", func(db *gorm.DB) *gorm.DB {
+ return db.Order("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
+ }
+ }
+ }
+
+ services.CacheAccount(account)
+ }
+
return account.EncodeToUserInfo(), nil
}
diff --git a/pkg/internal/http/api/accounts_api.go b/pkg/internal/http/api/accounts_api.go
index 6afea80..7dbed14 100644
--- a/pkg/internal/http/api/accounts_api.go
+++ b/pkg/internal/http/api/accounts_api.go
@@ -65,8 +65,9 @@ func getUserinfo(c *fiber.Ctx) error {
var resp fiber.Map
raw, _ := jsoniter.Marshal(data)
- jsoniter.Unmarshal(raw, &resp)
+ _ = jsoniter.Unmarshal(raw, &resp)
+ // Used to support OIDC standard
resp["sub"] = strconv.Itoa(int(data.ID))
resp["family_name"] = data.Profile.FirstName
resp["given_name"] = data.Profile.LastName
diff --git a/pkg/internal/http/api/userinfo_api.go b/pkg/internal/http/api/userinfo_api.go
index 77b28fa..ed30a07 100644
--- a/pkg/internal/http/api/userinfo_api.go
+++ b/pkg/internal/http/api/userinfo_api.go
@@ -1,8 +1,12 @@
package api
import (
+ "context"
"fmt"
"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"
"gorm.io/gorm"
"strconv"
"strings"
@@ -15,10 +19,21 @@ 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)
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)
}
@@ -44,6 +59,8 @@ func getOtherUserinfo(c *fiber.Ctx) error {
}
}
+ services.CacheAccount(account)
+
return c.JSON(account)
}
diff --git a/pkg/internal/services/accounts.go b/pkg/internal/services/accounts.go
index 0601914..6027229 100644
--- a/pkg/internal/services/accounts.go
+++ b/pkg/internal/services/accounts.go
@@ -6,6 +6,10 @@ import (
"git.solsynth.dev/hypernet/nexus/pkg/nex"
"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"
"time"
"unicode"
@@ -22,6 +26,31 @@ import (
"github.com/samber/lo"
)
+func GetAccountCacheKey(query any) string {
+ return fmt.Sprintf("account-query#%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),
+ account,
+ store.WithExpiration(30*time.Minute),
+ store.WithTags([]string{"account", fmt.Sprintf("user#%d", account.ID)}),
+ )
+ _ = marshal.Set(
+ ctx,
+ GetAccountCacheKey(account.ID),
+ account,
+ store.WithExpiration(30*time.Minute),
+ store.WithTags([]string{"account", fmt.Sprintf("user#%d", account.ID)}),
+ )
+}
+
func ValidateAccountName(val string, min, max int) bool {
actualLength := 0
for _, r := range val {
diff --git a/pkg/internal/services/preferences.go b/pkg/internal/services/preferences.go
index 4aaff95..4c5cb0b 100644
--- a/pkg/internal/services/preferences.go
+++ b/pkg/internal/services/preferences.go
@@ -49,10 +49,10 @@ func GetNotificationPreference(account models.Account) (models.PreferenceNotific
var notification models.PreferenceNotification
cacheManager := cache.New[any](localCache.S)
marshal := marshaler.New(cacheManager)
- contx := context.Background()
+ ctx := context.Background()
- if val, err := marshal.Get(contx, GetNotificationPreferenceCacheKey(account.ID), new(models.PreferenceNotification)); err == nil {
- notification = val.(models.PreferenceNotification)
+ 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(¬ification).Error; err != nil {
return notification, err