♻️ Use the new dealer BaseUser and remove ExternalID

This commit is contained in:
LittleSheep 2024-09-11 23:42:46 +08:00
parent aab0724653
commit a131a5bf86
20 changed files with 65 additions and 163 deletions

2
go.mod
View File

@ -3,7 +3,7 @@ module git.solsynth.dev/hydrogen/interactive
go 1.21.6
require (
git.solsynth.dev/hydrogen/dealer v0.0.0-20240823113302-208da7e90fdb
git.solsynth.dev/hydrogen/dealer v0.0.0-20240911145828-d734d617bfc8
github.com/go-playground/validator/v10 v10.17.0
github.com/gofiber/fiber/v2 v2.52.4
github.com/json-iterator/go v1.1.12

2
go.sum
View File

@ -1,5 +1,7 @@
git.solsynth.dev/hydrogen/dealer v0.0.0-20240823113302-208da7e90fdb h1:dv4uVDMe53eBprW2Q8ocAhZuO+DKWlWyxGiJMiwE62E=
git.solsynth.dev/hydrogen/dealer v0.0.0-20240823113302-208da7e90fdb/go.mod h1:Q51JPkKnV0UoOT/IRmdBh5CyfSlp7s8BRGzgooYHqkI=
git.solsynth.dev/hydrogen/dealer v0.0.0-20240911145828-d734d617bfc8 h1:kWheneSdSySG5tz9TAXrtr546JdMpQZTyWDFk4jeGwg=
git.solsynth.dev/hydrogen/dealer v0.0.0-20240911145828-d734d617bfc8/go.mod h1:Q51JPkKnV0UoOT/IRmdBh5CyfSlp7s8BRGzgooYHqkI=
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=

View File

@ -1,21 +1,12 @@
package models
// Account profiles basically fetched from Hydrogen.Passport
// But cache at here for better usage
// At the same time this model can make relations between local models
type Account struct {
BaseModel
import "git.solsynth.dev/hydrogen/dealer/pkg/hyper"
type Account struct {
hyper.BaseUser
Name string `json:"name"`
Nick string `json:"nick"`
Avatar string `json:"avatar"`
Banner string `json:"banner"`
Description string `json:"description"`
EmailAddress string `json:"email_address"`
PowerLevel int `json:"power_level"`
Posts []Post `json:"posts" gorm:"foreignKey:AuthorID"`
Reactions []Reaction `json:"reactions"`
ExternalID uint `json:"external_id"`
TotalUpvote int `json:"total_upvote"`
TotalDownvote int `json:"total_downvote"`

View File

@ -1,17 +0,0 @@
package models
import (
"time"
"gorm.io/datatypes"
"gorm.io/gorm"
)
type JSONMap = datatypes.JSONType[map[string]any]
type BaseModel struct {
ID uint `json:"id" gorm:"primaryKey"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `json:"deleted_at" gorm:"index"`
}

View File

@ -1,7 +1,9 @@
package models
import "git.solsynth.dev/hydrogen/dealer/pkg/hyper"
type Tag struct {
BaseModel
hyper.BaseModel
Alias string `json:"alias" gorm:"uniqueIndex" validate:"lowercase"`
Name string `json:"name"`
@ -10,7 +12,7 @@ type Tag struct {
}
type Category struct {
BaseModel
hyper.BaseModel
Alias string `json:"alias" gorm:"uniqueIndex" validate:"lowercase,alphanum"`
Name string `json:"name"`

View File

@ -3,6 +3,7 @@ package models
import (
"time"
"git.solsynth.dev/hydrogen/dealer/pkg/hyper"
"gorm.io/datatypes"
)
@ -22,7 +23,7 @@ const (
)
type Post struct {
BaseModel
hyper.BaseModel
Type string `json:"type"`
Body datatypes.JSONMap `json:"body"`

View File

@ -1,15 +1,9 @@
package models
// Realm profiles basically fetched from Hydrogen.Passport
// But cache at here for better usage and database relations
type Realm struct {
BaseModel
import "git.solsynth.dev/hydrogen/dealer/pkg/hyper"
type Realm struct {
hyper.BaseRealm
Alias string `json:"alias"`
Name string `json:"name"`
Description string `json:"description"`
Posts []Post `json:"posts"`
IsPublic bool `json:"is_public"`
IsCommunity bool `json:"is_community"`
ExternalID uint `json:"external_id"`
}

View File

@ -4,6 +4,7 @@ import (
"fmt"
"time"
"git.solsynth.dev/hydrogen/dealer/pkg/hyper"
"git.solsynth.dev/hydrogen/interactive/pkg/internal/database"
"git.solsynth.dev/hydrogen/interactive/pkg/internal/gap"
"git.solsynth.dev/hydrogen/interactive/pkg/internal/models"
@ -82,7 +83,7 @@ func createArticle(c *fiber.Ctx) error {
if data.RealmAlias != nil {
if realm, err := services.GetRealmWithAlias(*data.RealmAlias); err != nil {
return fiber.NewError(fiber.StatusBadRequest, err.Error())
} else if _, err = services.GetRealmMember(realm.ExternalID, user.ExternalID); err != nil {
} else if _, err = services.GetRealmMember(realm.ID, user.ID); err != nil {
return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("unable to post in the realm, access denied: %v", err))
} else {
item.RealmID = &realm.ID
@ -129,7 +130,7 @@ func editArticle(c *fiber.Ctx) error {
var item models.Post
if err := database.C.Where(models.Post{
BaseModel: models.BaseModel{ID: uint(id)},
BaseModel: hyper.BaseModel{ID: uint(id)},
AuthorID: user.ID,
}).First(&item).Error; err != nil {
return fiber.NewError(fiber.StatusNotFound, err.Error())
@ -179,7 +180,7 @@ func editArticle(c *fiber.Ctx) error {
if data.RealmAlias != nil {
if realm, err := services.GetRealmWithAlias(*data.RealmAlias); err != nil {
return fiber.NewError(fiber.StatusBadRequest, err.Error())
} else if _, err = services.GetRealmMember(realm.ExternalID, user.ExternalID); err != nil {
} else if _, err = services.GetRealmMember(realm.ID, user.ID); err != nil {
return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("unable to post in the realm, access denied: %v", err))
} else {
item.RealmID = &realm.ID

View File

@ -2,7 +2,6 @@ package api
import (
"git.solsynth.dev/hydrogen/interactive/pkg/internal/gap"
"git.solsynth.dev/hydrogen/interactive/pkg/internal/models"
"git.solsynth.dev/hydrogen/interactive/pkg/internal/server/exts"
"git.solsynth.dev/hydrogen/interactive/pkg/internal/services"
"github.com/gofiber/fiber/v2"
@ -29,13 +28,9 @@ func listCategories(c *fiber.Ctx) error {
}
func newCategory(c *fiber.Ctx) error {
if err := gap.H.EnsureAuthenticated(c); err != nil {
if err := gap.H.EnsureGrantedPerm(c, "CreatePostCategories", true); err != nil {
return err
}
user := c.Locals("user").(models.Account)
if user.PowerLevel <= 55 {
return fiber.NewError(fiber.StatusForbidden, "require power level 55 to create categories")
}
var data struct {
Alias string `json:"alias" validate:"required"`
@ -56,13 +51,9 @@ func newCategory(c *fiber.Ctx) error {
}
func editCategory(c *fiber.Ctx) error {
if err := gap.H.EnsureAuthenticated(c); err != nil {
if err := gap.H.EnsureGrantedPerm(c, "CreatePostCategories", true); err != nil {
return err
}
user := c.Locals("user").(models.Account)
if user.PowerLevel <= 55 {
return fiber.NewError(fiber.StatusForbidden, "require power level 55 to edit categories")
}
id, _ := c.ParamsInt("categoryId", 0)
category, err := services.GetCategoryWithID(uint(id))
@ -89,13 +80,9 @@ func editCategory(c *fiber.Ctx) error {
}
func deleteCategory(c *fiber.Ctx) error {
if err := gap.H.EnsureAuthenticated(c); err != nil {
if err := gap.H.EnsureGrantedPerm(c, "CreatePostCategories", true); err != nil {
return err
}
user := c.Locals("user").(models.Account)
if user.PowerLevel <= 55 {
return fiber.NewError(fiber.StatusForbidden, "require power level 55 to delete categories")
}
id, _ := c.ParamsInt("categoryId", 0)
category, err := services.GetCategoryWithID(uint(id))

View File

@ -5,6 +5,7 @@ import (
"strconv"
"strings"
"git.solsynth.dev/hydrogen/dealer/pkg/hyper"
"git.solsynth.dev/hydrogen/interactive/pkg/internal/database"
"git.solsynth.dev/hydrogen/interactive/pkg/internal/gap"
"git.solsynth.dev/hydrogen/interactive/pkg/internal/models"
@ -72,7 +73,7 @@ func listPost(c *fiber.Ctx) error {
if len(c.Query("author")) > 0 {
var author models.Account
if err := database.C.Where(&models.Account{Name: c.Query("author")}).First(&author).Error; err != nil {
if err := database.C.Where(&hyper.BaseUser{Name: c.Query("author")}).First(&author).Error; err != nil {
return fiber.NewError(fiber.StatusNotFound, err.Error())
}
tx = tx.Where("author_id = ?", author.ID)
@ -125,7 +126,7 @@ func listPostMinimal(c *fiber.Ctx) error {
if len(c.Query("author")) > 0 {
var author models.Account
if err := database.C.Where(&models.Account{Name: c.Query("author")}).First(&author).Error; err != nil {
if err := database.C.Where(&hyper.BaseUser{Name: c.Query("author")}).First(&author).Error; err != nil {
return fiber.NewError(fiber.StatusNotFound, err.Error())
}
tx = tx.Where("author_id = ?", author.ID)
@ -191,7 +192,7 @@ func deletePost(c *fiber.Ctx) error {
var item models.Post
if err := database.C.Where(models.Post{
BaseModel: models.BaseModel{ID: uint(id)},
BaseModel: hyper.BaseModel{ID: uint(id)},
AuthorID: user.ID,
}).First(&item).Error; err != nil {
return fiber.NewError(fiber.StatusNotFound, err.Error())

View File

@ -3,6 +3,7 @@ package api
import (
"fmt"
"git.solsynth.dev/hydrogen/dealer/pkg/hyper"
"git.solsynth.dev/hydrogen/interactive/pkg/internal/database"
"git.solsynth.dev/hydrogen/interactive/pkg/internal/models"
"git.solsynth.dev/hydrogen/interactive/pkg/internal/services"
@ -23,7 +24,7 @@ func listPostReplies(c *fiber.Ctx) error {
if len(c.Query("author")) > 0 {
var author models.Account
if err := database.C.Where(&models.Account{Name: c.Query("author")}).First(&author).Error; err != nil {
if err := database.C.Where(&hyper.BaseUser{Name: c.Query("author")}).First(&author).Error; err != nil {
return fiber.NewError(fiber.StatusNotFound, err.Error())
}
tx = tx.Where("author_id = ?", author.ID)

View File

@ -4,6 +4,7 @@ import (
"fmt"
"time"
"git.solsynth.dev/hydrogen/dealer/pkg/hyper"
"git.solsynth.dev/hydrogen/interactive/pkg/internal/database"
"git.solsynth.dev/hydrogen/interactive/pkg/internal/gap"
"git.solsynth.dev/hydrogen/interactive/pkg/internal/models"
@ -101,7 +102,7 @@ func createStory(c *fiber.Ctx) error {
if data.RealmAlias != nil {
if realm, err := services.GetRealmWithAlias(*data.RealmAlias); err != nil {
return fiber.NewError(fiber.StatusBadRequest, err.Error())
} else if _, err = services.GetRealmMember(realm.ExternalID, user.ExternalID); err != nil {
} else if _, err = services.GetRealmMember(realm.ID, user.ID); err != nil {
return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("unable to post in the realm, access denied: %v", err))
} else {
item.RealmID = &realm.ID
@ -148,7 +149,7 @@ func editStory(c *fiber.Ctx) error {
var item models.Post
if err := database.C.Where(models.Post{
BaseModel: models.BaseModel{ID: uint(id)},
BaseModel: hyper.BaseModel{ID: uint(id)},
AuthorID: user.ID,
}).First(&item).Error; err != nil {
return fiber.NewError(fiber.StatusNotFound, err.Error())
@ -198,7 +199,7 @@ func editStory(c *fiber.Ctx) error {
if data.RealmAlias != nil {
if realm, err := services.GetRealmWithAlias(*data.RealmAlias); err != nil {
return fiber.NewError(fiber.StatusBadRequest, err.Error())
} else if _, err = services.GetRealmMember(realm.ExternalID, user.ExternalID); err != nil {
} else if _, err = services.GetRealmMember(realm.ID, user.ID); err != nil {
return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("unable to post in the realm, access denied: %v", err))
} else {
item.RealmID = &realm.ID

View File

@ -1,6 +1,7 @@
package api
import (
"git.solsynth.dev/hydrogen/dealer/pkg/hyper"
"git.solsynth.dev/hydrogen/interactive/pkg/internal/database"
"git.solsynth.dev/hydrogen/interactive/pkg/internal/gap"
"git.solsynth.dev/hydrogen/interactive/pkg/internal/models"
@ -16,7 +17,7 @@ func getUserinfo(c *fiber.Ctx) error {
var data models.Account
if err := database.C.
Where(&models.Account{BaseModel: models.BaseModel{ID: user.ID}}).
Where(&hyper.BaseModel{ID: user.ID}).
First(&data).Error; err != nil {
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
}
@ -29,7 +30,7 @@ func getOthersInfo(c *fiber.Ctx) error {
var data models.Account
if err := database.C.
Where(&models.Account{Name: account}).
Where(&hyper.BaseUser{Name: account}).
First(&data).Error; err != nil {
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
}
@ -42,7 +43,7 @@ func listOthersPinnedPost(c *fiber.Ctx) error {
var user models.Account
if err := database.C.
Where(&models.Account{Name: account}).
Where(&hyper.BaseUser{Name: account}).
First(&user).Error; err != nil {
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
}

View File

@ -1,19 +0,0 @@
package exts
import (
"git.solsynth.dev/hydrogen/dealer/pkg/proto"
"git.solsynth.dev/hydrogen/interactive/pkg/internal/services"
"github.com/gofiber/fiber/v2"
)
func LinkAccountMiddleware(c *fiber.Ctx) error {
if val, ok := c.Locals("p_user").(*proto.UserInfo); ok {
if account, err := services.LinkAccount(val); err != nil {
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
} else {
c.Locals("user", account)
}
}
return c.Next()
}

View File

@ -3,9 +3,11 @@ package server
import (
"strings"
"git.solsynth.dev/hydrogen/dealer/pkg/hyper"
"git.solsynth.dev/hydrogen/interactive/pkg/internal/database"
"git.solsynth.dev/hydrogen/interactive/pkg/internal/gap"
"git.solsynth.dev/hydrogen/interactive/pkg/internal/models"
"git.solsynth.dev/hydrogen/interactive/pkg/internal/server/api"
"git.solsynth.dev/hydrogen/interactive/pkg/internal/server/exts"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/cors"
"github.com/gofiber/fiber/v2/middleware/idempotency"
@ -53,7 +55,15 @@ func NewServer() {
}))
app.Use(gap.H.AuthMiddleware)
app.Use(exts.LinkAccountMiddleware)
app.Use(hyper.LinkAccountMiddleware[models.Account](
database.C,
&models.Account{},
func(u hyper.BaseUser) models.Account {
return models.Account{
BaseUser: u,
}
},
))
api.MapAPIs(app, "/api")
}

View File

@ -88,7 +88,7 @@ func NotifyPosterAccount(user models.Account, title, body string, subtitle *stri
return err
}
_, err = proto.NewNotifierClient(pc).NotifyUser(ctx, &proto.NotifyUserRequest{
UserId: uint64(user.ExternalID),
UserId: uint64(user.ID),
Notify: &proto.NotifyRequest{
Topic: "interactive.feedback",
Title: title,
@ -101,7 +101,7 @@ func NotifyPosterAccount(user models.Account, title, body string, subtitle *stri
if err != nil {
log.Warn().Err(err).Msg("An error occurred when notify account...")
} else {
log.Debug().Uint("uid", user.ExternalID).Msg("Notified account.")
log.Debug().Uint("uid", user.ID).Msg("Notified account.")
}
return err

View File

@ -1,51 +0,0 @@
package services
import (
"errors"
"fmt"
"git.solsynth.dev/hydrogen/dealer/pkg/proto"
"git.solsynth.dev/hydrogen/interactive/pkg/internal/database"
"git.solsynth.dev/hydrogen/interactive/pkg/internal/models"
"gorm.io/gorm"
"reflect"
)
func LinkAccount(userinfo *proto.UserInfo) (models.Account, error) {
var account models.Account
if userinfo == nil {
return account, fmt.Errorf("remote userinfo was not found")
}
if err := database.C.Where(&models.Account{
ExternalID: uint(userinfo.Id),
}).First(&account).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
account = models.Account{
Name: userinfo.Name,
Nick: userinfo.Nick,
Avatar: userinfo.Avatar,
Banner: userinfo.Banner,
Description: userinfo.GetDescription(),
EmailAddress: userinfo.Email,
PowerLevel: 0,
ExternalID: uint(userinfo.Id),
}
return account, database.C.Save(&account).Error
}
return account, err
}
prev := account
account.Name = userinfo.Name
account.Nick = userinfo.Nick
account.Avatar = userinfo.Avatar
account.Banner = userinfo.Banner
account.Description = userinfo.GetDescription()
account.EmailAddress = userinfo.Email
var err error
if !reflect.DeepEqual(prev, account) {
err = database.C.Save(&account).Error
}
return account, err
}

View File

@ -4,6 +4,7 @@ import (
"errors"
"strings"
"git.solsynth.dev/hydrogen/dealer/pkg/hyper"
"git.solsynth.dev/hydrogen/interactive/pkg/internal/database"
"git.solsynth.dev/hydrogen/interactive/pkg/internal/models"
"gorm.io/gorm"
@ -27,7 +28,7 @@ func GetCategory(alias string) (models.Category, error) {
func GetCategoryWithID(id uint) (models.Category, error) {
var category models.Category
if err := database.C.Where(models.Category{
BaseModel: models.BaseModel{ID: id},
BaseModel: hyper.BaseModel{ID: id},
}).First(&category).Error; err != nil {
return category, err
}

View File

@ -310,7 +310,7 @@ func NewPost(user models.Account, item models.Post) (models.Post, error) {
if item.RealmID != nil {
log.Debug().Uint("id", *item.RealmID).Msg("Looking for post author realm...")
_, err := GetRealmMember(*item.RealmID, user.ExternalID)
_, err := GetRealmMember(*item.RealmID, user.ID)
if err != nil {
return item, fmt.Errorf("you aren't a part of that realm: %v", err)
}

View File

@ -4,6 +4,8 @@ import (
"context"
"errors"
"fmt"
"reflect"
"git.solsynth.dev/hydrogen/dealer/pkg/hyper"
"git.solsynth.dev/hydrogen/dealer/pkg/proto"
"git.solsynth.dev/hydrogen/interactive/pkg/internal/database"
@ -11,7 +13,6 @@ import (
"git.solsynth.dev/hydrogen/interactive/pkg/internal/models"
"github.com/samber/lo"
"gorm.io/gorm"
"reflect"
)
func GetRealmWithExtID(id uint) (models.Realm, error) {
@ -54,7 +55,7 @@ func GetRealmMember(realmId uint, userId uint) (*proto.RealmMemberInfo, error) {
return nil, err
}
response, err := proto.NewRealmClient(pc).GetRealmMember(context.Background(), &proto.RealmMemberLookupRequest{
RealmId: uint64(realm.ExternalID),
RealmId: uint64(realm.ID),
UserId: lo.ToPtr(uint64(userId)),
})
if err != nil {
@ -69,17 +70,10 @@ func LinkRealm(info *proto.RealmInfo) (models.Realm, error) {
if info == nil {
return realm, fmt.Errorf("remote realm info was not found")
}
if err := database.C.Where(&models.Realm{
ExternalID: uint(info.Id),
}).First(&realm).Error; err != nil {
if err := database.C.Where("id = ?", info.Id).First(&realm).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
realm = models.Realm{
Alias: info.Alias,
Name: info.Name,
Description: info.Description,
IsPublic: info.IsPublic,
IsCommunity: info.IsCommunity,
ExternalID: uint(info.Id),
BaseRealm: hyper.LinkRealm(info),
}
return realm, database.C.Save(&realm).Error
}
@ -90,6 +84,8 @@ func LinkRealm(info *proto.RealmInfo) (models.Realm, error) {
realm.Alias = info.Alias
realm.Name = info.Name
realm.Description = info.Description
realm.Avatar = info.Avatar
realm.Banner = info.Banner
realm.IsPublic = info.IsPublic
realm.IsCommunity = info.IsCommunity