mirror of
https://github.com/makayabou/asg-server.git
synced 2026-05-02 17:43:36 +02:00
[webhooks] add device endpoint
This commit is contained in:
parent
c0ce84e89f
commit
4d4f1e0bcd
43
api/mobile.http
Normal file
43
api/mobile.http
Normal file
@ -0,0 +1,43 @@
|
||||
@baseUrl={{$dotenv CLOUD__URL}}/api/mobile/v1
|
||||
@mobileToken={{$dotenv MOBILE__TOKEN}}
|
||||
@phone={{$dotenv PHONE}}
|
||||
|
||||
###
|
||||
POST {{baseUrl}}/device HTTP/1.1
|
||||
Authorization: Bearer 123456789
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"name": "Android Phone",
|
||||
"pushToken": "eTxx88nfSla87gZuJcW5mS:APA91bHGxVgSqqRtxwFHD1q9em5Oa6xSP4gO_OZRrqOoP1wjf_7UMfXKsc4uws6rWkqn73jYCc1owyATB1v61mqak4ntpqtmRkNtTey7NQXa0Wz3uQZBWY-Ecbn2rWG2VJRihOzXRId-"
|
||||
}
|
||||
|
||||
###
|
||||
GET {{baseUrl}}/message HTTP/1.1
|
||||
Authorization: Bearer {{mobileToken}}
|
||||
|
||||
###
|
||||
PATCH {{baseUrl}}/message HTTP/1.1
|
||||
Authorization: Bearer {{mobileToken}}
|
||||
Content-Type: application/json
|
||||
|
||||
[
|
||||
{
|
||||
"id": "2dcIAhcLg81cez7GE_Pdp",
|
||||
"state": "Failed",
|
||||
"recipients": [
|
||||
{
|
||||
"phoneNumber": "{{phone}}",
|
||||
"state": "Failed"
|
||||
}
|
||||
],
|
||||
"states": {
|
||||
"Processed": "2024-05-13T16:49:17.357+07:00",
|
||||
"Failed": "2024-05-13T16:49:17.357+07:00"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
###
|
||||
GET {{baseUrl}}/webhooks HTTP/1.1
|
||||
Authorization: Bearer {{mobileToken}}
|
||||
@ -9,16 +9,6 @@ GET {{baseUrl}}/health HTTP/1.1
|
||||
###
|
||||
GET {{baseUrl}}/api/3rdparty/v1/health HTTP/1.1
|
||||
|
||||
###
|
||||
POST {{baseUrl}}/api/mobile/v1/device HTTP/1.1
|
||||
Authorization: Bearer 123456789
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"name": "Android Phone",
|
||||
"pushToken": "eTxx88nfSla87gZuJcW5mS:APA91bHGxVgSqqRtxwFHD1q9em5Oa6xSP4gO_OZRrqOoP1wjf_7UMfXKsc4uws6rWkqn73jYCc1owyATB1v61mqak4ntpqtmRkNtTey7NQXa0Wz3uQZBWY-Ecbn2rWG2VJRihOzXRId-"
|
||||
}
|
||||
|
||||
###
|
||||
POST {{baseUrl}}/api/3rdparty/v1/message?skipPhoneValidation=false HTTP/1.1
|
||||
Content-Type: application/json
|
||||
@ -58,32 +48,6 @@ Authorization: Basic {{credentials}}
|
||||
GET {{baseUrl}}/api/3rdparty/v1/device HTTP/1.1
|
||||
Authorization: Basic {{credentials}}
|
||||
|
||||
###
|
||||
GET {{baseUrl}}/api/mobile/v1/message HTTP/1.1
|
||||
Authorization: Bearer {{mobileToken}}
|
||||
|
||||
###
|
||||
PATCH {{baseUrl}}/api/mobile/v1/message HTTP/1.1
|
||||
Authorization: Bearer {{mobileToken}}
|
||||
Content-Type: application/json
|
||||
|
||||
[
|
||||
{
|
||||
"id": "2dcIAhcLg81cez7GE_Pdp",
|
||||
"state": "Failed",
|
||||
"recipients": [
|
||||
{
|
||||
"phoneNumber": "{{phone}}",
|
||||
"state": "Failed"
|
||||
}
|
||||
],
|
||||
"states": {
|
||||
"Processed": "2024-05-13T16:49:17.357+07:00",
|
||||
"Failed": "2024-05-13T16:49:17.357+07:00"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
###
|
||||
POST {{baseUrl}}/api/upstream/v1/push HTTP/1.1
|
||||
Content-Type: application/json
|
||||
|
||||
220
api/swagger.json
220
api/swagger.json
@ -208,6 +208,150 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/3rdparty/webhooks": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"ApiAuth": []
|
||||
}
|
||||
],
|
||||
"description": "Returns list of registered webhooks",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"User",
|
||||
"Webhooks"
|
||||
],
|
||||
"summary": "List webhooks",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Webhook list",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/github_com_capcom6_sms-gateway_pkg_smsgateway.WebhookDTO"
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/smsgateway.ErrorResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal server error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/smsgateway.ErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"security": [
|
||||
{
|
||||
"ApiAuth": []
|
||||
}
|
||||
],
|
||||
"description": "Registers webhook. If webhook with same ID already exists, it will be replaced",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"User",
|
||||
"Webhooks"
|
||||
],
|
||||
"summary": "Register webhook",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Webhook",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/github_com_capcom6_sms-gateway_pkg_smsgateway.WebhookDTO"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "Created",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/github_com_capcom6_sms-gateway_pkg_smsgateway.WebhookDTO"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Invalid request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/smsgateway.ErrorResponse"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/smsgateway.ErrorResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal server error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/smsgateway.ErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/3rdparty/webhooks/{id}": {
|
||||
"delete": {
|
||||
"security": [
|
||||
{
|
||||
"ApiAuth": []
|
||||
}
|
||||
],
|
||||
"description": "Deletes webhook",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"User",
|
||||
"Webhooks"
|
||||
],
|
||||
"summary": "Delete webhook",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Webhook ID",
|
||||
"name": "id",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "Webhook deleted",
|
||||
"schema": {
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/smsgateway.ErrorResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal server error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/smsgateway.ErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/health": {
|
||||
"get": {
|
||||
"description": "Checks if service is healthy",
|
||||
@ -429,6 +573,47 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/mobile/v1/webhooks": {
|
||||
"get": {
|
||||
"security": [
|
||||
{
|
||||
"MobileToken": []
|
||||
}
|
||||
],
|
||||
"description": "Returns list of registered webhooks for device",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"Device",
|
||||
"Webhooks"
|
||||
],
|
||||
"summary": "List webhooks",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Webhook list",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/github_com_capcom6_sms-gateway_pkg_smsgateway.WebhookDTO"
|
||||
}
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/smsgateway.ErrorResponse"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal server error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/smsgateway.ErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/upstream/v1/push": {
|
||||
"post": {
|
||||
"description": "Enqueues notifications for sending to devices",
|
||||
@ -483,6 +668,41 @@
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"github_com_capcom6_sms-gateway_pkg_smsgateway.WebhookDTO": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"event",
|
||||
"url"
|
||||
],
|
||||
"properties": {
|
||||
"event": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/github_com_capcom6_sms-gateway_pkg_smsgateway.WebhookEvent"
|
||||
}
|
||||
],
|
||||
"example": "sms:received"
|
||||
},
|
||||
"id": {
|
||||
"type": "string",
|
||||
"maxLength": 36,
|
||||
"example": "123e4567-e89b-12d3-a456-426614174000"
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"example": "https://example.com/webhook"
|
||||
}
|
||||
}
|
||||
},
|
||||
"github_com_capcom6_sms-gateway_pkg_smsgateway.WebhookEvent": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"sms:received"
|
||||
],
|
||||
"x-enum-varnames": [
|
||||
"WebhookEventSmsReceived"
|
||||
]
|
||||
},
|
||||
"smsgateway.Device": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
142
api/swagger.yaml
142
api/swagger.yaml
@ -1,5 +1,28 @@
|
||||
basePath: /api
|
||||
definitions:
|
||||
github_com_capcom6_sms-gateway_pkg_smsgateway.WebhookDTO:
|
||||
properties:
|
||||
event:
|
||||
allOf:
|
||||
- $ref: '#/definitions/github_com_capcom6_sms-gateway_pkg_smsgateway.WebhookEvent'
|
||||
example: sms:received
|
||||
id:
|
||||
example: 123e4567-e89b-12d3-a456-426614174000
|
||||
maxLength: 36
|
||||
type: string
|
||||
url:
|
||||
example: https://example.com/webhook
|
||||
type: string
|
||||
required:
|
||||
- event
|
||||
- url
|
||||
type: object
|
||||
github_com_capcom6_sms-gateway_pkg_smsgateway.WebhookEvent:
|
||||
enum:
|
||||
- sms:received
|
||||
type: string
|
||||
x-enum-varnames:
|
||||
- WebhookEventSmsReceived
|
||||
smsgateway.Device:
|
||||
properties:
|
||||
createdAt:
|
||||
@ -402,6 +425,99 @@ paths:
|
||||
summary: Health check
|
||||
tags:
|
||||
- System
|
||||
/api/v1/3rdparty/webhooks:
|
||||
get:
|
||||
description: Returns list of registered webhooks
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: Webhook list
|
||||
schema:
|
||||
items:
|
||||
$ref: '#/definitions/github_com_capcom6_sms-gateway_pkg_smsgateway.WebhookDTO'
|
||||
type: array
|
||||
"401":
|
||||
description: Unauthorized
|
||||
schema:
|
||||
$ref: '#/definitions/smsgateway.ErrorResponse'
|
||||
"500":
|
||||
description: Internal server error
|
||||
schema:
|
||||
$ref: '#/definitions/smsgateway.ErrorResponse'
|
||||
security:
|
||||
- ApiAuth: []
|
||||
summary: List webhooks
|
||||
tags:
|
||||
- User
|
||||
- Webhooks
|
||||
post:
|
||||
consumes:
|
||||
- application/json
|
||||
description: Registers webhook. If webhook with same ID already exists, it will
|
||||
be replaced
|
||||
parameters:
|
||||
- description: Webhook
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/github_com_capcom6_sms-gateway_pkg_smsgateway.WebhookDTO'
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"201":
|
||||
description: Created
|
||||
schema:
|
||||
$ref: '#/definitions/github_com_capcom6_sms-gateway_pkg_smsgateway.WebhookDTO'
|
||||
"400":
|
||||
description: Invalid request
|
||||
schema:
|
||||
$ref: '#/definitions/smsgateway.ErrorResponse'
|
||||
"401":
|
||||
description: Unauthorized
|
||||
schema:
|
||||
$ref: '#/definitions/smsgateway.ErrorResponse'
|
||||
"500":
|
||||
description: Internal server error
|
||||
schema:
|
||||
$ref: '#/definitions/smsgateway.ErrorResponse'
|
||||
security:
|
||||
- ApiAuth: []
|
||||
summary: Register webhook
|
||||
tags:
|
||||
- User
|
||||
- Webhooks
|
||||
/api/v1/3rdparty/webhooks/{id}:
|
||||
delete:
|
||||
description: Deletes webhook
|
||||
parameters:
|
||||
- description: Webhook ID
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"204":
|
||||
description: Webhook deleted
|
||||
schema:
|
||||
type: object
|
||||
"401":
|
||||
description: Unauthorized
|
||||
schema:
|
||||
$ref: '#/definitions/smsgateway.ErrorResponse'
|
||||
"500":
|
||||
description: Internal server error
|
||||
schema:
|
||||
$ref: '#/definitions/smsgateway.ErrorResponse'
|
||||
security:
|
||||
- ApiAuth: []
|
||||
summary: Delete webhook
|
||||
tags:
|
||||
- User
|
||||
- Webhooks
|
||||
/health:
|
||||
get:
|
||||
description: Checks if service is healthy
|
||||
@ -544,6 +660,32 @@ paths:
|
||||
tags:
|
||||
- Device
|
||||
- Messages
|
||||
/mobile/v1/webhooks:
|
||||
get:
|
||||
description: Returns list of registered webhooks for device
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: Webhook list
|
||||
schema:
|
||||
items:
|
||||
$ref: '#/definitions/github_com_capcom6_sms-gateway_pkg_smsgateway.WebhookDTO'
|
||||
type: array
|
||||
"401":
|
||||
description: Unauthorized
|
||||
schema:
|
||||
$ref: '#/definitions/smsgateway.ErrorResponse'
|
||||
"500":
|
||||
description: Internal server error
|
||||
schema:
|
||||
$ref: '#/definitions/smsgateway.ErrorResponse'
|
||||
security:
|
||||
- MobileToken: []
|
||||
summary: List webhooks
|
||||
tags:
|
||||
- Device
|
||||
- Webhooks
|
||||
/upstream/v1/push:
|
||||
post:
|
||||
consumes:
|
||||
|
||||
@ -6,10 +6,10 @@ import (
|
||||
|
||||
"github.com/android-sms-gateway/client-go/smsgateway"
|
||||
"github.com/capcom6/sms-gateway/internal/sms-gateway/handlers/base"
|
||||
"github.com/capcom6/sms-gateway/internal/sms-gateway/handlers/webhooks"
|
||||
"github.com/capcom6/sms-gateway/internal/sms-gateway/models"
|
||||
"github.com/capcom6/sms-gateway/internal/sms-gateway/modules/auth"
|
||||
"github.com/capcom6/sms-gateway/internal/sms-gateway/modules/messages"
|
||||
"github.com/capcom6/sms-gateway/internal/sms-gateway/modules/webhooks"
|
||||
"github.com/capcom6/sms-gateway/internal/sms-gateway/repositories"
|
||||
"github.com/capcom6/sms-gateway/internal/sms-gateway/services"
|
||||
"github.com/capcom6/sms-gateway/pkg/types"
|
||||
@ -28,7 +28,7 @@ type ThirdPartyHandlerParams struct {
|
||||
fx.In
|
||||
|
||||
HealthHandler *healthHandler
|
||||
WebhooksHandler *webhooks.Handler
|
||||
WebhooksHandler *webhooks.ThirdPartyController
|
||||
|
||||
AuthSvc *auth.Service
|
||||
MessagesSvc *messages.Service
|
||||
@ -42,7 +42,7 @@ type thirdPartyHandler struct {
|
||||
base.Handler
|
||||
|
||||
healthHandler *healthHandler
|
||||
webhooksHandler *webhooks.Handler
|
||||
webhooksHandler *webhooks.ThirdPartyController
|
||||
|
||||
authSvc *auth.Service
|
||||
messagesSvc *messages.Service
|
||||
|
||||
@ -8,6 +8,7 @@ import (
|
||||
"github.com/android-sms-gateway/client-go/smsgateway"
|
||||
"github.com/capcom6/go-infra-fx/http/apikey"
|
||||
"github.com/capcom6/sms-gateway/internal/sms-gateway/handlers/base"
|
||||
"github.com/capcom6/sms-gateway/internal/sms-gateway/handlers/webhooks"
|
||||
"github.com/capcom6/sms-gateway/internal/sms-gateway/models"
|
||||
"github.com/capcom6/sms-gateway/internal/sms-gateway/modules/auth"
|
||||
"github.com/capcom6/sms-gateway/internal/sms-gateway/modules/messages"
|
||||
@ -26,6 +27,8 @@ type mobileHandler struct {
|
||||
authSvc *auth.Service
|
||||
messagesSvc *messages.Service
|
||||
|
||||
webhooksCtrl *webhooks.MobileController
|
||||
|
||||
idGen func() string
|
||||
}
|
||||
|
||||
@ -156,20 +159,6 @@ func (h *mobileHandler) patchMessage(device models.Device, c *fiber.Ctx) error {
|
||||
return c.SendStatus(fiber.StatusNoContent)
|
||||
}
|
||||
|
||||
func (h *mobileHandler) authorize(handler func(models.Device, *fiber.Ctx) error) fiber.Handler {
|
||||
return func(c *fiber.Ctx) error {
|
||||
token := c.Locals("token").(string)
|
||||
|
||||
device, err := h.authSvc.AuthorizeDevice(token)
|
||||
if err != nil {
|
||||
h.Logger.Error("Can't authorize device", zap.Error(err))
|
||||
return fiber.ErrUnauthorized
|
||||
}
|
||||
|
||||
return handler(device, c)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *mobileHandler) Register(router fiber.Router) {
|
||||
router = router.Group("/mobile/v1")
|
||||
|
||||
@ -184,15 +173,29 @@ func (h *mobileHandler) Register(router fiber.Router) {
|
||||
Authorizer: func(token string) bool {
|
||||
return len(token) > 0
|
||||
},
|
||||
}))
|
||||
}), func(c *fiber.Ctx) error {
|
||||
token := c.Locals("token").(string)
|
||||
|
||||
router.Patch("/device", h.authorize(h.patchDevice))
|
||||
device, err := h.authSvc.AuthorizeDevice(token)
|
||||
if err != nil {
|
||||
h.Logger.Error("Can't authorize device", zap.Error(err))
|
||||
return fiber.ErrUnauthorized
|
||||
}
|
||||
|
||||
router.Get("/message", h.authorize(h.getMessage))
|
||||
router.Patch("/message", h.authorize(h.patchMessage))
|
||||
c.Locals("device", device)
|
||||
|
||||
return c.Next()
|
||||
})
|
||||
|
||||
router.Patch("/device", auth.WithDevice(h.patchDevice))
|
||||
|
||||
router.Get("/message", auth.WithDevice(h.getMessage))
|
||||
router.Patch("/message", auth.WithDevice(h.patchMessage))
|
||||
|
||||
h.webhooksCtrl.Register(router.Group("/webhooks"))
|
||||
}
|
||||
|
||||
type MobileHandlerParams struct {
|
||||
type mobileHandlerParams struct {
|
||||
fx.In
|
||||
|
||||
Logger *zap.Logger
|
||||
@ -200,15 +203,18 @@ type MobileHandlerParams struct {
|
||||
|
||||
AuthSvc *auth.Service
|
||||
MessagesSvc *messages.Service
|
||||
|
||||
WebhooksCtrl *webhooks.MobileController
|
||||
}
|
||||
|
||||
func newMobileHandler(params MobileHandlerParams) *mobileHandler {
|
||||
func newMobileHandler(params mobileHandlerParams) *mobileHandler {
|
||||
idGen, _ := nanoid.Standard(21)
|
||||
|
||||
return &mobileHandler{
|
||||
Handler: base.Handler{Logger: params.Logger, Validator: params.Validator},
|
||||
authSvc: params.AuthSvc,
|
||||
messagesSvc: params.MessagesSvc,
|
||||
idGen: idGen,
|
||||
Handler: base.Handler{Logger: params.Logger, Validator: params.Validator},
|
||||
authSvc: params.AuthSvc,
|
||||
messagesSvc: params.MessagesSvc,
|
||||
webhooksCtrl: params.WebhooksCtrl,
|
||||
idGen: idGen,
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ package handlers
|
||||
|
||||
import (
|
||||
"github.com/capcom6/go-infra-fx/http"
|
||||
"github.com/capcom6/sms-gateway/internal/sms-gateway/handlers/webhooks"
|
||||
"go.uber.org/fx"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
@ -19,6 +20,8 @@ var Module = fx.Module(
|
||||
),
|
||||
fx.Provide(
|
||||
newHealthHandler,
|
||||
webhooks.NewThirdPartyController,
|
||||
webhooks.NewMobileController,
|
||||
fx.Private,
|
||||
),
|
||||
)
|
||||
|
||||
116
internal/sms-gateway/handlers/webhooks/3rdparty.go
Normal file
116
internal/sms-gateway/handlers/webhooks/3rdparty.go
Normal file
@ -0,0 +1,116 @@
|
||||
package webhooks
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/capcom6/sms-gateway/internal/sms-gateway/handlers/base"
|
||||
"github.com/capcom6/sms-gateway/internal/sms-gateway/models"
|
||||
"github.com/capcom6/sms-gateway/internal/sms-gateway/modules/auth"
|
||||
"github.com/capcom6/sms-gateway/internal/sms-gateway/modules/webhooks"
|
||||
"github.com/capcom6/sms-gateway/pkg/smsgateway"
|
||||
"github.com/go-playground/validator/v10"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"go.uber.org/fx"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type thirdPartyControllerParams struct {
|
||||
fx.In
|
||||
|
||||
WebhooksSvc *webhooks.Service
|
||||
|
||||
Validator *validator.Validate
|
||||
Logger *zap.Logger
|
||||
}
|
||||
|
||||
type ThirdPartyController struct {
|
||||
base.Handler
|
||||
|
||||
webhooksSvc *webhooks.Service
|
||||
}
|
||||
|
||||
// @Summary List webhooks
|
||||
// @Description Returns list of registered webhooks
|
||||
// @Security ApiAuth
|
||||
// @Tags User, Webhooks
|
||||
// @Produce json
|
||||
// @Success 200 {object} []smsgateway.WebhookDTO "Webhook list"
|
||||
// @Failure 401 {object} smsgateway.ErrorResponse "Unauthorized"
|
||||
// @Failure 500 {object} smsgateway.ErrorResponse "Internal server error"
|
||||
// @Router /api/v1/3rdparty/webhooks [get]
|
||||
//
|
||||
// List webhooks
|
||||
func (h *ThirdPartyController) get(user models.User, c *fiber.Ctx) error {
|
||||
items, err := h.webhooksSvc.Select(user.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't select webhooks: %w", err)
|
||||
}
|
||||
|
||||
return c.JSON(items)
|
||||
}
|
||||
|
||||
// @Summary Register webhook
|
||||
// @Description Registers webhook. If webhook with same ID already exists, it will be replaced
|
||||
// @Security ApiAuth
|
||||
// @Tags User, Webhooks
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body smsgateway.WebhookDTO true "Webhook"
|
||||
// @Success 201 {object} smsgateway.WebhookDTO "Created"
|
||||
// @Failure 400 {object} smsgateway.ErrorResponse "Invalid request"
|
||||
// @Failure 401 {object} smsgateway.ErrorResponse "Unauthorized"
|
||||
// @Failure 500 {object} smsgateway.ErrorResponse "Internal server error"
|
||||
// @Router /api/v1/3rdparty/webhooks [post]
|
||||
//
|
||||
// Register webhook
|
||||
func (h *ThirdPartyController) post(user models.User, c *fiber.Ctx) error {
|
||||
dto := &smsgateway.WebhookDTO{}
|
||||
|
||||
if err := h.BodyParserValidator(c, dto); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := h.webhooksSvc.Replace(user.ID, dto); err != nil {
|
||||
return fmt.Errorf("can't write webhook: %w", err)
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusCreated).JSON(dto)
|
||||
}
|
||||
|
||||
// @Summary Delete webhook
|
||||
// @Description Deletes webhook
|
||||
// @Security ApiAuth
|
||||
// @Tags User, Webhooks
|
||||
// @Produce json
|
||||
// @Param id path string true "Webhook ID"
|
||||
// @Success 204 {object} object "Webhook deleted"
|
||||
// @Failure 401 {object} smsgateway.ErrorResponse "Unauthorized"
|
||||
// @Failure 500 {object} smsgateway.ErrorResponse "Internal server error"
|
||||
// @Router /api/v1/3rdparty/webhooks/{id} [delete]
|
||||
//
|
||||
// Delete webhook
|
||||
func (h *ThirdPartyController) delete(user models.User, c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
|
||||
if err := h.webhooksSvc.Delete(user.ID, webhooks.WithExtID(id)); err != nil {
|
||||
return fmt.Errorf("can't delete webhook: %w", err)
|
||||
}
|
||||
|
||||
return c.SendStatus(fiber.StatusNoContent)
|
||||
}
|
||||
|
||||
func (h *ThirdPartyController) Register(router fiber.Router) {
|
||||
router.Get("/", auth.WithUser(h.get))
|
||||
router.Post("/", auth.WithUser(h.post))
|
||||
router.Delete("/:id", auth.WithUser(h.delete))
|
||||
}
|
||||
|
||||
func NewThirdPartyController(params thirdPartyControllerParams) *ThirdPartyController {
|
||||
return &ThirdPartyController{
|
||||
Handler: base.Handler{
|
||||
Logger: params.Logger.Named("controller"),
|
||||
Validator: params.Validator,
|
||||
},
|
||||
webhooksSvc: params.WebhooksSvc,
|
||||
}
|
||||
}
|
||||
61
internal/sms-gateway/handlers/webhooks/mobile.go
Normal file
61
internal/sms-gateway/handlers/webhooks/mobile.go
Normal file
@ -0,0 +1,61 @@
|
||||
package webhooks
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/capcom6/sms-gateway/internal/sms-gateway/handlers/base"
|
||||
"github.com/capcom6/sms-gateway/internal/sms-gateway/models"
|
||||
"github.com/capcom6/sms-gateway/internal/sms-gateway/modules/auth"
|
||||
"github.com/capcom6/sms-gateway/internal/sms-gateway/modules/webhooks"
|
||||
_ "github.com/capcom6/sms-gateway/pkg/smsgateway"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"go.uber.org/fx"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type mobileControllerParams struct {
|
||||
fx.In
|
||||
|
||||
WebhooksServices *webhooks.Service
|
||||
|
||||
Logger *zap.Logger
|
||||
}
|
||||
|
||||
type MobileController struct {
|
||||
base.Handler
|
||||
|
||||
webhooksSvc *webhooks.Service
|
||||
}
|
||||
|
||||
// @Summary List webhooks
|
||||
// @Description Returns list of registered webhooks for device
|
||||
// @Security MobileToken
|
||||
// @Tags Device, Webhooks
|
||||
// @Produce json
|
||||
// @Success 200 {object} []smsgateway.WebhookDTO "Webhook list"
|
||||
// @Failure 401 {object} smsgateway.ErrorResponse "Unauthorized"
|
||||
// @Failure 500 {object} smsgateway.ErrorResponse "Internal server error"
|
||||
// @Router /mobile/v1/webhooks [get]
|
||||
//
|
||||
// List webhooks
|
||||
func (h *MobileController) get(device models.Device, c *fiber.Ctx) error {
|
||||
items, err := h.webhooksSvc.Select(device.UserID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't select webhooks: %w", err)
|
||||
}
|
||||
|
||||
return c.JSON(items)
|
||||
}
|
||||
|
||||
func (h *MobileController) Register(router fiber.Router) {
|
||||
router.Get("/", auth.WithDevice(h.get))
|
||||
}
|
||||
|
||||
func NewMobileController(params mobileControllerParams) *MobileController {
|
||||
return &MobileController{
|
||||
Handler: base.Handler{
|
||||
Logger: params.Logger.Named("mobile"),
|
||||
},
|
||||
webhooksSvc: params.WebhooksServices,
|
||||
}
|
||||
}
|
||||
@ -10,3 +10,9 @@ func WithUser(handler func(models.User, *fiber.Ctx) error) fiber.Handler {
|
||||
return handler(c.Locals("user").(models.User), c)
|
||||
}
|
||||
}
|
||||
|
||||
func WithDevice(handler func(models.Device, *fiber.Ctx) error) fiber.Handler {
|
||||
return func(c *fiber.Ctx) error {
|
||||
return handler(c.Locals("device").(models.Device), c)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
package webhooks
|
||||
|
||||
func webhookToDTO(model *Webhook) WebhookDTO {
|
||||
return WebhookDTO{
|
||||
import "github.com/capcom6/sms-gateway/pkg/smsgateway"
|
||||
|
||||
func webhookToDTO(model *Webhook) smsgateway.WebhookDTO {
|
||||
return smsgateway.WebhookDTO{
|
||||
ID: model.ExtID,
|
||||
URL: model.URL,
|
||||
Event: model.Event,
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
package webhooks
|
||||
|
||||
type WebhookDTO struct {
|
||||
ID string `json:"id" validate:"max=36" example:"123e4567-e89b-12d3-a456-426614174000"`
|
||||
URL string `json:"url" validate:"required,http_url" example:"https://example.com/webhook"`
|
||||
Event Event `json:"event" validate:"required" example:"sms:received"`
|
||||
}
|
||||
@ -1,80 +0,0 @@
|
||||
package webhooks
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/capcom6/sms-gateway/internal/sms-gateway/handlers/base"
|
||||
"github.com/capcom6/sms-gateway/internal/sms-gateway/models"
|
||||
"github.com/capcom6/sms-gateway/internal/sms-gateway/modules/auth"
|
||||
"github.com/go-playground/validator/v10"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"go.uber.org/fx"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type handlerParams struct {
|
||||
fx.In
|
||||
|
||||
WebhooksSvc *Service
|
||||
|
||||
Validator *validator.Validate
|
||||
Logger *zap.Logger
|
||||
}
|
||||
|
||||
type Handler struct {
|
||||
base.Handler
|
||||
|
||||
webhooksSvc *Service
|
||||
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
func (h *Handler) get(user models.User, c *fiber.Ctx) error {
|
||||
items, err := h.webhooksSvc.Select(user.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't select webhooks: %w", err)
|
||||
}
|
||||
|
||||
return c.JSON(items)
|
||||
}
|
||||
|
||||
func (h *Handler) post(user models.User, c *fiber.Ctx) error {
|
||||
dto := WebhookDTO{}
|
||||
|
||||
if err := h.BodyParserValidator(c, &dto); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := h.webhooksSvc.Replace(user.ID, dto); err != nil {
|
||||
return fmt.Errorf("can't write webhook: %w", err)
|
||||
}
|
||||
|
||||
return c.SendStatus(fiber.StatusCreated)
|
||||
}
|
||||
|
||||
func (h *Handler) delete(user models.User, c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
|
||||
if err := h.webhooksSvc.Delete(user.ID, WithExtID(id)); err != nil {
|
||||
return fmt.Errorf("can't delete webhook: %w", err)
|
||||
}
|
||||
|
||||
return c.SendStatus(fiber.StatusNoContent)
|
||||
}
|
||||
|
||||
func (h *Handler) Register(router fiber.Router) {
|
||||
router.Get("/", auth.WithUser(h.get))
|
||||
router.Post("/", auth.WithUser(h.post))
|
||||
router.Delete("/:id", auth.WithUser(h.delete))
|
||||
}
|
||||
|
||||
func NewHandler(params handlerParams) *Handler {
|
||||
return &Handler{
|
||||
Handler: base.Handler{
|
||||
Logger: params.Logger.Named("webhooks"),
|
||||
Validator: params.Validator,
|
||||
},
|
||||
webhooksSvc: params.WebhooksSvc,
|
||||
logger: params.Logger,
|
||||
}
|
||||
}
|
||||
@ -2,6 +2,7 @@ package webhooks
|
||||
|
||||
import (
|
||||
"github.com/capcom6/sms-gateway/internal/sms-gateway/models"
|
||||
"github.com/capcom6/sms-gateway/pkg/smsgateway"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
@ -10,8 +11,8 @@ type Webhook struct {
|
||||
ExtID string `json:"id" gorm:"not null;type:varchar(36);uniqueIndex:unq_webhooks_user_extid,priority:2"`
|
||||
UserID string `json:"-" gorm:"<-:create;not null;type:varchar(32);uniqueIndex:unq_webhooks_user_extid,priority:1"`
|
||||
|
||||
URL string `json:"url" validate:"required,http_url" gorm:"not null;type:varchar(256)"`
|
||||
Event Event `json:"event" gorm:"not null;type:varchar(32)"`
|
||||
URL string `json:"url" validate:"required,http_url" gorm:"not null;type:varchar(256)"`
|
||||
Event smsgateway.WebhookEvent `json:"event" gorm:"not null;type:varchar(32)"`
|
||||
|
||||
User models.User `gorm:"foreignKey:UserID;constraint:OnDelete:CASCADE"`
|
||||
|
||||
|
||||
@ -14,7 +14,6 @@ var Module = fx.Module(
|
||||
fx.Provide(NewRepository, fx.Private),
|
||||
fx.Provide(
|
||||
NewService,
|
||||
NewHandler,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/capcom6/go-helpers/slices"
|
||||
"github.com/capcom6/sms-gateway/internal/sms-gateway/modules/db"
|
||||
"github.com/capcom6/sms-gateway/pkg/smsgateway"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
@ -20,7 +21,7 @@ func NewService(idgen db.IDGen, webhooks *Repository) *Service {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) Select(userID string, filters ...SelectFilter) ([]WebhookDTO, error) {
|
||||
func (s *Service) Select(userID string, filters ...SelectFilter) ([]smsgateway.WebhookDTO, error) {
|
||||
filters = append(filters, WithUserID(userID))
|
||||
|
||||
items, err := s.webhooks.Select(filters...)
|
||||
@ -31,7 +32,7 @@ func (s *Service) Select(userID string, filters ...SelectFilter) ([]WebhookDTO,
|
||||
return slices.Map(items, webhookToDTO), nil
|
||||
}
|
||||
|
||||
func (s *Service) Replace(userID string, webhook WebhookDTO) error {
|
||||
func (s *Service) Replace(userID string, webhook *smsgateway.WebhookDTO) error {
|
||||
if webhook.ID == "" {
|
||||
webhook.ID = s.idgen()
|
||||
}
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
package webhooks
|
||||
|
||||
type Event string
|
||||
|
||||
const (
|
||||
EventSmsReceived Event = "sms:received"
|
||||
)
|
||||
7
pkg/smsgateway/dto.go
Normal file
7
pkg/smsgateway/dto.go
Normal file
@ -0,0 +1,7 @@
|
||||
package smsgateway
|
||||
|
||||
type WebhookDTO struct {
|
||||
ID string `json:"id" validate:"max=36" example:"123e4567-e89b-12d3-a456-426614174000"`
|
||||
URL string `json:"url" validate:"required,http_url" example:"https://example.com/webhook"`
|
||||
Event WebhookEvent `json:"event" validate:"required" example:"sms:received"`
|
||||
}
|
||||
7
pkg/smsgateway/types.go
Normal file
7
pkg/smsgateway/types.go
Normal file
@ -0,0 +1,7 @@
|
||||
package smsgateway
|
||||
|
||||
type WebhookEvent string
|
||||
|
||||
const (
|
||||
WebhookEventSmsReceived WebhookEvent = "sms:received"
|
||||
)
|
||||
Loading…
x
Reference in New Issue
Block a user