♻️ Move realm system to Passport

This commit is contained in:
2024-05-04 22:22:58 +08:00
parent 1181b1e5ce
commit f78a1447d5
20 changed files with 344 additions and 428 deletions

12
pkg/services/encryptor.go Normal file
View File

@ -0,0 +1,12 @@
package services
import "golang.org/x/crypto/bcrypt"
func HashPassword(raw string) string {
data, _ := bcrypt.GenerateFromPassword([]byte(raw), 12)
return string(data)
}
func VerifyPassword(text string, password string) bool {
return bcrypt.CompareHashAndPassword([]byte(password), []byte(text)) == nil
}

81
pkg/services/jwt.go Normal file
View File

@ -0,0 +1,81 @@
package services
import (
"fmt"
"github.com/gofiber/fiber/v2"
"time"
"github.com/golang-jwt/jwt/v5"
"github.com/spf13/viper"
)
type PayloadClaims struct {
jwt.RegisteredClaims
Type string `json:"typ"`
}
const (
JwtAccessType = "access"
JwtRefreshType = "refresh"
)
const (
CookieAccessKey = "passport_auth_key"
CookieRefreshKey = "passport_refresh_key"
)
func EncodeJwt(id string, typ, sub string, aud []string, exp time.Time) (string, error) {
tk := jwt.NewWithClaims(jwt.SigningMethodHS512, PayloadClaims{
jwt.RegisteredClaims{
Subject: sub,
Audience: aud,
Issuer: fmt.Sprintf("https://%s", viper.GetString("domain")),
ExpiresAt: jwt.NewNumericDate(exp),
NotBefore: jwt.NewNumericDate(time.Now()),
IssuedAt: jwt.NewNumericDate(time.Now()),
ID: id,
},
typ,
})
return tk.SignedString([]byte(viper.GetString("secret")))
}
func DecodeJwt(str string) (PayloadClaims, error) {
var claims PayloadClaims
tk, err := jwt.ParseWithClaims(str, &claims, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
}
return []byte(viper.GetString("secret")), nil
})
if err != nil {
return claims, err
}
if data, ok := tk.Claims.(*PayloadClaims); ok {
return *data, nil
} else {
return claims, fmt.Errorf("unexpected token payload: not payload claims type")
}
}
func SetJwtCookieSet(c *fiber.Ctx, access, refresh string) {
c.Cookie(&fiber.Cookie{
Name: CookieAccessKey,
Value: access,
Domain: viper.GetString("security.cookie_domain"),
SameSite: viper.GetString("security.cookie_samesite"),
Expires: time.Now().Add(60 * time.Minute),
Path: "/",
})
c.Cookie(&fiber.Cookie{
Name: CookieRefreshKey,
Value: refresh,
Domain: viper.GetString("security.cookie_domain"),
SameSite: viper.GetString("security.cookie_samesite"),
Expires: time.Now().Add(24 * 30 * time.Hour),
Path: "/",
})
}

View File

