Compare commits
No commits in common. "ee7736b261ea684654ac39749a7b616cee86fa4a" and "b3fe2c2163a3a97b5a508b9461fbbe8d372eae58" have entirely different histories.
ee7736b261
...
b3fe2c2163
7
go.mod
7
go.mod
@ -5,13 +5,14 @@ go 1.22
|
|||||||
toolchain go1.22.1
|
toolchain go1.22.1
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.solsynth.dev/hydrogen/dealer v0.0.0-20240716024524-cfb73fde1951
|
|
||||||
git.solsynth.dev/hydrogen/paperclip v0.0.0-20240622051057-0f56dba45745
|
git.solsynth.dev/hydrogen/paperclip v0.0.0-20240622051057-0f56dba45745
|
||||||
|
git.solsynth.dev/hydrogen/passport v0.0.0-20240623083719-86b2cd81400a
|
||||||
github.com/go-playground/validator/v10 v10.17.0
|
github.com/go-playground/validator/v10 v10.17.0
|
||||||
github.com/gofiber/contrib/websocket v1.3.0
|
github.com/gofiber/contrib/websocket v1.3.0
|
||||||
github.com/gofiber/fiber/v2 v2.52.4
|
github.com/gofiber/fiber/v2 v2.52.4
|
||||||
github.com/gofiber/template/html/v2 v2.1.1
|
github.com/gofiber/template/html/v2 v2.1.1
|
||||||
github.com/google/uuid v1.6.0
|
github.com/golang-jwt/jwt/v5 v5.2.0
|
||||||
|
github.com/hashicorp/consul/api v1.29.1
|
||||||
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible
|
github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible
|
||||||
github.com/json-iterator/go v1.1.12
|
github.com/json-iterator/go v1.1.12
|
||||||
github.com/livekit/protocol v1.14.0
|
github.com/livekit/protocol v1.14.0
|
||||||
@ -53,8 +54,8 @@ require (
|
|||||||
github.com/go-sql-driver/mysql v1.7.1 // indirect
|
github.com/go-sql-driver/mysql v1.7.1 // indirect
|
||||||
github.com/gofiber/template v1.8.3 // indirect
|
github.com/gofiber/template v1.8.3 // indirect
|
||||||
github.com/gofiber/utils v1.1.0 // indirect
|
github.com/gofiber/utils v1.1.0 // indirect
|
||||||
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
github.com/gorilla/websocket v1.5.1 // indirect
|
github.com/gorilla/websocket v1.5.1 // indirect
|
||||||
github.com/hashicorp/consul/api v1.29.1 // indirect
|
|
||||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||||
github.com/hashicorp/go-hclog v1.6.3 // indirect
|
github.com/hashicorp/go-hclog v1.6.3 // indirect
|
||||||
|
8
go.sum
8
go.sum
@ -1,7 +1,9 @@
|
|||||||
git.solsynth.dev/hydrogen/dealer v0.0.0-20240716024524-cfb73fde1951 h1:RgZJK4PXhrjhUX75BclBCg2xfetMkswcMwMqfTBtryQ=
|
|
||||||
git.solsynth.dev/hydrogen/dealer v0.0.0-20240716024524-cfb73fde1951/go.mod h1:eZwAwP7ahL7TO8GWBlYFYDdjlna+8zHYbDfNabnuUEU=
|
|
||||||
git.solsynth.dev/hydrogen/paperclip v0.0.0-20240622051057-0f56dba45745 h1:40BUsQMNXjqHyytkyF9py1HjTAWlRgO6R57YXUrHNy4=
|
git.solsynth.dev/hydrogen/paperclip v0.0.0-20240622051057-0f56dba45745 h1:40BUsQMNXjqHyytkyF9py1HjTAWlRgO6R57YXUrHNy4=
|
||||||
git.solsynth.dev/hydrogen/paperclip v0.0.0-20240622051057-0f56dba45745/go.mod h1:FsQGSLTl0gvo+9Jmbot02S72suyF9tFTrzDj70Xhifo=
|
git.solsynth.dev/hydrogen/paperclip v0.0.0-20240622051057-0f56dba45745/go.mod h1:FsQGSLTl0gvo+9Jmbot02S72suyF9tFTrzDj70Xhifo=
|
||||||
|
git.solsynth.dev/hydrogen/passport v0.0.0-20240623081149-7ddbea8bcb86 h1:cxjBOhemnyxf49CJyPmnt1RKFHerK45rXXBPwsIFrhA=
|
||||||
|
git.solsynth.dev/hydrogen/passport v0.0.0-20240623081149-7ddbea8bcb86/go.mod h1:tUr7x1v0trG3ALDacdDuhJiPRPgFhJ1Si9OqNlYbgSk=
|
||||||
|
git.solsynth.dev/hydrogen/passport v0.0.0-20240623083719-86b2cd81400a h1:oxNbS6Q+sSOfYUQTcx9/awCmlk/lpVP997hgpMmFsyw=
|
||||||
|
git.solsynth.dev/hydrogen/passport v0.0.0-20240623083719-86b2cd81400a/go.mod h1:tUr7x1v0trG3ALDacdDuhJiPRPgFhJ1Si9OqNlYbgSk=
|
||||||
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
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-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
@ -101,6 +103,8 @@ github.com/gofiber/template/html/v2 v2.1.1/go.mod h1:2G0GHHOUx70C1LDncoBpe4T6maQ
|
|||||||
github.com/gofiber/utils v1.1.0 h1:vdEBpn7AzIUJRhe+CiTOJdUcTg4Q9RK+pEa0KPbLdrM=
|
github.com/gofiber/utils v1.1.0 h1:vdEBpn7AzIUJRhe+CiTOJdUcTg4Q9RK+pEa0KPbLdrM=
|
||||||
github.com/gofiber/utils v1.1.0/go.mod h1:poZpsnhBykfnY1Mc0KeEa6mSHrS3dV0+oBWyeQmb2e0=
|
github.com/gofiber/utils v1.1.0/go.mod h1:poZpsnhBykfnY1Mc0KeEa6mSHrS3dV0+oBWyeQmb2e0=
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
|
github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw=
|
||||||
|
github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
|
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
|
||||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||||
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
|
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
|
||||||
|
12
pkg/internal/gap/client.go
Normal file
12
pkg/internal/gap/client.go
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package gap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.solsynth.dev/hydrogen/passport/pkg/hyper"
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
)
|
||||||
|
|
||||||
|
var H *hyper.HyperConn
|
||||||
|
|
||||||
|
func NewHyperClient() {
|
||||||
|
H = hyper.NewHyperConn(viper.GetString("consul.addr"))
|
||||||
|
}
|
@ -2,41 +2,38 @@ package gap
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"git.solsynth.dev/hydrogen/dealer/pkg/hyper"
|
"strconv"
|
||||||
"git.solsynth.dev/hydrogen/dealer/pkg/proto"
|
|
||||||
"github.com/rs/zerolog/log"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/api"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
var H *hyper.HyperConn
|
func Register() error {
|
||||||
|
cfg := api.DefaultConfig()
|
||||||
|
cfg.Address = viper.GetString("consul.addr")
|
||||||
|
|
||||||
func RegisterService() error {
|
client, err := api.NewClient(cfg)
|
||||||
grpcBind := strings.SplitN(viper.GetString("grpc_bind"), ":", 2)
|
|
||||||
httpBind := strings.SplitN(viper.GetString("bind"), ":", 2)
|
|
||||||
|
|
||||||
outboundIp, _ := GetOutboundIP()
|
|
||||||
|
|
||||||
grpcOutbound := fmt.Sprintf("%s:%s", outboundIp, grpcBind[1])
|
|
||||||
httpOutbound := fmt.Sprintf("%s:%s", outboundIp, httpBind[1])
|
|
||||||
|
|
||||||
var err error
|
|
||||||
H, err = hyper.NewHyperConn(viper.GetString("dealer.addr"), &proto.ServiceInfo{
|
|
||||||
Id: viper.GetString("id"),
|
|
||||||
Type: hyper.ServiceTypeMessagingProvider,
|
|
||||||
Label: "Messaging",
|
|
||||||
GrpcAddr: grpcOutbound,
|
|
||||||
HttpAddr: &httpOutbound,
|
|
||||||
})
|
|
||||||
if err == nil {
|
|
||||||
go func() {
|
|
||||||
err := H.KeepRegisterService()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msg("An error occurred while registering service...")
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
grpcBind := strings.SplitN(viper.GetString("grpc_bind"), ":", 2)
|
||||||
|
|
||||||
|
outboundIp, _ := GetOutboundIP()
|
||||||
|
port, _ := strconv.Atoi(grpcBind[1])
|
||||||
|
|
||||||
|
registration := new(api.AgentServiceRegistration)
|
||||||
|
registration.ID = viper.GetString("id")
|
||||||
|
registration.Name = "Hydrogen.Messaging"
|
||||||
|
registration.Address = outboundIp.String()
|
||||||
|
registration.Port = port
|
||||||
|
registration.Check = &api.AgentServiceCheck{
|
||||||
|
GRPC: fmt.Sprintf("%s:%s", outboundIp, grpcBind[1]),
|
||||||
|
Timeout: "5s",
|
||||||
|
Interval: "1m",
|
||||||
|
DeregisterCriticalServiceAfter: "3m",
|
||||||
|
}
|
||||||
|
|
||||||
|
return client.Agent().ServiceRegister(registration)
|
||||||
|
}
|
||||||
|
48
pkg/internal/server/api/events_ws.go
Normal file
48
pkg/internal/server/api/events_ws.go
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.solsynth.dev/hydrogen/messaging/pkg/internal/models"
|
||||||
|
"git.solsynth.dev/hydrogen/messaging/pkg/internal/services"
|
||||||
|
"github.com/gofiber/contrib/websocket"
|
||||||
|
jsoniter "github.com/json-iterator/go"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func messageGateway(c *websocket.Conn) {
|
||||||
|
user := c.Locals("user").(models.Account)
|
||||||
|
|
||||||
|
// Push connection
|
||||||
|
services.ClientRegister(user, c)
|
||||||
|
log.Debug().Uint("user", user.ID).Msg("New websocket connection established...")
|
||||||
|
|
||||||
|
// Event loop
|
||||||
|
var task models.UnifiedCommand
|
||||||
|
|
||||||
|
var messageType int
|
||||||
|
var packet []byte
|
||||||
|
var err error
|
||||||
|
|
||||||
|
for {
|
||||||
|
if messageType, packet, err = c.ReadMessage(); err != nil {
|
||||||
|
break
|
||||||
|
} else if err := jsoniter.Unmarshal(packet, &task); err != nil {
|
||||||
|
_ = c.WriteMessage(messageType, models.UnifiedCommand{
|
||||||
|
Action: "error",
|
||||||
|
Message: "unable to unmarshal your command, requires json request",
|
||||||
|
}.Marshal())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
message := services.DealCommand(task, user)
|
||||||
|
|
||||||
|
if message != nil {
|
||||||
|
if err = c.WriteMessage(messageType, message.Marshal()); err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pop connection
|
||||||
|
services.ClientUnregister(user, c)
|
||||||
|
log.Debug().Uint("user", user.ID).Msg("A websocket connection disconnected...")
|
||||||
|
}
|
@ -1,6 +1,8 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"git.solsynth.dev/hydrogen/messaging/pkg/internal/gap"
|
||||||
|
"github.com/gofiber/contrib/websocket"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -45,5 +47,12 @@ func MapAPIs(app *fiber.App) {
|
|||||||
channels.Delete("/:channel/calls/ongoing", endCall)
|
channels.Delete("/:channel/calls/ongoing", endCall)
|
||||||
channels.Post("/:channel/calls/ongoing/token", exchangeCallToken)
|
channels.Post("/:channel/calls/ongoing/token", exchangeCallToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
api.Use(func(c *fiber.Ctx) error {
|
||||||
|
if err := gap.H.EnsureAuthenticated(c); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return c.Next()
|
||||||
|
}).Get("/ws", websocket.New(messageGateway))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
package exts
|
package exts
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"git.solsynth.dev/hydrogen/dealer/pkg/proto"
|
|
||||||
"git.solsynth.dev/hydrogen/messaging/pkg/internal/services"
|
"git.solsynth.dev/hydrogen/messaging/pkg/internal/services"
|
||||||
|
"git.solsynth.dev/hydrogen/passport/pkg/proto"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func LinkAccountMiddleware(c *fiber.Ctx) error {
|
func LinkAccountMiddleware(c *fiber.Ctx) error {
|
||||||
if val, ok := c.Locals("p_user").(*proto.UserInfo); ok {
|
if val, ok := c.Locals("p_user").(*proto.Userinfo); ok {
|
||||||
if account, err := services.LinkAccount(val); err != nil {
|
if account, err := services.LinkAccount(val); err != nil {
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
return fiber.NewError(fiber.StatusInternalServerError, err.Error())
|
||||||
} else {
|
} else {
|
||||||
|
@ -3,69 +3,57 @@ package services
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"git.solsynth.dev/hydrogen/dealer/pkg/hyper"
|
|
||||||
"git.solsynth.dev/hydrogen/messaging/pkg/internal/database"
|
"git.solsynth.dev/hydrogen/messaging/pkg/internal/database"
|
||||||
"git.solsynth.dev/hydrogen/messaging/pkg/internal/gap"
|
"git.solsynth.dev/hydrogen/messaging/pkg/internal/gap"
|
||||||
jsoniter "github.com/json-iterator/go"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.solsynth.dev/hydrogen/dealer/pkg/proto"
|
|
||||||
"git.solsynth.dev/hydrogen/messaging/pkg/internal/models"
|
"git.solsynth.dev/hydrogen/messaging/pkg/internal/models"
|
||||||
|
"git.solsynth.dev/hydrogen/passport/pkg/proto"
|
||||||
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
func CheckUserPerm(userId, otherId uint, key string, val any) error {
|
func GetAccountFriend(userId, relatedId uint, status int) (*proto.FriendshipResponse, error) {
|
||||||
var user models.Account
|
var user models.Account
|
||||||
if err := database.C.Where("id = ?", userId).First(&user).Error; err != nil {
|
if err := database.C.Where("id = ?", userId).First(&user).Error; err != nil {
|
||||||
return fmt.Errorf("account not found: %v", err)
|
return nil, err
|
||||||
}
|
}
|
||||||
var other models.Account
|
var related models.Account
|
||||||
if err := database.C.Where("id = ?", otherId).First(&other).Error; err != nil {
|
if err := database.C.Where("id = ?", relatedId).First(&related).Error; err != nil {
|
||||||
return fmt.Errorf("other not found: %v", err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
encodedData, _ := jsoniter.Marshal(val)
|
pc, err := gap.H.DiscoverServiceGRPC("Hydrogen.Passport")
|
||||||
|
|
||||||
pc, err := gap.H.GetServiceGrpcConn(hyper.ServiceTypeAuthProvider)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
out, err := proto.NewAuthClient(pc).EnsureUserPermGranted(ctx, &proto.CheckUserPermRequest{
|
return proto.NewFriendshipsClient(pc).GetFriendship(ctx, &proto.FriendshipTwoSideLookupRequest{
|
||||||
UserId: uint64(user.ExternalID),
|
AccountId: uint64(user.ExternalID),
|
||||||
OtherId: uint64(other.ExternalID),
|
RelatedId: uint64(related.ExternalID),
|
||||||
Key: key,
|
Status: uint32(status),
|
||||||
Value: encodedData,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
} else if !out.IsValid {
|
|
||||||
return fmt.Errorf("missing permission: %v", key)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
func NotifyAccountMessager(user models.Account, t, s, c string, realtime bool, forcePush bool, links ...*proto.NotifyLink) error {
|
||||||
}
|
|
||||||
|
|
||||||
func NotifyAccountMessager(user models.Account, title, body string, subtitle *string, realtime bool, forcePush bool) error {
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
pc, err := gap.H.GetServiceGrpcConn(hyper.ServiceTypeAuthProvider)
|
pc, err := gap.H.DiscoverServiceGRPC("Hydrogen.Passport")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, err = proto.NewNotifierClient(pc).NotifyUser(ctx, &proto.NotifyUserRequest{
|
_, err = proto.NewNotifyClient(pc).NotifyUser(ctx, &proto.NotifyRequest{
|
||||||
UserId: uint64(user.ID),
|
ClientId: viper.GetString("passport.client_id"),
|
||||||
Notify: &proto.NotifyRequest{
|
ClientSecret: viper.GetString("passport.client_secret"),
|
||||||
Topic: "messaging.message",
|
Type: fmt.Sprintf("messaging.%s", t),
|
||||||
Title: title,
|
Subject: s,
|
||||||
Subtitle: subtitle,
|
Content: c,
|
||||||
Body: body,
|
Links: links,
|
||||||
|
RecipientId: uint64(user.ExternalID),
|
||||||
IsRealtime: realtime,
|
IsRealtime: realtime,
|
||||||
IsForcePush: forcePush,
|
IsForcePush: forcePush,
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return err
|
return err
|
||||||
|
@ -2,7 +2,6 @@ package services
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"git.solsynth.dev/hydrogen/dealer/pkg/hyper"
|
|
||||||
"git.solsynth.dev/hydrogen/messaging/pkg/internal/gap"
|
"git.solsynth.dev/hydrogen/messaging/pkg/internal/gap"
|
||||||
|
|
||||||
"git.solsynth.dev/hydrogen/paperclip/pkg/proto"
|
"git.solsynth.dev/hydrogen/paperclip/pkg/proto"
|
||||||
@ -10,7 +9,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func CheckAttachmentByIDExists(id uint, usage string) bool {
|
func CheckAttachmentByIDExists(id uint, usage string) bool {
|
||||||
pc, err := gap.H.GetServiceGrpcConn(hyper.ServiceTypeAuthProvider)
|
pc, err := gap.H.DiscoverServiceGRPC("Hydrogen.Passport")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -3,14 +3,14 @@ package services
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"git.solsynth.dev/hydrogen/dealer/pkg/proto"
|
|
||||||
"git.solsynth.dev/hydrogen/messaging/pkg/internal/database"
|
"git.solsynth.dev/hydrogen/messaging/pkg/internal/database"
|
||||||
"git.solsynth.dev/hydrogen/messaging/pkg/internal/models"
|
"git.solsynth.dev/hydrogen/messaging/pkg/internal/models"
|
||||||
|
"git.solsynth.dev/hydrogen/passport/pkg/proto"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"reflect"
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
func LinkAccount(userinfo *proto.UserInfo) (models.Account, error) {
|
func LinkAccount(userinfo *proto.Userinfo) (models.Account, error) {
|
||||||
var account models.Account
|
var account models.Account
|
||||||
if userinfo == nil {
|
if userinfo == nil {
|
||||||
return account, fmt.Errorf("remote userinfo was not found")
|
return account, fmt.Errorf("remote userinfo was not found")
|
||||||
|
@ -99,9 +99,9 @@ func NewCall(channel models.Channel, founder models.ChannelMember) (models.Call,
|
|||||||
for _, member := range members {
|
for _, member := range members {
|
||||||
if member.ID != call.Founder.ID {
|
if member.ID != call.Founder.ID {
|
||||||
err = NotifyAccountMessager(member.Account,
|
err = NotifyAccountMessager(member.Account,
|
||||||
|
"incomingCall",
|
||||||
fmt.Sprintf("Call in #%s", channel.Alias),
|
fmt.Sprintf("Call in #%s", channel.Alias),
|
||||||
fmt.Sprintf("%s started a new call", call.Founder.Account.Name),
|
fmt.Sprintf("%s started a new call", call.Founder.Account.Name),
|
||||||
nil,
|
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
)
|
)
|
||||||
|
@ -33,8 +33,8 @@ func GetChannelMember(user models.Account, channelId uint) (models.ChannelMember
|
|||||||
}
|
}
|
||||||
|
|
||||||
func AddChannelMemberWithCheck(user models.Account, target models.Channel) error {
|
func AddChannelMemberWithCheck(user models.Account, target models.Channel) error {
|
||||||
if err := CheckUserPerm(user.ID, target.AccountID, "ChannelAdd", true); err != nil {
|
if _, err := GetAccountFriend(user.ID, target.AccountID, 1); err != nil {
|
||||||
return fmt.Errorf("unable to add user into your channel")
|
return fmt.Errorf("you only can invite your friends to your channel")
|
||||||
}
|
}
|
||||||
|
|
||||||
member := models.ChannelMember{
|
member := models.ChannelMember{
|
||||||
|
47
pkg/internal/services/connections.go
Normal file
47
pkg/internal/services/connections.go
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
package services
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"git.solsynth.dev/hydrogen/messaging/pkg/internal/models"
|
||||||
|
"github.com/gofiber/contrib/websocket"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
wsMutex sync.Mutex
|
||||||
|
wsConn = make(map[uint]map[*websocket.Conn]bool)
|
||||||
|
)
|
||||||
|
|
||||||
|
func ClientRegister(user models.Account, conn *websocket.Conn) {
|
||||||
|
wsMutex.Lock()
|
||||||
|
if wsConn[user.ID] == nil {
|
||||||
|
wsConn[user.ID] = make(map[*websocket.Conn]bool)
|
||||||
|
}
|
||||||
|
wsConn[user.ID][conn] = true
|
||||||
|
wsMutex.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func ClientUnregister(user models.Account, conn *websocket.Conn) {
|
||||||
|
wsMutex.Lock()
|
||||||
|
if wsConn[user.ID] == nil {
|
||||||
|
wsConn[user.ID] = make(map[*websocket.Conn]bool)
|
||||||
|
}
|
||||||
|
delete(wsConn[user.ID], conn)
|
||||||
|
wsMutex.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func PushCommand(userId uint, task models.UnifiedCommand) {
|
||||||
|
for conn := range wsConn[userId] {
|
||||||
|
_ = conn.WriteMessage(1, task.Marshal())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func DealCommand(task models.UnifiedCommand, user models.Account) *models.UnifiedCommand {
|
||||||
|
switch task.Action {
|
||||||
|
default:
|
||||||
|
return &models.UnifiedCommand{
|
||||||
|
Action: "error",
|
||||||
|
Message: "command not found",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
pkg/internal/services/encryptor.go
Normal file
12
pkg/internal/services/encryptor.go
Normal 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
|
||||||
|
}
|
@ -136,9 +136,9 @@ func NotifyMessageEvent(members []models.ChannelMember, event models.Event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err := NotifyAccountMessager(member.Account,
|
err := NotifyAccountMessager(member.Account,
|
||||||
|
"incomingMessage",
|
||||||
fmt.Sprintf("%s in %s", event.Sender.Account.Nick, channelDisplay),
|
fmt.Sprintf("%s in %s", event.Sender.Account.Nick, channelDisplay),
|
||||||
fmt.Sprintf("%s", displayText),
|
fmt.Sprintf("%s", displayText),
|
||||||
nil,
|
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
|
81
pkg/internal/services/jwt.go
Normal file
81
pkg/internal/services/jwt.go
Normal 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 = "identity_auth_key"
|
||||||
|
CookieRefreshKey = "identity_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: "/",
|
||||||
|
})
|
||||||
|
}
|
@ -4,11 +4,10 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"git.solsynth.dev/hydrogen/dealer/pkg/hyper"
|
|
||||||
"git.solsynth.dev/hydrogen/dealer/pkg/proto"
|
|
||||||
"git.solsynth.dev/hydrogen/messaging/pkg/internal/database"
|
"git.solsynth.dev/hydrogen/messaging/pkg/internal/database"
|
||||||
"git.solsynth.dev/hydrogen/messaging/pkg/internal/gap"
|
"git.solsynth.dev/hydrogen/messaging/pkg/internal/gap"
|
||||||
"git.solsynth.dev/hydrogen/messaging/pkg/internal/models"
|
"git.solsynth.dev/hydrogen/messaging/pkg/internal/models"
|
||||||
|
"git.solsynth.dev/hydrogen/passport/pkg/proto"
|
||||||
"github.com/samber/lo"
|
"github.com/samber/lo"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"reflect"
|
"reflect"
|
||||||
@ -16,11 +15,11 @@ import (
|
|||||||
|
|
||||||
func GetRealmWithExtID(id uint) (models.Realm, error) {
|
func GetRealmWithExtID(id uint) (models.Realm, error) {
|
||||||
var realm models.Realm
|
var realm models.Realm
|
||||||
pc, err := gap.H.GetServiceGrpcConn(hyper.ServiceTypeAuthProvider)
|
pc, err := gap.H.DiscoverServiceGRPC("Hydrogen.Passport")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return realm, err
|
return realm, err
|
||||||
}
|
}
|
||||||
response, err := proto.NewRealmClient(pc).GetRealm(context.Background(), &proto.LookupRealmRequest{
|
response, err := proto.NewRealmsClient(pc).GetRealm(context.Background(), &proto.RealmLookupRequest{
|
||||||
Id: lo.ToPtr(uint64(id)),
|
Id: lo.ToPtr(uint64(id)),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -31,11 +30,11 @@ func GetRealmWithExtID(id uint) (models.Realm, error) {
|
|||||||
|
|
||||||
func GetRealmWithAlias(alias string) (models.Realm, error) {
|
func GetRealmWithAlias(alias string) (models.Realm, error) {
|
||||||
var realm models.Realm
|
var realm models.Realm
|
||||||
pc, err := gap.H.GetServiceGrpcConn(hyper.ServiceTypeAuthProvider)
|
pc, err := gap.H.DiscoverServiceGRPC("Hydrogen.Passport")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return realm, err
|
return realm, err
|
||||||
}
|
}
|
||||||
response, err := proto.NewRealmClient(pc).GetRealm(context.Background(), &proto.LookupRealmRequest{
|
response, err := proto.NewRealmsClient(pc).GetRealm(context.Background(), &proto.RealmLookupRequest{
|
||||||
Alias: &alias,
|
Alias: &alias,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -44,16 +43,16 @@ func GetRealmWithAlias(alias string) (models.Realm, error) {
|
|||||||
return LinkRealm(response)
|
return LinkRealm(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetRealmMember(realmId uint, userId uint) (*proto.RealmMemberInfo, error) {
|
func GetRealmMember(realmId uint, userId uint) (*proto.RealmMemberResponse, error) {
|
||||||
var realm models.Realm
|
var realm models.Realm
|
||||||
if err := database.C.Where("id = ?", realmId).First(&realm).Error; err != nil {
|
if err := database.C.Where("id = ?", realmId).First(&realm).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
pc, err := gap.H.GetServiceGrpcConn(hyper.ServiceTypeAuthProvider)
|
pc, err := gap.H.DiscoverServiceGRPC("Hydrogen.Passport")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
response, err := proto.NewRealmClient(pc).GetRealmMember(context.Background(), &proto.RealmMemberLookupRequest{
|
response, err := proto.NewRealmsClient(pc).GetRealmMember(context.Background(), &proto.RealmMemberLookupRequest{
|
||||||
RealmId: uint64(realm.ExternalID),
|
RealmId: uint64(realm.ExternalID),
|
||||||
UserId: lo.ToPtr(uint64(userId)),
|
UserId: lo.ToPtr(uint64(userId)),
|
||||||
})
|
})
|
||||||
@ -64,12 +63,12 @@ func GetRealmMember(realmId uint, userId uint) (*proto.RealmMemberInfo, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ListRealmMember(realmId uint) ([]*proto.RealmMemberInfo, error) {
|
func ListRealmMember(realmId uint) ([]*proto.RealmMemberResponse, error) {
|
||||||
pc, err := gap.H.GetServiceGrpcConn(hyper.ServiceTypeAuthProvider)
|
pc, err := gap.H.DiscoverServiceGRPC("Hydrogen.Passport")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
response, err := proto.NewRealmClient(pc).ListRealmMember(context.Background(), &proto.RealmMemberLookupRequest{
|
response, err := proto.NewRealmsClient(pc).ListRealmMember(context.Background(), &proto.RealmMemberLookupRequest{
|
||||||
RealmId: uint64(realmId),
|
RealmId: uint64(realmId),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -79,7 +78,7 @@ func ListRealmMember(realmId uint) ([]*proto.RealmMemberInfo, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func LinkRealm(info *proto.RealmInfo) (models.Realm, error) {
|
func LinkRealm(info *proto.RealmResponse) (models.Realm, error) {
|
||||||
var realm models.Realm
|
var realm models.Realm
|
||||||
if info == nil {
|
if info == nil {
|
||||||
return realm, fmt.Errorf("remote realm info was not found")
|
return realm, fmt.Errorf("remote realm info was not found")
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
package services
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"git.solsynth.dev/hydrogen/dealer/pkg/proto"
|
|
||||||
"git.solsynth.dev/hydrogen/messaging/pkg/internal/gap"
|
|
||||||
"git.solsynth.dev/hydrogen/messaging/pkg/internal/models"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func PushCommand(userId uint, task models.UnifiedCommand) {
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
pc := gap.H.GetDealerGrpcConn()
|
|
||||||
_, _ = proto.NewStreamControllerClient(pc).PushStream(ctx, &proto.PushStreamRequest{
|
|
||||||
UserId: uint64(userId),
|
|
||||||
Body: task.Marshal(),
|
|
||||||
})
|
|
||||||
}
|
|
@ -44,10 +44,12 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Connect other services
|
// Connect other services
|
||||||
if err := gap.RegisterService(); err != nil {
|
|
||||||
log.Fatal().Err(err).Msg("An error occurred when connecting to consul...")
|
|
||||||
}
|
|
||||||
services.SetupLiveKit()
|
services.SetupLiveKit()
|
||||||
|
if err := gap.Register(); err != nil {
|
||||||
|
log.Fatal().Err(err).Msg("An error occurred when connecting to consul...")
|
||||||
|
} else {
|
||||||
|
gap.NewHyperClient()
|
||||||
|
}
|
||||||
|
|
||||||
// Server
|
// Server
|
||||||
server.NewServer()
|
server.NewServer()
|
||||||
|
@ -7,11 +7,11 @@ grpc_bind = "0.0.0.0:7447"
|
|||||||
domain = "im.solsynth.dev"
|
domain = "im.solsynth.dev"
|
||||||
secret = "LtTjzAGFLshwXhN4ZD4nG5KlMv1MWcsvfv03TSZYnT1VhiAnLIZFTnHUwR0XhGgi"
|
secret = "LtTjzAGFLshwXhN4ZD4nG5KlMv1MWcsvfv03TSZYnT1VhiAnLIZFTnHUwR0XhGgi"
|
||||||
|
|
||||||
[dealer]
|
[consul]
|
||||||
addr = "127.0.0.1:7442"
|
addr = "127.0.0.1:8500"
|
||||||
|
|
||||||
[debug]
|
[debug]
|
||||||
database = false
|
database = true
|
||||||
print_routes = false
|
print_routes = false
|
||||||
|
|
||||||
[calling]
|
[calling]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user