Compare commits

...

6 Commits

Author SHA1 Message Date
ef20829b2e 🐛 Fix did not remove user from program if they didn't pay 2025-04-02 23:15:59 +08:00
e716f5700c 🐛 Fix check punishment expires 2025-04-02 01:33:45 +08:00
b327e08062 DirectAccess in users 2025-03-29 18:04:05 +08:00
6ada023cea :arrow_up Upgrade nexus to fix panic 2025-03-29 16:00:01 +08:00
7389f70128 🛂 Clear auth context cache when logout for security 2025-03-29 15:32:20 +08:00
cc7c96311f ⬆️ Upgrade nexus 2025-03-29 15:22:53 +08:00
9 changed files with 86 additions and 22 deletions

2
go.mod
View File

@@ -3,7 +3,7 @@ module git.solsynth.dev/hypernet/passport
go 1.23.2
require (
git.solsynth.dev/hypernet/nexus v0.0.0-20250329053929-488793a2dc56
git.solsynth.dev/hypernet/nexus v0.0.0-20250330063116-4350d197f9c6
git.solsynth.dev/hypernet/paperclip v0.0.0-20250310151112-1d866f317f47
git.solsynth.dev/hypernet/pusher v0.0.0-20250216145944-5fb769823a88
git.solsynth.dev/hypernet/wallet v0.0.0-20250323095812-468cd655f886

12
go.sum
View File

@@ -1,9 +1,13 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
git.solsynth.dev/hypernet/nexus v0.0.0-20250329052546-e7d7cd1000db h1:7IXfXuV2TlZiixUkjTsgx9sPjzobEIcuSuzmUbUlIow=
git.solsynth.dev/hypernet/nexus v0.0.0-20250329052546-e7d7cd1000db/go.mod h1:5tk62VQ1DcbR0EAN2jAOqYxHiegUPEC805JlfQ/G19I=
git.solsynth.dev/hypernet/nexus v0.0.0-20250329053929-488793a2dc56 h1:SnT9NVcXQ1WDka9kKAA+lH/r2UJouND7FDugu4ZZwLc=
git.solsynth.dev/hypernet/nexus v0.0.0-20250329053929-488793a2dc56/go.mod h1:5tk62VQ1DcbR0EAN2jAOqYxHiegUPEC805JlfQ/G19I=
git.solsynth.dev/hypernet/nexus v0.0.0-20250329072130-f113ae6cbaf7 h1:0OitkUQJ3hrobm71UHETLB9N6jTgm6jKTeGRJuBI/6E=
git.solsynth.dev/hypernet/nexus v0.0.0-20250329072130-f113ae6cbaf7/go.mod h1:5tk62VQ1DcbR0EAN2jAOqYxHiegUPEC805JlfQ/G19I=
git.solsynth.dev/hypernet/nexus v0.0.0-20250329072729-4a08fd8f1c46 h1:oH2jq7ZG5cslCULUMWqv4dS/YNvd+Xcuv4rBPj0uGA8=
git.solsynth.dev/hypernet/nexus v0.0.0-20250329072729-4a08fd8f1c46/go.mod h1:5tk62VQ1DcbR0EAN2jAOqYxHiegUPEC805JlfQ/G19I=
git.solsynth.dev/hypernet/nexus v0.0.0-20250329075932-d5422ab5b04c h1:XgdTgJxSAQuCbiG15hN5pY6chzcz8sX3Onm2itS+Ufs=
git.solsynth.dev/hypernet/nexus v0.0.0-20250329075932-d5422ab5b04c/go.mod h1:5tk62VQ1DcbR0EAN2jAOqYxHiegUPEC805JlfQ/G19I=
git.solsynth.dev/hypernet/nexus v0.0.0-20250330063116-4350d197f9c6 h1:K7dYn7/rAXry3dSghFVd4aHOt2+8nTbhdav6DTW8sP8=
git.solsynth.dev/hypernet/nexus v0.0.0-20250330063116-4350d197f9c6/go.mod h1:5tk62VQ1DcbR0EAN2jAOqYxHiegUPEC805JlfQ/G19I=
git.solsynth.dev/hypernet/paperclip v0.0.0-20250310151112-1d866f317f47 h1:fvu+bNKPTNtQocssnKbEZ66MqR0iBfAxY3HwlqnmYyE=
git.solsynth.dev/hypernet/paperclip v0.0.0-20250310151112-1d866f317f47/go.mod h1:jvxq2qftz2v72x+24+cTFJdQKr9eHQTdk3KVR7cx36s=
git.solsynth.dev/hypernet/pusher v0.0.0-20250216145944-5fb769823a88 h1:2HEENe9KUrdaJeNBzx9lsuXQGyzWqCgnLTKQnr8xFr8=

View File

@@ -2,7 +2,10 @@ package authkit
import (
"context"
"time"
"git.solsynth.dev/hypernet/nexus/pkg/nex"
"git.solsynth.dev/hypernet/nexus/pkg/nex/cachekit"
"git.solsynth.dev/hypernet/nexus/pkg/nex/sec"
"git.solsynth.dev/hypernet/nexus/pkg/proto"
"git.solsynth.dev/hypernet/passport/pkg/authkit/models"
@@ -10,6 +13,14 @@ import (
)
func GetUser(nx *nex.Conn, userId uint) (models.Account, error) {
cacheConn, err := cachekit.NewConn(nx, 3*time.Second)
if err == nil {
key := cachekit.FKey(cachekit.DAAttachment, userId)
if user, err := cachekit.Get[models.Account](cacheConn, key); err == nil {
return user, nil
}
}
conn, err := nx.GetClientGrpcConn(nex.ServiceTypeAuth)
if err != nil {
return models.Account{}, err
@@ -26,6 +37,14 @@ func GetUser(nx *nex.Conn, userId uint) (models.Account, error) {
}
func GetUserByName(nx *nex.Conn, name string) (models.Account, error) {
cacheConn, err := cachekit.NewConn(nx, 3*time.Second)
if err == nil {
key := cachekit.FKey(cachekit.DAAttachment, name)
if user, err := cachekit.Get[models.Account](cacheConn, key); err == nil {
return user, nil
}
}
conn, err := nx.GetClientGrpcConn(nex.ServiceTypeAuth)
if err != nil {
return models.Account{}, err
@@ -41,24 +60,59 @@ func GetUserByName(nx *nex.Conn, name string) (models.Account, error) {
}), nil
}
func ListUser(nx *nex.Conn, userId []uint) ([]models.Account, error) {
func ListUser(nx *nex.Conn, userIds []uint) ([]models.Account, error) {
var accounts []models.Account
var missingId []uint
cachedUsers := make(map[uint]models.Account)
// Try to get users from cache
cacheConn, err := cachekit.NewConn(nx, 3*time.Second)
if err == nil {
for _, userId := range userIds {
key := cachekit.FKey(cachekit.DAAttachment, userId)
if user, err := cachekit.Get[models.Account](cacheConn, key); err == nil {
cachedUsers[userId] = user
} else {
missingId = append(missingId, userId)
}
}
}
// If all users are found in cache, return them
if len(missingId) == 0 {
for _, account := range cachedUsers {
accounts = append(accounts, account)
}
return accounts, nil
}
// Fetch missing users from the gRPC service
conn, err := nx.GetClientGrpcConn(nex.ServiceTypeAuth)
if err != nil {
return nil, err
}
raw, _ := proto.NewUserServiceClient(conn).ListUser(context.Background(), &proto.ListUserRequest{
UserId: lo.Map(userId, func(item uint, index int) uint64 {
UserId: lo.Map(missingId, func(item uint, index int) uint64 {
return uint64(item)
}),
})
var out []models.Account
// Convert fetched users and add to the result
for _, item := range raw.GetData() {
out = append(out, GetAccountFromUserInfo(&sec.UserInfo{
account := GetAccountFromUserInfo(&sec.UserInfo{
ID: uint(item.GetId()),
Name: item.GetName(),
PermNodes: nex.DecodeMap(item.GetPermNodes()),
Metadata: nex.DecodeMap(item.GetMetadata()),
}))
})
accounts = append(accounts, account)
}
return out, nil
// Merge cached and fetched results
for _, account := range cachedUsers {
accounts = append(accounts, account)
}
return accounts, nil
}

View File

@@ -22,7 +22,7 @@ var (
Nx *nex.Conn
Px *pushcon.Conn
Rx *rx.MqConn
Ca *cachekit.CaConn
Ca *cachekit.Conn
)
const (
@@ -64,7 +64,7 @@ func InitializeToNexus() error {
if err != nil {
return fmt.Errorf("error during initialize nexus rx module: %v", err)
}
Ca, err = cachekit.NewCaConn(Nx, time.Second*3)
Ca, err = cachekit.NewConn(Nx, time.Second*3)
if err != nil {
return fmt.Errorf("error during initialize nexus cache module: %v", err)
}

View File

@@ -26,7 +26,7 @@ import (
)
func KgAccountCache(query any) string {
return fmt.Sprintf("account#%v", query)
return cachekit.FKey(cachekit.DAUser, query)
}
func CacheAccount(account models.Account) {

View File

@@ -31,7 +31,7 @@ func Authenticate(sessionId uint) (ctx models.AuthTicket, perms map[string]any,
}
func KgAuthContextCache(sessionId uint) string {
return fmt.Sprintf("auth-context#%d", sessionId)
return cachekit.FKey("auth-context", sessionId)
}
func GetAuthContext(sessionId uint) (models.AuthTicket, error) {
@@ -59,7 +59,6 @@ func CacheAuthContext(sessionId uint) (models.AuthTicket, error) {
var ticket models.AuthTicket
if err := database.C.
Where("id = ?", sessionId).
Preload("Account").
First(&ticket).Error; err != nil {
return ticket, fmt.Errorf("invalid auth ticket: %v", err)
} else if err := ticket.IsAvailable(); err != nil {

View File

@@ -84,12 +84,14 @@ func PeriodicChargeProgramFee() {
var members []models.ProgramMember
// Every month paid once
if err := database.C.Where("last_paid IS NULL OR last_paid < ?", time.Now().AddDate(0, 0, -30)).
Preload("Program").Find(&members).Error; err != nil {
Preload("Program").Preload("Account").Find(&members).Error; err != nil {
return
}
for _, member := range members {
if err := ChargeForProgram(member); err == nil {
database.C.Model(&member).Update("last_paid", time.Now())
} else {
LeaveProgram(member.Account, member.Program)
}
}
}

View File

@@ -32,7 +32,7 @@ func NewPunishment(in models.Punishment, moderator ...models.Account) (models.Pu
if err := database.C.Create(&in).Error; err != nil {
return in, err
} else {
var moderator = "System"
moderator := "System"
if in.Moderator != nil {
moderator = fmt.Sprintf("@%s", in.Moderator.Name)
}
@@ -57,7 +57,7 @@ func EditPunishment(in models.Punishment) (models.Punishment, error) {
if err := database.C.Save(&in).Error; err != nil {
return in, err
} else {
var moderator = "System"
moderator := "System"
if in.Moderator != nil {
moderator = fmt.Sprintf("@%s", in.Moderator.Name)
}
@@ -81,7 +81,7 @@ func DeletePunishment(in models.Punishment) error {
if err := database.C.Delete(&in).Error; err != nil {
return err
} else {
var moderator = "System"
moderator := "System"
if in.Moderator != nil {
moderator = fmt.Sprintf("@%s", in.Moderator.Name)
}
@@ -125,7 +125,7 @@ func GetMadePunishment(id uint, moderator models.Account) (models.Punishment, er
func ListPunishments(user models.Account) ([]models.Punishment, error) {
var punishments []models.Punishment
if err := database.C.
Where("account_id = ? AND (expired_at IS NULL OR expired_at <= ?)", user.ID, time.Now()).
Where("account_id = ? AND (expired_at IS NULL OR expired_at > ?)", user.ID, time.Now()).
Preload("Moderator").
Order("created_at DESC").
Find(&punishments).Error; err != nil {
@@ -183,7 +183,7 @@ func ListMadePunishments(moderator models.Account, take, offset int) ([]models.P
func CheckLoginAbility(user models.Account) error {
var punishments []models.Punishment
if err := database.C.Where("account_id = ? AND (expired_at IS NULL OR expired_at <= ?)", user.ID, time.Now()).
if err := database.C.Where("account_id = ? AND (expired_at IS NULL OR expired_at > ?)", user.ID, time.Now()).
Find(&punishments).Error; err != nil {
return fmt.Errorf("failed to get punishments: %v", err)
}

View File

@@ -1,8 +1,11 @@
package api
import (
"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"
"git.solsynth.dev/hypernet/passport/pkg/internal/services"
"git.solsynth.dev/hypernet/passport/pkg/internal/web/exts"
"github.com/gofiber/fiber/v2"
)
@@ -51,6 +54,8 @@ func deleteTicket(c *fiber.Ctx) error {
AccountID: user.ID,
}).Error; err != nil {
return fiber.NewError(fiber.StatusNotFound, err.Error())
} else {
cachekit.Delete(gap.Ca, services.KgAuthContextCache(uint(id)))
}
return c.SendStatus(fiber.StatusOK)