⬆️ Upgrade Passport

This commit is contained in:
LittleSheep 2024-05-05 00:39:59 +08:00
parent 3929f502ec
commit e6407bbe4d
16 changed files with 159 additions and 27 deletions

4
go.mod
View File

@ -5,7 +5,7 @@ go 1.22
toolchain go1.22.1
require (
git.solsynth.dev/hydrogen/identity v0.0.0-20240406034845-44d2ec9c4ace
git.solsynth.dev/hydrogen/passport v0.0.0-20240504085931-7c418a3cd32f
github.com/go-playground/validator/v10 v10.17.0
github.com/gofiber/contrib/websocket v1.3.0
github.com/gofiber/fiber/v2 v2.52.4
@ -59,7 +59,7 @@ require (
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/jxskiss/base62 v1.1.0 // indirect
github.com/klauspost/compress v1.17.7 // indirect
github.com/klauspost/compress v1.17.8 // indirect
github.com/klauspost/cpuid/v2 v2.2.6 // indirect
github.com/leodido/go-urn v1.2.4 // indirect
github.com/lithammer/shortuuid/v4 v4.0.0 // indirect

8
go.sum
View File

@ -1,5 +1,5 @@
git.solsynth.dev/hydrogen/identity v0.0.0-20240406034845-44d2ec9c4ace h1:bXbBjM56vA3BxfyuD0IrlJabpVx5bLi4qCv3/RsPa1c=
git.solsynth.dev/hydrogen/identity v0.0.0-20240406034845-44d2ec9c4ace/go.mod h1:GxcduEpQWQ2mO37A9uRtseS680uMLi957GDywRBAJHg=
git.solsynth.dev/hydrogen/passport v0.0.0-20240504085931-7c418a3cd32f h1:sKrQrKZc5C+dwefRsnc0uAGttzpSUWXUBoFaCXLkaTo=
git.solsynth.dev/hydrogen/passport v0.0.0-20240504085931-7c418a3cd32f/go.mod h1:3JRFPtf0dXRk2UQ1yVIgIspNfytM2yLBeBePJChgLZE=
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o=
@ -119,8 +119,8 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jxskiss/base62 v1.1.0 h1:A5zbF8v8WXx2xixnAKD2w+abC+sIzYJX+nxmhA6HWFw=
github.com/jxskiss/base62 v1.1.0/go.mod h1:HhWAlUXvxKThfOlZbcuFzsqwtF5TcqS9ru3y5GfjWAc=
github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg=
github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU=
github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc=
github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=

View File

@ -7,6 +7,7 @@ import (
var DatabaseAutoActionRange = []any{
&models.Account{},
&models.Realm{},
&models.Channel{},
&models.ChannelMember{},
&models.Call{},

View File

@ -1,13 +1,14 @@
package grpc
import (
idpb "git.solsynth.dev/hydrogen/identity/pkg/grpc/proto"
idpb "git.solsynth.dev/hydrogen/passport/pkg/grpc/proto"
"google.golang.org/grpc/credentials/insecure"
"github.com/spf13/viper"
"google.golang.org/grpc"
)
var Realms idpb.RealmsClient
var Friendships idpb.FriendshipsClient
var Notify idpb.NotifyClient
var Auth idpb.AuthClient
@ -17,6 +18,7 @@ func ConnectPassport() error {
if conn, err := grpc.Dial(addr, grpc.WithTransportCredentials(insecure.NewCredentials())); err != nil {
return err
} else {
Realms = idpb.NewRealmsClient(conn)
Friendships = idpb.NewFriendshipsClient(conn)
Notify = idpb.NewNotifyClient(conn)
Auth = idpb.NewAuthClient(conn)

View File

@ -10,7 +10,7 @@ const (
type Channel struct {
BaseModel
Alias string `json:"alias" gorm:"uniqueIndex"`
Alias string `json:"alias"`
Name string `json:"name"`
Description string `json:"description"`
Members []ChannelMember `json:"members"`
@ -19,7 +19,7 @@ type Channel struct {
Type ChannelType `json:"type"`
Account Account `json:"account"`
AccountID uint `json:"account_id"`
RealmID uint `json:"realm_id"`
RealmID *uint `json:"realm_id"`
}
type NotifyLevel = int8

15
pkg/models/realms.go Normal file
View File

@ -0,0 +1,15 @@
package models
// Realm profiles basically fetched from Hydrogen.Passport
// But cache at here for better usage and database relations
type Realm struct {
BaseModel
Alias string `json:"alias"`
Name string `json:"name"`
Description string `json:"description"`
Channels []Channel `json:"channels"`
IsPublic bool `json:"is_public"`
IsCommunity bool `json:"is_community"`
ExternalID uint `json:"external_id"`
}

View File

@ -3,14 +3,13 @@ package server
import (
"strings"
"git.solsynth.dev/hydrogen/messaging/pkg/security"
"git.solsynth.dev/hydrogen/messaging/pkg/services"
"github.com/gofiber/fiber/v2"
)
func authMiddleware(c *fiber.Ctx) error {
var token string
if cookie := c.Cookies(security.CookieAccessKey); len(cookie) > 0 {
if cookie := c.Cookies(services.CookieAccessKey); len(cookie) > 0 {
token = cookie
}
if header := c.Get(fiber.HeaderAuthorization); len(header) > 0 {
@ -42,10 +41,10 @@ func authFunc(c *fiber.Ctx, overrides ...string) error {
}
}
rtk := c.Cookies(security.CookieRefreshKey)
rtk := c.Cookies(services.CookieRefreshKey)
if user, atk, rtk, err := services.Authenticate(token, rtk); err == nil {
if atk != token {
security.SetJwtCookieSet(c, atk, rtk)
services.SetJwtCookieSet(c, atk, rtk)
}
c.Locals("principal", user)
return nil

View File

@ -1,6 +1,7 @@
package server
import (
"fmt"
"git.solsynth.dev/hydrogen/messaging/pkg/database"
"git.solsynth.dev/hydrogen/messaging/pkg/models"
"git.solsynth.dev/hydrogen/messaging/pkg/services"
@ -22,7 +23,7 @@ func listChannelMembers(c *fiber.Ctx) error {
}
}
func inviteChannel(c *fiber.Ctx) error {
func addChannelMember(c *fiber.Ctx) error {
user := c.Locals("principal").(models.Account)
alias := c.Params("channel")
@ -49,14 +50,14 @@ func inviteChannel(c *fiber.Ctx) error {
return fiber.NewError(fiber.StatusNotFound, err.Error())
}
if err := services.InviteChannelMember(account, channel); err != nil {
if err := services.AddChannelMemberWithCheck(account, channel); err != nil {
return fiber.NewError(fiber.StatusBadRequest, err.Error())
} else {
return c.SendStatus(fiber.StatusOK)
}
}
func kickChannel(c *fiber.Ctx) error {
func removeChannelMember(c *fiber.Ctx) error {
user := c.Locals("principal").(models.Account)
alias := c.Params("channel")
@ -124,6 +125,34 @@ func editChannelMembership(c *fiber.Ctx) error {
}
}
func joinChannel(c *fiber.Ctx) error {
user := c.Locals("principal").(models.Account)
alias := c.Params("channel")
var channel models.Channel
if err := database.C.Where(&models.Channel{
Alias: alias,
}).First(&channel).Error; err != nil {
return fiber.NewError(fiber.StatusNotFound, err.Error())
} else if _, _, err := services.GetAvailableChannel(channel.ID, user); err == nil {
return fiber.NewError(fiber.StatusBadRequest, "you already joined the channel")
} else if channel.RealmID == nil {
return fiber.NewError(fiber.StatusBadRequest, "you was impossible to join a channel without related realm")
}
if realm, err := services.GetRealm(channel.ID); err != nil {
return fiber.NewError(fiber.StatusInternalServerError, fmt.Sprintf("invalid channel, related realm was not found: %v", err))
} else if _, err := services.GetRealmMember(realm.ID, user.ExternalID); err != nil {
return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("you are not a part of the realm: %v", err))
}
if err := services.AddChannelMember(user, channel); err != nil {
return fiber.NewError(fiber.StatusBadRequest, err.Error())
} else {
return c.SendStatus(fiber.StatusOK)
}
}
func leaveChannel(c *fiber.Ctx) error {
user := c.Locals("principal").(models.Account)
alias := c.Params("channel")

View File

@ -9,6 +9,7 @@ import (
)
func listMessage(c *fiber.Ctx) error {
user := c.Locals("principal").(models.Account)
take := c.QueryInt("take", 0)
offset := c.QueryInt("offset", 0)
alias := c.Params("channel")
@ -16,6 +17,8 @@ func listMessage(c *fiber.Ctx) error {
channel, err := services.GetChannelWithAlias(alias)
if err != nil {
return fiber.NewError(fiber.StatusNotFound, err.Error())
} else if _, _, err := services.GetAvailableChannel(channel.ID, user); err != nil {
return fiber.NewError(fiber.StatusForbidden, fmt.Sprintf("you need join the channel before you read the messages: %v", err))
}
count := services.CountMessage(channel)
@ -30,7 +33,7 @@ func listMessage(c *fiber.Ctx) error {
})
}
func newTextMessage(c *fiber.Ctx) error {
func newMessage(c *fiber.Ctx) error {
user := c.Locals("principal").(models.Account)
alias := c.Params("channel")

View File

@ -88,12 +88,13 @@ func NewServer() {
channels.Get("/:channel/members", listChannelMembers)
channels.Put("/:channel/members", authMiddleware, editChannelMembership)
channels.Post("/:channel/invite", authMiddleware, inviteChannel)
channels.Post("/:channel/kick", authMiddleware, kickChannel)
channels.Post("/:channel/leave", authMiddleware, leaveChannel)
channels.Post("/:channel/members", authMiddleware, addChannelMember)
channels.Post("/:channel/members/me", authMiddleware, joinChannel)
channels.Delete("/:channel/members", authMiddleware, removeChannelMember)
channels.Delete("/:channel/members/me", authMiddleware, leaveChannel)
channels.Get("/:channel/messages", listMessage)
channels.Post("/:channel/messages", authMiddleware, newTextMessage)
channels.Get("/:channel/messages", authMiddleware, listMessage)
channels.Post("/:channel/messages", authMiddleware, newMessage)
channels.Put("/:channel/messages/:messageId", authMiddleware, editMessage)
channels.Delete("/:channel/messages/:messageId", authMiddleware, deleteMessage)

View File

@ -5,9 +5,9 @@ import (
"git.solsynth.dev/hydrogen/messaging/pkg/database"
"time"
"git.solsynth.dev/hydrogen/identity/pkg/grpc/proto"
"git.solsynth.dev/hydrogen/messaging/pkg/grpc"
"git.solsynth.dev/hydrogen/messaging/pkg/models"
"git.solsynth.dev/hydrogen/passport/pkg/grpc/proto"
"github.com/spf13/viper"
)

View File

@ -7,10 +7,10 @@ import (
"reflect"
"time"
"git.solsynth.dev/hydrogen/identity/pkg/grpc/proto"
"git.solsynth.dev/hydrogen/messaging/pkg/database"
"git.solsynth.dev/hydrogen/messaging/pkg/grpc"
"git.solsynth.dev/hydrogen/messaging/pkg/models"
"git.solsynth.dev/hydrogen/passport/pkg/grpc/proto"
"gorm.io/gorm"
)

View File

@ -19,7 +19,7 @@ func ListChannelMember(channelId uint) ([]models.ChannelMember, error) {
return members, nil
}
func InviteChannelMember(user models.Account, target models.Channel) error {
func AddChannelMemberWithCheck(user models.Account, target models.Channel) error {
if _, err := GetAccountFriend(user.ID, target.AccountID, 1); err != nil {
return fmt.Errorf("you only can invite your friends to your channel")
}

View File

@ -1,4 +1,4 @@
package security
package services
import "golang.org/x/crypto/bcrypt"

View File

@ -1,4 +1,4 @@
package security
package services
import (
"fmt"

82
pkg/services/realms.go Normal file
View File

@ -0,0 +1,82 @@
package services
import (
"context"
"errors"
"fmt"
"git.solsynth.dev/hydrogen/messaging/pkg/database"
"git.solsynth.dev/hydrogen/messaging/pkg/grpc"
"git.solsynth.dev/hydrogen/messaging/pkg/models"
"git.solsynth.dev/hydrogen/passport/pkg/grpc/proto"
"github.com/samber/lo"
"gorm.io/gorm"
)
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{
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 realm, nil
}