diff --git a/pkg/models/clients.go b/pkg/models/clients.go index 8227c89..5eafc53 100644 --- a/pkg/models/clients.go +++ b/pkg/models/clients.go @@ -5,13 +5,14 @@ import "gorm.io/datatypes" type ThirdClient struct { BaseModel - Alias string `json:"alias" gorm:"uniqueIndex"` - Name string `json:"name"` - Description string `json:"description"` - Secret string `json:"secret"` - Urls datatypes.JSONSlice[string] `json:"urls"` - Callbacks datatypes.JSONSlice[string] `json:"callbacks"` - Sessions []AuthSession `json:"sessions" gorm:"foreignKey:ClientID"` - IsDraft bool `json:"is_draft"` - AccountID *uint `json:"account_id"` + Alias string `json:"alias" gorm:"uniqueIndex"` + Name string `json:"name"` + Description string `json:"description"` + Secret string `json:"secret"` + Urls datatypes.JSONSlice[string] `json:"urls"` + Callbacks datatypes.JSONSlice[string] `json:"callbacks"` + Sessions []AuthSession `json:"sessions" gorm:"foreignKey:ClientID"` + Notifications []Notification `json:"notifications" gorm:"foreignKey:SenderID"` + IsDraft bool `json:"is_draft"` + AccountID *uint `json:"account_id"` } diff --git a/pkg/server/notify_api.go b/pkg/server/notify_api.go new file mode 100644 index 0000000..a6d3d77 --- /dev/null +++ b/pkg/server/notify_api.go @@ -0,0 +1,38 @@ +package server + +import ( + "code.smartsheep.studio/hydrogen/passport/pkg/models" + "code.smartsheep.studio/hydrogen/passport/pkg/services" + "github.com/gofiber/fiber/v2" +) + +func notifyUser(c *fiber.Ctx) error { + var data struct { + ClientID string `json:"client_id" validate:"required"` + ClientSecret string `json:"client_secret" validate:"required"` + Subject string `json:"subject" validate:"required,max=1024"` + Content string `json:"content" validate:"required,max=3072"` + IsImportant bool `json:"is_important"` + UserID uint `json:"user_id" validate:"required"` + } + + if err := BindAndValidate(c, &data); err != nil { + return err + } + + client, err := services.GetThirdClientWithSecret(data.ClientID, data.ClientSecret) + if err != nil { + return fiber.NewError(fiber.StatusForbidden, err.Error()) + } + + var user models.Account + if user, err = services.GetAccount(data.UserID); err != nil { + return fiber.NewError(fiber.StatusNotFound, err.Error()) + } + + if err := services.NewNotification(client, user, data.Subject, data.Content, data.IsImportant); err != nil { + return fiber.NewError(fiber.StatusBadRequest, err.Error()) + } + + return c.SendStatus(fiber.StatusOK) +} diff --git a/pkg/server/startup.go b/pkg/server/startup.go index 5fa34af..b47c681 100644 --- a/pkg/server/startup.go +++ b/pkg/server/startup.go @@ -80,6 +80,11 @@ func NewServer() { api.Get("/auth/o/connect", auth, preConnect) api.Post("/auth/o/connect", auth, doConnect) + + developers := A.Group("/dev").Name("Developers API") + { + developers.Post("/notify", notifyUser) + } } A.Use("/", cache.New(cache.Config{ diff --git a/pkg/services/clients.go b/pkg/services/clients.go new file mode 100644 index 0000000..77343b2 --- /dev/null +++ b/pkg/services/clients.go @@ -0,0 +1,31 @@ +package services + +import ( + "code.smartsheep.studio/hydrogen/passport/pkg/database" + "code.smartsheep.studio/hydrogen/passport/pkg/models" + "fmt" +) + +func GetThirdClient(id string) (models.ThirdClient, error) { + var client models.ThirdClient + if err := database.C.Where(&models.ThirdClient{ + Alias: id, + }).First(&client).Error; err != nil { + return client, err + } + + return client, nil +} + +func GetThirdClientWithSecret(id, secret string) (models.ThirdClient, error) { + client, err := GetThirdClient(id) + if err != nil { + return client, err + } + + if client.Secret != secret { + return client, fmt.Errorf("invalid client secret") + } + + return client, nil +} diff --git a/pkg/services/notifications.go b/pkg/services/notifications.go new file mode 100644 index 0000000..a666764 --- /dev/null +++ b/pkg/services/notifications.go @@ -0,0 +1,25 @@ +package services + +import ( + "code.smartsheep.studio/hydrogen/passport/pkg/database" + "code.smartsheep.studio/hydrogen/passport/pkg/models" +) + +func NewNotification(user models.ThirdClient, target models.Account, subject, content string, important bool) error { + notification := models.Notification{ + Subject: subject, + Content: content, + IsImportant: important, + ReadAt: nil, + SenderID: &user.ID, + RecipientID: target.ID, + } + + if err := database.C.Save(¬ification).Error; err != nil { + return err + } + + // TODO Notify all the listeners + + return nil +}