✨ Friends api
This commit is contained in:
parent
0b436c0a1e
commit
6850f64fe3
@ -68,6 +68,7 @@ func main() {
|
|||||||
quartz := cron.New(cron.WithLogger(cron.VerbosePrintfLogger(&log.Logger)))
|
quartz := cron.New(cron.WithLogger(cron.VerbosePrintfLogger(&log.Logger)))
|
||||||
quartz.AddFunc("@every 60m", services.DoAutoSignoff)
|
quartz.AddFunc("@every 60m", services.DoAutoSignoff)
|
||||||
quartz.AddFunc("@every 60m", services.DoAutoAuthCleanup)
|
quartz.AddFunc("@every 60m", services.DoAutoAuthCleanup)
|
||||||
|
quartz.AddFunc("@every 60m", services.DoAutoDatabaseCleanup)
|
||||||
quartz.Run()
|
quartz.Run()
|
||||||
|
|
||||||
// Messages
|
// Messages
|
||||||
|
@ -5,13 +5,13 @@ import (
|
|||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
func RunMigration(source *gorm.DB) error {
|
var DatabaseAutoActionRange = []any{
|
||||||
if err := source.AutoMigrate(
|
|
||||||
&models.Account{},
|
&models.Account{},
|
||||||
&models.AuthFactor{},
|
&models.AuthFactor{},
|
||||||
&models.AccountProfile{},
|
&models.AccountProfile{},
|
||||||
&models.AccountPage{},
|
&models.AccountPage{},
|
||||||
&models.AccountContact{},
|
&models.AccountContact{},
|
||||||
|
&models.AccountFriendship{},
|
||||||
&models.AuthSession{},
|
&models.AuthSession{},
|
||||||
&models.AuthChallenge{},
|
&models.AuthChallenge{},
|
||||||
&models.MagicToken{},
|
&models.MagicToken{},
|
||||||
@ -19,7 +19,10 @@ func RunMigration(source *gorm.DB) error {
|
|||||||
&models.ActionEvent{},
|
&models.ActionEvent{},
|
||||||
&models.Notification{},
|
&models.Notification{},
|
||||||
&models.NotificationSubscriber{},
|
&models.NotificationSubscriber{},
|
||||||
); err != nil {
|
}
|
||||||
|
|
||||||
|
func RunMigration(source *gorm.DB) error {
|
||||||
|
if err := source.AutoMigrate(DatabaseAutoActionRange...); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
46
pkg/grpc/friendships.go
Normal file
46
pkg/grpc/friendships.go
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package grpc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"git.solsynth.dev/hydrogen/identity/pkg/grpc/proto"
|
||||||
|
"git.solsynth.dev/hydrogen/identity/pkg/models"
|
||||||
|
"git.solsynth.dev/hydrogen/identity/pkg/services"
|
||||||
|
"github.com/samber/lo"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (v *Server) ListFriendship(_ context.Context, request *proto.FriendshipLookupRequest) (*proto.ListFriendshipResponse, error) {
|
||||||
|
account, err := services.GetAccount(uint(request.GetAccountId()))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
friends, err := services.ListFriend(account, models.FriendshipStatus(request.GetStatus()))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &proto.ListFriendshipResponse{
|
||||||
|
Data: lo.Map(friends, func(item models.AccountFriendship, index int) *proto.FriendshipResponse {
|
||||||
|
return &proto.FriendshipResponse{
|
||||||
|
AccountId: uint64(item.AccountID),
|
||||||
|
RelatedId: uint64(item.RelatedID),
|
||||||
|
Status: uint32(item.Status),
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Server) GetFriendship(ctx context.Context, request *proto.FriendshipTwoSideLookupRequest) (*proto.FriendshipResponse, error) {
|
||||||
|
friend, err := services.GetFriendWithTwoSides(uint(request.GetAccountId()), uint(request.GetRelatedId()))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else if friend.Status != models.FriendshipStatus(request.GetStatus()) {
|
||||||
|
return nil, fmt.Errorf("status mismatch")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &proto.FriendshipResponse{
|
||||||
|
AccountId: uint64(friend.AccountID),
|
||||||
|
RelatedId: uint64(friend.RelatedID),
|
||||||
|
Status: uint32(friend.Status),
|
||||||
|
}, nil
|
||||||
|
}
|
31
pkg/grpc/proto/friendships.proto
Normal file
31
pkg/grpc/proto/friendships.proto
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
option go_package = ".;proto";
|
||||||
|
|
||||||
|
package proto;
|
||||||
|
|
||||||
|
service Friendships {
|
||||||
|
rpc ListFriendship(FriendshipLookupRequest) returns (ListFriendshipResponse) {}
|
||||||
|
rpc GetFriendship(FriendshipTwoSideLookupRequest) returns (FriendshipResponse) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
message FriendshipLookupRequest {
|
||||||
|
uint64 account_id = 1;
|
||||||
|
uint32 status = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message FriendshipTwoSideLookupRequest {
|
||||||
|
uint64 account_id = 1;
|
||||||
|
uint64 related_id = 2;
|
||||||
|
uint32 status = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ListFriendshipResponse {
|
||||||
|
repeated FriendshipResponse data = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message FriendshipResponse {
|
||||||
|
uint64 account_id = 1;
|
||||||
|
uint64 related_id = 2;
|
||||||
|
uint32 status = 3;
|
||||||
|
}
|
@ -12,6 +12,7 @@ import (
|
|||||||
type Server struct {
|
type Server struct {
|
||||||
proto.UnimplementedAuthServer
|
proto.UnimplementedAuthServer
|
||||||
proto.UnimplementedNotifyServer
|
proto.UnimplementedNotifyServer
|
||||||
|
proto.UnimplementedFriendshipsServer
|
||||||
}
|
}
|
||||||
|
|
||||||
func StartGrpc() error {
|
func StartGrpc() error {
|
||||||
@ -24,6 +25,7 @@ func StartGrpc() error {
|
|||||||
|
|
||||||
proto.RegisterAuthServer(server, &Server{})
|
proto.RegisterAuthServer(server, &Server{})
|
||||||
proto.RegisterNotifyServer(server, &Server{})
|
proto.RegisterNotifyServer(server, &Server{})
|
||||||
|
proto.RegisterFriendshipsServer(server, &Server{})
|
||||||
|
|
||||||
reflection.Register(server)
|
reflection.Register(server)
|
||||||
|
|
||||||
|
@ -16,19 +16,27 @@ type Account struct {
|
|||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
Avatar string `json:"avatar"`
|
Avatar string `json:"avatar"`
|
||||||
Banner string `json:"banner"`
|
Banner string `json:"banner"`
|
||||||
|
ConfirmedAt *time.Time `json:"confirmed_at"`
|
||||||
|
PowerLevel int `json:"power_level"`
|
||||||
|
|
||||||
Profile AccountProfile `json:"profile"`
|
Profile AccountProfile `json:"profile"`
|
||||||
PersonalPage AccountPage `json:"personal_page"`
|
PersonalPage AccountPage `json:"personal_page"`
|
||||||
|
Contacts []AccountContact `json:"contacts"`
|
||||||
|
|
||||||
Sessions []AuthSession `json:"sessions"`
|
Sessions []AuthSession `json:"sessions"`
|
||||||
Challenges []AuthChallenge `json:"challenges"`
|
Challenges []AuthChallenge `json:"challenges"`
|
||||||
Factors []AuthFactor `json:"factors"`
|
Factors []AuthFactor `json:"factors"`
|
||||||
Contacts []AccountContact `json:"contacts"`
|
|
||||||
Events []ActionEvent `json:"events"`
|
Events []ActionEvent `json:"events"`
|
||||||
MagicTokens []MagicToken `json:"-" gorm:"foreignKey:AssignTo"`
|
MagicTokens []MagicToken `json:"-" gorm:"foreignKey:AssignTo"`
|
||||||
|
|
||||||
ThirdClients []ThirdClient `json:"clients"`
|
ThirdClients []ThirdClient `json:"clients"`
|
||||||
|
|
||||||
Notifications []Notification `json:"notifications" gorm:"foreignKey:RecipientID"`
|
Notifications []Notification `json:"notifications" gorm:"foreignKey:RecipientID"`
|
||||||
NotifySubscribers []NotificationSubscriber `json:"notify_subscribers"`
|
NotifySubscribers []NotificationSubscriber `json:"notify_subscribers"`
|
||||||
ConfirmedAt *time.Time `json:"confirmed_at"`
|
|
||||||
PowerLevel int `json:"power_level"`
|
Friendships []AccountFriendship `json:"friendships" gorm:"foreignKey:AccountID"`
|
||||||
|
RelatedFriendships []AccountFriendship `json:"related_friendships" gorm:"foreignKey:RelatedID"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v Account) GetPrimaryEmail() AccountContact {
|
func (v Account) GetPrimaryEmail() AccountContact {
|
||||||
@ -64,3 +72,21 @@ type AccountContact struct {
|
|||||||
VerifiedAt *time.Time `json:"verified_at"`
|
VerifiedAt *time.Time `json:"verified_at"`
|
||||||
AccountID uint `json:"account_id"`
|
AccountID uint `json:"account_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type FriendshipStatus = int8
|
||||||
|
|
||||||
|
const (
|
||||||
|
FriendshipPending = FriendshipStatus(iota)
|
||||||
|
FriendshipActive
|
||||||
|
FriendshipBlocked
|
||||||
|
)
|
||||||
|
|
||||||
|
type AccountFriendship struct {
|
||||||
|
BaseModel
|
||||||
|
|
||||||
|
AccountID uint `json:"account_id"`
|
||||||
|
RelatedID uint `json:"related_id"`
|
||||||
|
Account Account `json:"account"`
|
||||||
|
Related Account `json:"related"`
|
||||||
|
Status FriendshipStatus `json:"status"`
|
||||||
|
}
|
||||||
|
103
pkg/server/friendships_api.go
Normal file
103
pkg/server/friendships_api.go
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.solsynth.dev/hydrogen/identity/pkg/models"
|
||||||
|
"git.solsynth.dev/hydrogen/identity/pkg/services"
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func listFriendship(c *fiber.Ctx) error {
|
||||||
|
user := c.Locals("principal").(models.Account)
|
||||||
|
status := c.QueryInt("status", int(models.FriendshipActive))
|
||||||
|
|
||||||
|
if friends, err := services.ListFriend(user, models.FriendshipStatus(status)); err != nil {
|
||||||
|
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||||
|
} else {
|
||||||
|
return c.JSON(friends)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getFriendship(c *fiber.Ctx) error {
|
||||||
|
user := c.Locals("principal").(models.Account)
|
||||||
|
relatedId, _ := c.ParamsInt("relatedId", 0)
|
||||||
|
|
||||||
|
related, err := services.GetAccount(uint(relatedId))
|
||||||
|
if err != nil {
|
||||||
|
return fiber.NewError(fiber.StatusNotFound, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
if friend, err := services.GetFriendWithTwoSides(user.ID, related.ID); err != nil {
|
||||||
|
return fiber.NewError(fiber.StatusNotFound, err.Error())
|
||||||
|
} else {
|
||||||
|
return c.JSON(friend)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeFriendship(c *fiber.Ctx) error {
|
||||||
|
user := c.Locals("principal").(models.Account)
|
||||||
|
relatedId, _ := c.ParamsInt("relatedId", 0)
|
||||||
|
|
||||||
|
related, err := services.GetAccount(uint(relatedId))
|
||||||
|
if err != nil {
|
||||||
|
return fiber.NewError(fiber.StatusNotFound, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
friend, err := services.NewFriend(user, related, models.FriendshipPending)
|
||||||
|
if err != nil {
|
||||||
|
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||||
|
} else {
|
||||||
|
return c.JSON(friend)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func editFriendship(c *fiber.Ctx) error {
|
||||||
|
user := c.Locals("principal").(models.Account)
|
||||||
|
relatedId, _ := c.ParamsInt("relatedId", 0)
|
||||||
|
|
||||||
|
var data struct {
|
||||||
|
Status uint8 `json:"status"`
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := BindAndValidate(c, &data); err != nil {
|
||||||
|
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
related, err := services.GetAccount(uint(relatedId))
|
||||||
|
if err != nil {
|
||||||
|
return fiber.NewError(fiber.StatusNotFound, err.Error())
|
||||||
|
}
|
||||||
|
friendship, err := services.GetFriendWithTwoSides(user.ID, related.ID)
|
||||||
|
if err != nil {
|
||||||
|
return fiber.NewError(fiber.StatusNotFound, err.Error())
|
||||||
|
} else if friendship.Status == models.FriendshipPending || data.Status == uint8(models.FriendshipPending) {
|
||||||
|
if friendship.RelatedID != user.ID {
|
||||||
|
return fiber.NewError(fiber.StatusNotFound, "only related person can accept or revoke accept friendship")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if friendship, err := services.EditFriend(friendship); err != nil {
|
||||||
|
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||||
|
} else {
|
||||||
|
return c.JSON(friendship)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteFriendship(c *fiber.Ctx) error {
|
||||||
|
user := c.Locals("principal").(models.Account)
|
||||||
|
relatedId, _ := c.ParamsInt("relatedId", 0)
|
||||||
|
|
||||||
|
related, err := services.GetAccount(uint(relatedId))
|
||||||
|
if err != nil {
|
||||||
|
return fiber.NewError(fiber.StatusNotFound, err.Error())
|
||||||
|
}
|
||||||
|
friendship, err := services.GetFriendWithTwoSides(user.ID, related.ID)
|
||||||
|
if err != nil {
|
||||||
|
return fiber.NewError(fiber.StatusNotFound, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := services.DeleteFriend(friendship); err != nil {
|
||||||
|
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||||
|
} else {
|
||||||
|
return c.JSON(friendship)
|
||||||
|
}
|
||||||
|
}
|
@ -86,6 +86,15 @@ func NewServer() {
|
|||||||
me.Delete("/sessions/:sessionId", authMiddleware, killSession)
|
me.Delete("/sessions/:sessionId", authMiddleware, killSession)
|
||||||
|
|
||||||
me.Post("/confirm", doRegisterConfirm)
|
me.Post("/confirm", doRegisterConfirm)
|
||||||
|
|
||||||
|
friends := me.Group("/friends").Name("Friends")
|
||||||
|
{
|
||||||
|
friends.Get("/", authMiddleware, listFriendship)
|
||||||
|
friends.Get("/:relatedId", authMiddleware, getFriendship)
|
||||||
|
friends.Post("/:relatedId", authMiddleware, makeFriendship)
|
||||||
|
friends.Put("/:relatedId", authMiddleware, editFriendship)
|
||||||
|
friends.Delete("/:relatedId", authMiddleware, deleteFriendship)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
directory := api.Group("/users/:alias").Name("User Directory")
|
directory := api.Group("/users/:alias").Name("User Directory")
|
||||||
|
@ -13,6 +13,7 @@ func getOtherUserinfo(c *fiber.Ctx) error {
|
|||||||
if err := database.C.
|
if err := database.C.
|
||||||
Where(&models.Account{Name: alias}).
|
Where(&models.Account{Name: alias}).
|
||||||
Omit("sessions", "challenges", "factors", "events", "clients", "notifications", "notify_subscribers").
|
Omit("sessions", "challenges", "factors", "events", "clients", "notifications", "notify_subscribers").
|
||||||
|
Preload("Profile").
|
||||||
First(&account).Error; err != nil {
|
First(&account).Error; err != nil {
|
||||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||||
}
|
}
|
||||||
|
23
pkg/services/cleaner.go
Normal file
23
pkg/services/cleaner.go
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package services
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.solsynth.dev/hydrogen/identity/pkg/database"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func DoAutoDatabaseCleanup() {
|
||||||
|
deadline := time.Now().Add(60 * time.Minute)
|
||||||
|
log.Debug().Time("deadline", deadline).Msg("Now cleaning up entire database...")
|
||||||
|
|
||||||
|
var count int64
|
||||||
|
for _, model := range database.DatabaseAutoActionRange {
|
||||||
|
tx := database.C.Unscoped().Delete(model, "deleted_at >= ?", deadline)
|
||||||
|
if tx.Error != nil {
|
||||||
|
log.Error().Err(tx.Error).Msg("An error occurred when running auth context cleanup...")
|
||||||
|
}
|
||||||
|
count += tx.RowsAffected
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debug().Int64("affected", count).Msg("Clean up entire database accomplished.")
|
||||||
|
}
|
89
pkg/services/friendships.go
Normal file
89
pkg/services/friendships.go
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
package services
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"git.solsynth.dev/hydrogen/identity/pkg/database"
|
||||||
|
"git.solsynth.dev/hydrogen/identity/pkg/models"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ListFriend(anyside models.Account, status models.FriendshipStatus) ([]models.AccountFriendship, error) {
|
||||||
|
var relationships []models.AccountFriendship
|
||||||
|
if err := database.C.
|
||||||
|
Where(&models.AccountFriendship{Status: status}).
|
||||||
|
Where(&models.AccountFriendship{AccountID: anyside.ID}).
|
||||||
|
Or(&models.AccountFriendship{RelatedID: anyside.ID}).
|
||||||
|
Find(&relationships).Error; err != nil {
|
||||||
|
return relationships, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return relationships, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetFriend(anysideId uint) (models.AccountFriendship, error) {
|
||||||
|
var relationship models.AccountFriendship
|
||||||
|
if err := database.C.
|
||||||
|
Where(&models.AccountFriendship{AccountID: anysideId}).
|
||||||
|
Or(&models.AccountFriendship{RelatedID: anysideId}).
|
||||||
|
Preload("Account").
|
||||||
|
Preload("Related").
|
||||||
|
First(&relationship).Error; err != nil {
|
||||||
|
return relationship, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return relationship, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetFriendWithTwoSides(userId, relatedId uint, noPreload ...bool) (models.AccountFriendship, error) {
|
||||||
|
var tx *gorm.DB
|
||||||
|
if len(noPreload) > 0 && noPreload[0] {
|
||||||
|
tx = database.C
|
||||||
|
} else {
|
||||||
|
tx = database.C.Preload("Account").Preload("Related")
|
||||||
|
}
|
||||||
|
|
||||||
|
var relationship models.AccountFriendship
|
||||||
|
if err := tx.
|
||||||
|
Where(&models.AccountFriendship{AccountID: userId, RelatedID: relatedId}).
|
||||||
|
Or(&models.AccountFriendship{RelatedID: userId, AccountID: relatedId}).
|
||||||
|
First(&relationship).Error; err != nil {
|
||||||
|
return relationship, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return relationship, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFriend(user models.Account, related models.Account, status models.FriendshipStatus) (models.AccountFriendship, error) {
|
||||||
|
relationship := models.AccountFriendship{
|
||||||
|
AccountID: user.ID,
|
||||||
|
RelatedID: related.ID,
|
||||||
|
Status: status,
|
||||||
|
}
|
||||||
|
|
||||||
|
if user.ID == related.ID {
|
||||||
|
return relationship, fmt.Errorf("you cannot make friendship with yourself")
|
||||||
|
} else if _, err := GetFriendWithTwoSides(user.ID, related.ID, true); err == nil || !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
|
return relationship, fmt.Errorf("you already have a friendship with him or her")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := database.C.Save(&relationship).Error; err != nil {
|
||||||
|
return relationship, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return relationship, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func EditFriend(relationship models.AccountFriendship) (models.AccountFriendship, error) {
|
||||||
|
if err := database.C.Save(&relationship).Error; err != nil {
|
||||||
|
return relationship, err
|
||||||
|
}
|
||||||
|
return relationship, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeleteFriend(relationship models.AccountFriendship) error {
|
||||||
|
if err := database.C.Delete(&relationship).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
@ -27,7 +27,7 @@ func DoAutoSignoff() {
|
|||||||
duration := time.Duration(viper.GetInt64("security.auto_signoff_duration")) * time.Second
|
duration := time.Duration(viper.GetInt64("security.auto_signoff_duration")) * time.Second
|
||||||
divider := time.Now().Add(-duration)
|
divider := time.Now().Add(-duration)
|
||||||
|
|
||||||
log.Debug().Time("before", divider).Msg("Now auto signing off sessions...")
|
log.Debug().Time("before", divider).Msg("Now signing off sessions...")
|
||||||
|
|
||||||
if tx := database.C.
|
if tx := database.C.
|
||||||
Where("last_grant_at < ?", divider).
|
Where("last_grant_at < ?", divider).
|
||||||
@ -39,7 +39,7 @@ func DoAutoSignoff() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func DoAutoAuthCleanup() {
|
func DoAutoAuthCleanup() {
|
||||||
log.Debug().Msg("Now auto cleaning up cached auth context...")
|
log.Debug().Msg("Now cleaning up cached auth context...")
|
||||||
|
|
||||||
count := 0
|
count := 0
|
||||||
err := database.B.Batch(func(tx *bbolt.Tx) error {
|
err := database.B.Batch(func(tx *bbolt.Tx) error {
|
||||||
|
Loading…
Reference in New Issue
Block a user