@ -3,6 +3,7 @@ package services
import (
"errors"
"fmt"
"git.solsynth.dev/hydrogen/passport/pkg/services"
"time"
"git.solsynth.dev/hydrogen/interactive/pkg/database"
@ -296,14 +297,9 @@ func NewPost[T models.PostInterface](item T) (T, error) {
}
if item.GetRealm() != nil {
if item.GetRealm().RealmType != models.RealmTypePublic {
var member models.RealmMember
if err := database.C.Where(&models.RealmMember{
RealmID: item.GetRealm().ID,
AccountID: item.GetAuthor().ID,
}).First(&member).Error; err != nil {
return item, fmt.Errorf("you aren't a part of that realm")
}
_, err := services.GetRealmMember(item.GetRealm().ID, item.GetAuthor().ID)
if err != nil {
return item, fmt.Errorf("you aren't a part of that realm: %v", err)
}
}

View File

@ -1,118 +1,82 @@
package services
import (
"context"
"errors"
"fmt"
"git.solsynth.dev/hydrogen/interactive/pkg/database"
"git.solsynth.dev/hydrogen/interactive/pkg/grpc"
"git.solsynth.dev/hydrogen/interactive/pkg/models"
"git.solsynth.dev/hydrogen/passport/pkg/grpc/proto"
"github.com/samber/lo"
"gorm.io/gorm"
)
func ListRealm() ([]models.Realm, error) {
var realms []models.Realm
if err := database.C.Find(&realms).Error; err != nil {
return realms, err
}
return realms, nil
}
func ListRealmWithUser(user models.Account) ([]models.Realm, error) {
var realms []models.Realm
if err := database.C.Where(&models.Realm{AccountID: user.ID}).Find(&realms).Error; err != nil {
return realms, err
}
return realms, nil
}
func ListRealmIsAvailable(user models.Account) ([]models.Realm, error) {
var realms []models.Realm
var members []models.RealmMember
if err := database.C.Where(&models.RealmMember{
AccountID: user.ID,
}).Find(&members).Error; err != nil {
return realms, err
}
idx := lo.Map(members, func(item models.RealmMember, index int) uint {
return item.RealmID
func GetRealm(id uint) (models.Realm, error) {
var realm models.Realm
response, err := grpc.Realms.GetRealm(context.Background(), &proto.RealmLookupRequest{
Id: lo.ToPtr(uint64(id)),
})
if err != nil {
return realm, err
}
return LinkRealm(response)
}
func GetRealmWithAlias(alias string) (models.Realm, error) {
var realm models.Realm
response, err := grpc.Realms.GetRealm(context.Background(), &proto.RealmLookupRequest{
Alias: &alias,
})
if err != nil {
return realm, err
}
return LinkRealm(response)
}
func GetRealmMember(realmId uint, userId uint) (*proto.RealmMemberResponse, error) {
response, err := grpc.Realms.GetRealmMember(context.Background(), &proto.RealmMemberLookupRequest{
RealmId: uint64(realmId),
UserId: lo.ToPtr(uint64(userId)),
})
if err != nil {
return nil, err
} else {
return response, nil
}
}
func ListRealmMember(realmId uint) ([]*proto.RealmMemberResponse, error) {
response, err := grpc.Realms.ListRealmMember(context.Background(), &proto.RealmMemberLookupRequest{
RealmId: uint64(realmId),
})
if err != nil {
return nil, err
} else {
return response.Data, nil
}
}
func LinkRealm(info *proto.RealmResponse) (models.Realm, error) {
var realm models.Realm
if info == nil {
return realm, fmt.Errorf("remote realm info was not found")
}
if err := database.C.Where(&models.Realm{
RealmType: models.RealmTypePublic,
}).Or("id IN ?", idx).Find(&realms).Error; err != nil {
return realms, err
ExternalID: uint(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),
}
return realm, database.C.Save(&realm).Error
}
return realm, err
}
return realms, nil
}
func NewRealm(user models.Account, name, description string, realmType int) (models.Realm, error) {
realm := models.Realm{
Name: name,
Description: description,
AccountID: user.ID,
RealmType: realmType,
Members: []models.RealmMember{
{AccountID: user.ID},
},
}
err := database.C.Save(&realm).Error
return realm, err
}
func ListRealmMember(realmId uint) ([]models.RealmMember, error) {
var members []models.RealmMember
if err := database.C.
Where(&models.RealmMember{RealmID: realmId}).
Preload("Account").
Find(&members).Error; err != nil {
return members, err
}
return members, nil
}
func InviteRealmMember(user models.Account, target models.Realm) error {
if _, err := GetAccountFriend(user.ID, target.AccountID, 1); err != nil {
return fmt.Errorf("you only can invite your friends to your realm")
}
member := models.RealmMember{
RealmID: target.ID,
AccountID: user.ID,
}
err := database.C.Save(&member).Error
return err
}
func KickRealmMember(user models.Account, target models.Realm) error {
var member models.RealmMember
if err := database.C.Where(&models.RealmMember{
RealmID: target.ID,
AccountID: user.ID,
}).First(&member).Error; err != nil {
return err
}
return database.C.Delete(&member).Error
}
func EditRealm(realm models.Realm, name, description string, realmType int) (models.Realm, error) {
realm.Name = name
realm.Description = description
realm.RealmType = realmType
err := database.C.Save(&realm).Error
return realm, err
}
func DeleteRealm(realm models.Realm) error {
return database.C.Delete(&realm).Error
return realm, nil
}