mirror of
https://github.com/makayabou/asg-server.git
synced 2026-05-02 17:43:36 +02:00
Added: mobile endpoints without patch
This commit is contained in:
parent
159523154a
commit
cad991d442
@ -4,6 +4,7 @@ import (
|
||||
"log"
|
||||
|
||||
"bitbucket.org/capcom6/smsgatewaybackend/internal/config"
|
||||
_ "bitbucket.org/capcom6/smsgatewaybackend/internal/smsgateway"
|
||||
microbase "bitbucket.org/soft-c/gomicrobase"
|
||||
)
|
||||
|
||||
|
||||
11
go.mod
11
go.mod
@ -3,22 +3,24 @@ module bitbucket.org/capcom6/smsgatewaybackend
|
||||
go 1.18
|
||||
|
||||
require (
|
||||
bitbucket.org/soft-c/gomicrobase v1.1.2-0.20221004142125-98b1dad322bc
|
||||
bitbucket.org/soft-c/gohelpers v1.0.3-0.20221006072847-aee2524b5192
|
||||
bitbucket.org/soft-c/gomicrobase v1.1.2-0.20221006080527-7eeddcd13770
|
||||
github.com/go-playground/validator/v10 v10.11.0
|
||||
github.com/gofiber/fiber/v2 v2.38.1
|
||||
github.com/jaevor/go-nanoid v1.3.0
|
||||
github.com/joho/godotenv v1.4.0
|
||||
gorm.io/gorm v1.23.8
|
||||
)
|
||||
|
||||
require (
|
||||
bitbucket.org/soft-c/gohelpers v1.0.2 // indirect
|
||||
github.com/andybalholm/brotli v1.0.4 // indirect
|
||||
github.com/ansrivas/fiberprometheus/v2 v2.4.1 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/go-playground/locales v0.14.0 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.0 // indirect
|
||||
github.com/go-playground/validator/v10 v10.11.0 // indirect
|
||||
github.com/go-sql-driver/mysql v1.6.0 // indirect
|
||||
github.com/gofiber/adaptor/v2 v2.1.27 // indirect
|
||||
github.com/gofiber/fiber/v2 v2.38.1 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
@ -38,5 +40,4 @@ require (
|
||||
google.golang.org/protobuf v1.28.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
gorm.io/driver/mysql v1.3.6 // indirect
|
||||
gorm.io/gorm v1.23.8 // indirect
|
||||
)
|
||||
|
||||
22
go.sum
22
go.sum
@ -1,9 +1,7 @@
|
||||
bitbucket.org/soft-c/gohelpers v1.0.2 h1:WP6g2V5jlyoY8ksz0N9VAjcbZeuOAupZSLCEj1kab+s=
|
||||
bitbucket.org/soft-c/gohelpers v1.0.2/go.mod h1:ltWoO1ZiJoATBjBw6AnV3Qf91qrp2IQCmYZlL/CwKSs=
|
||||
bitbucket.org/soft-c/gomicrobase v1.1.1 h1:UMgeksfIgR4st2sfITl8GMYwn7HQVoizoygb/yYQNeM=
|
||||
bitbucket.org/soft-c/gomicrobase v1.1.1/go.mod h1:+Jh2pL0WUtAGJu1twMdQCnxeRXjSbrra4RecZMoe/bw=
|
||||
bitbucket.org/soft-c/gomicrobase v1.1.2-0.20221004142125-98b1dad322bc h1:Bsq8Uuf6rkg5BYnG9usB0hmCQq5JKAvN2GWW9JhFMUU=
|
||||
bitbucket.org/soft-c/gomicrobase v1.1.2-0.20221004142125-98b1dad322bc/go.mod h1:Pvv07ulIXfDG5us/ZG5Of7vvjY+tq3fkcrY/MmJUEiE=
|
||||
bitbucket.org/soft-c/gohelpers v1.0.3-0.20221006072847-aee2524b5192 h1:Mmoyu4csqhWcxCQc0qhSyd9dIt1BCxJ1OYOZA4D/S2U=
|
||||
bitbucket.org/soft-c/gohelpers v1.0.3-0.20221006072847-aee2524b5192/go.mod h1:AlZzQ1xftfS8rWSwjwTj3/MPMFFfgfNCP3b7xLoEeKM=
|
||||
bitbucket.org/soft-c/gomicrobase v1.1.2-0.20221006080527-7eeddcd13770 h1:IAEOe5Uv9+zQEaOuT8eHJPUfS64Nc0I9ufq7afFXKUk=
|
||||
bitbucket.org/soft-c/gomicrobase v1.1.2-0.20221006080527-7eeddcd13770/go.mod h1:Pvv07ulIXfDG5us/ZG5Of7vvjY+tq3fkcrY/MmJUEiE=
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||
@ -95,8 +93,6 @@ github.com/gofiber/adaptor/v2 v2.1.25/go.mod h1:gOxtwMVqUStB5goAYtKd+hSvGupdd+aR
|
||||
github.com/gofiber/adaptor/v2 v2.1.27 h1:I3Xjn1qaH6W09shPi8F/kz98AncwbVYWFBV4niBBC0Q=
|
||||
github.com/gofiber/adaptor/v2 v2.1.27/go.mod h1:xcc+UqppJ+XfYVcqxp2fHyoqKctQxxvZ/IyUybNSIlQ=
|
||||
github.com/gofiber/fiber/v2 v2.36.0/go.mod h1:tgCr+lierLwLoVHHO/jn3Niannv34WRkQETU8wiL9fQ=
|
||||
github.com/gofiber/fiber/v2 v2.37.0 h1:KVboSQ7e0wDbSFXNjXKqoigwp9HYUqgWn4uGFaUO1P8=
|
||||
github.com/gofiber/fiber/v2 v2.37.0/go.mod h1:xm3pDGlfE1xqVKb77iH8weLU0FFoTeWeK3nbiYM2Nh0=
|
||||
github.com/gofiber/fiber/v2 v2.37.1/go.mod h1:j3UslgQeJQP3mNhBxHnLLE8TPqA1Fd/lrl4gD25rRUY=
|
||||
github.com/gofiber/fiber/v2 v2.38.1 h1:GEQ/Yt3Wsf2a30iTqtLXlBYJZso0JXPovt/tmj5H9jU=
|
||||
github.com/gofiber/fiber/v2 v2.38.1/go.mod h1:t0NlbaXzuGH7I+7M4paE848fNWInZ7mfxI/Er1fTth8=
|
||||
@ -140,6 +136,7 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
@ -156,6 +153,8 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/jaevor/go-nanoid v1.3.0 h1:nD+iepesZS6pr3uOVf20vR9GdGgJW1HPaR46gtrxzkg=
|
||||
github.com/jaevor/go-nanoid v1.3.0/go.mod h1:SI+jFaPuddYkqkVQoNGHs81navCtH388TcrH0RqFKgY=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
@ -174,8 +173,6 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V
|
||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY=
|
||||
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
||||
github.com/klauspost/compress v1.15.11 h1:Lcadnb3RKGin4FYM/orgq0qde+nc15E5Cbqg4B9Sx9c=
|
||||
github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
@ -246,12 +243,11 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasthttp v1.38.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I=
|
||||
github.com/valyala/fasthttp v1.39.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I=
|
||||
github.com/valyala/fasthttp v1.40.0 h1:CRq/00MfruPGFLTQKY8b+8SfdK60TxNztjRMnH0t1Yc=
|
||||
github.com/valyala/fasthttp v1.40.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I=
|
||||
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
|
||||
@ -391,8 +387,6 @@ golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220907062415-87db552b00fd h1:AZeIEzg+8RCELJYq8w+ODLVxFgLMMigSwO/ffKPEd9U=
|
||||
golang.org/x/sys v0.0.0-20220907062415-87db552b00fd/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec h1:BkDtF2Ih9xZ7le9ndzTA7KJow28VbQW3odyk/8drmuI=
|
||||
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
|
||||
12
internal/smsgateway/app.go
Normal file
12
internal/smsgateway/app.go
Normal file
@ -0,0 +1,12 @@
|
||||
package smsgateway
|
||||
|
||||
import (
|
||||
"bitbucket.org/capcom6/smsgatewaybackend/internal/smsgateway/handlers"
|
||||
"bitbucket.org/capcom6/smsgatewaybackend/internal/smsgateway/models"
|
||||
microbase "bitbucket.org/soft-c/gomicrobase"
|
||||
)
|
||||
|
||||
func init() {
|
||||
microbase.RegisterMigration(models.Migrate)
|
||||
microbase.RegisterHandlers(handlers.Register)
|
||||
}
|
||||
29
internal/smsgateway/handlers/3rdparty.go
Normal file
29
internal/smsgateway/handlers/3rdparty.go
Normal file
@ -0,0 +1,29 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
microbase "bitbucket.org/soft-c/gomicrobase"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v2/middleware/basicauth"
|
||||
)
|
||||
|
||||
type thirdPartyHandler struct {
|
||||
microbase.Handler
|
||||
}
|
||||
|
||||
func (h *thirdPartyHandler) postMessage(c *fiber.Ctx) error {
|
||||
return fiber.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (h *thirdPartyHandler) register(router fiber.Router) {
|
||||
router.Use(basicauth.New(basicauth.Config{
|
||||
Authorizer: func(username string, password string) bool {
|
||||
return len(username) > 0 && len(password) > 0
|
||||
},
|
||||
}))
|
||||
|
||||
router.Post("/message", h.postMessage)
|
||||
}
|
||||
|
||||
func newThirdPartyHandler() *thirdPartyHandler {
|
||||
return &thirdPartyHandler{}
|
||||
}
|
||||
24
internal/smsgateway/handlers/handlers.go
Normal file
24
internal/smsgateway/handlers/handlers.go
Normal file
@ -0,0 +1,24 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"bitbucket.org/capcom6/smsgatewaybackend/internal/smsgateway/repositories"
|
||||
"bitbucket.org/capcom6/smsgatewaybackend/internal/smsgateway/services"
|
||||
"github.com/go-playground/validator/v10"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func Register(router fiber.Router, db *gorm.DB) error {
|
||||
users := repositories.NewUsersRepository(db)
|
||||
devices := repositories.NewDevicesRepository(db)
|
||||
messages := repositories.NewMessagesRepository(db)
|
||||
|
||||
validator := validator.New()
|
||||
authSvc := services.NewAuthService(users, devices)
|
||||
messagesSvc := services.NewMessagesService(messages)
|
||||
|
||||
newMobileHandler(validator, authSvc, messagesSvc).register(router.Group("/mobile/v1"))
|
||||
newThirdPartyHandler().register(router.Group("/3rdparty/v1"))
|
||||
|
||||
return nil
|
||||
}
|
||||
16
internal/smsgateway/handlers/log.go
Normal file
16
internal/smsgateway/handlers/log.go
Normal file
@ -0,0 +1,16 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
l "log"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type empty struct{}
|
||||
|
||||
var packageName = strings.Split(reflect.TypeOf(empty{}).PkgPath(), "/")
|
||||
var logPrefix = fmt.Sprintf("[%s] ", packageName[len(packageName)-1])
|
||||
var log = l.New(os.Stdout, logPrefix, l.Ldate|l.Ltime|l.Lshortfile)
|
||||
var errorLog = l.New(os.Stderr, logPrefix, l.Ldate|l.Ltime|l.Lshortfile)
|
||||
113
internal/smsgateway/handlers/mobile.go
Normal file
113
internal/smsgateway/handlers/mobile.go
Normal file
@ -0,0 +1,113 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"bitbucket.org/capcom6/smsgatewaybackend/internal/smsgateway/models"
|
||||
"bitbucket.org/capcom6/smsgatewaybackend/internal/smsgateway/services"
|
||||
"bitbucket.org/capcom6/smsgatewaybackend/pkg/smsgateway"
|
||||
"bitbucket.org/soft-c/gohelpers/pkg/fiber/middleware/apikey"
|
||||
microbase "bitbucket.org/soft-c/gomicrobase"
|
||||
"github.com/go-playground/validator/v10"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/jaevor/go-nanoid"
|
||||
)
|
||||
|
||||
type mobileHandler struct {
|
||||
microbase.Handler
|
||||
|
||||
authSvc *services.AuthService
|
||||
messagesSvc *services.MessagesService
|
||||
|
||||
idGen func() string
|
||||
}
|
||||
|
||||
func (h *mobileHandler) postRegister(c *fiber.Ctx) error {
|
||||
req := smsgateway.MobileRegisterRequest{}
|
||||
|
||||
if err := h.BodyParserValidator(c, &req); err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
|
||||
id := h.idGen()
|
||||
login := strings.ToUpper(id[:6])
|
||||
password := strings.ToLower(id[7:])
|
||||
|
||||
user, err := h.authSvc.RegisterUser(login, password)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't create user: %w", err)
|
||||
}
|
||||
|
||||
device, err := h.authSvc.RegisterDevice(user.ID, req.Name, req.PushToken)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't register device: %w", err)
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusCreated).JSON(smsgateway.MobileRegisterResponse{
|
||||
Id: device.ID,
|
||||
Token: device.AuthToken,
|
||||
Login: login,
|
||||
Password: password,
|
||||
})
|
||||
}
|
||||
|
||||
func (h *mobileHandler) getMessage(device models.Device, c *fiber.Ctx) error {
|
||||
messages, err := h.messagesSvc.SelectPending(device.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't get messages: %w", err)
|
||||
}
|
||||
|
||||
return c.JSON(messages)
|
||||
}
|
||||
|
||||
func (h *mobileHandler) patchMessage(device models.Device, c *fiber.Ctx) error {
|
||||
req := []smsgateway.MessageState{}
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
|
||||
if err := h.Validator.Var(req, "required,dive"); err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, err.Error())
|
||||
}
|
||||
|
||||
return fiber.ErrNotImplemented
|
||||
}
|
||||
|
||||
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 {
|
||||
errorLog.Println(err)
|
||||
return fiber.ErrUnauthorized
|
||||
}
|
||||
|
||||
return handler(device, c)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *mobileHandler) register(router fiber.Router) {
|
||||
router.Post("/register", h.postRegister)
|
||||
|
||||
router.Use(apikey.New(apikey.Config{
|
||||
Authorizer: func(token string) bool {
|
||||
return len(token) > 0
|
||||
},
|
||||
}))
|
||||
|
||||
router.Get("/message", h.authorize(h.getMessage))
|
||||
router.Patch("/message", h.authorize(h.patchMessage))
|
||||
}
|
||||
|
||||
func newMobileHandler(validator *validator.Validate, authSvc *services.AuthService, messagesSvc *services.MessagesService) *mobileHandler {
|
||||
idGen, _ := nanoid.Standard(21)
|
||||
|
||||
return &mobileHandler{
|
||||
Handler: microbase.Handler{Validator: validator},
|
||||
authSvc: authSvc,
|
||||
messagesSvc: messagesSvc,
|
||||
idGen: idGen,
|
||||
}
|
||||
}
|
||||
62
internal/smsgateway/models/models.go
Normal file
62
internal/smsgateway/models/models.go
Normal file
@ -0,0 +1,62 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type MessageState string
|
||||
|
||||
const (
|
||||
MessageStatePending MessageState = "Pending"
|
||||
MessageStateSent MessageState = "Sent"
|
||||
MessageStateDelivered MessageState = "Delivered"
|
||||
MessageStateFailed MessageState = "Failed"
|
||||
)
|
||||
|
||||
type TimedModel struct {
|
||||
CreatedAt time.Time `gorm:"not null;default:CURRENT_TIMESTAMP(3)"`
|
||||
UpdatedAt time.Time `gorm:"not null;default:CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)"`
|
||||
DeletedAt gorm.DeletedAt
|
||||
}
|
||||
|
||||
type User struct {
|
||||
ID string `gorm:"primaryKey;type:varchar(32)"`
|
||||
PasswordHash string `gorm:"not null;type:varchar(72)"`
|
||||
Devices []Device `gorm:"foreignKey:UserID;constraint:OnDelete:CASCADE"`
|
||||
|
||||
TimedModel
|
||||
}
|
||||
|
||||
type Device struct {
|
||||
ID string `gorm:"primaryKey;type:char(21)"`
|
||||
Name string `gorm:"type:varchar(128)"`
|
||||
AuthToken string `gorm:"not null;uniqueIndex;type:char(21)"`
|
||||
PushToken string `gorm:"type:varchar(256)"`
|
||||
|
||||
UserID string `gorm:"not null;type:varchar(32)"`
|
||||
|
||||
TimedModel
|
||||
}
|
||||
|
||||
type Message struct {
|
||||
ID uint64 `gorm:"primaryKey;type:BIGINT UNSIGNED;autoIncrement"`
|
||||
DeviceID string `gorm:"not null;type:char(21);uniqueIndex:unq_messages_device_id;index:idx_messages_device_state"`
|
||||
ExtID string `gorm:"not null;type:varchar(36);uniqueIndex:unq_messages_device_id"`
|
||||
Message string `gorm:"not null;type:tinytext"`
|
||||
State MessageState `gorm:"not null;type:enum('Pending','Sent','Delivered','Failed');default:Pending;index:idx_messages_device_state"`
|
||||
|
||||
Device Device `gorm:"foreignKey:DeviceID;constraint:OnDelete:CASCADE"`
|
||||
Recipients []MessageRecipient `gorm:"foreignKey:MessageID;constraint:OnDelete:CASCADE"`
|
||||
}
|
||||
|
||||
type MessageRecipient struct {
|
||||
MessageID uint64 `gorm:"primaryKey;type:BIGINT UNSIGNED"`
|
||||
PhoneNumber string `gorm:"primaryKey;type:char(11)"`
|
||||
State MessageState `gorm:"not null;type:enum('Pending','Sent','Delivered','Failed');default:Pending"`
|
||||
}
|
||||
|
||||
func Migrate(db *gorm.DB) error {
|
||||
return db.AutoMigrate(&User{}, &Device{}, &Message{}, &MessageRecipient{})
|
||||
}
|
||||
30
internal/smsgateway/repositories/devices.go
Normal file
30
internal/smsgateway/repositories/devices.go
Normal file
@ -0,0 +1,30 @@
|
||||
package repositories
|
||||
|
||||
import (
|
||||
"bitbucket.org/capcom6/smsgatewaybackend/internal/smsgateway/models"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrDeviceNotFound = gorm.ErrRecordNotFound
|
||||
)
|
||||
|
||||
type DevicesRepository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func (r *DevicesRepository) GetByToken(token string) (models.Device, error) {
|
||||
device := models.Device{}
|
||||
|
||||
return device, r.db.Where("auth_token = ?", token).Take(&device).Error
|
||||
}
|
||||
|
||||
func (r *DevicesRepository) Insert(device *models.Device) error {
|
||||
return r.db.Create(device).Error
|
||||
}
|
||||
|
||||
func NewDevicesRepository(db *gorm.DB) *DevicesRepository {
|
||||
return &DevicesRepository{
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
27
internal/smsgateway/repositories/messages.go
Normal file
27
internal/smsgateway/repositories/messages.go
Normal file
@ -0,0 +1,27 @@
|
||||
package repositories
|
||||
|
||||
import (
|
||||
"bitbucket.org/capcom6/smsgatewaybackend/internal/smsgateway/models"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type MessagesRepository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func (r *MessagesRepository) SelectPending(deviceID string) (messages []models.Message, err error) {
|
||||
err = r.db.
|
||||
Where("device_id = ? AND state = ?", deviceID, models.MessageStatePending).
|
||||
Order("id").
|
||||
Preload("Recipients").
|
||||
Find(&messages).
|
||||
Error
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func NewMessagesRepository(db *gorm.DB) *MessagesRepository {
|
||||
return &MessagesRepository{
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
30
internal/smsgateway/repositories/users.go
Normal file
30
internal/smsgateway/repositories/users.go
Normal file
@ -0,0 +1,30 @@
|
||||
package repositories
|
||||
|
||||
import (
|
||||
"bitbucket.org/capcom6/smsgatewaybackend/internal/smsgateway/models"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrUserNotFound = gorm.ErrRecordNotFound
|
||||
)
|
||||
|
||||
type UsersRepository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func (r *UsersRepository) GetByLogin(login string) (models.User, error) {
|
||||
user := models.User{}
|
||||
|
||||
return user, r.db.Where("id = ?", login).Preload("Devices").Take(&user).Error
|
||||
}
|
||||
|
||||
func (r *UsersRepository) Insert(user *models.User) error {
|
||||
return r.db.Create(user).Error
|
||||
}
|
||||
|
||||
func NewUsersRepository(db *gorm.DB) *UsersRepository {
|
||||
return &UsersRepository{
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
60
internal/smsgateway/services/auth.go
Normal file
60
internal/smsgateway/services/auth.go
Normal file
@ -0,0 +1,60 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"bitbucket.org/capcom6/smsgatewaybackend/internal/smsgateway/models"
|
||||
"bitbucket.org/capcom6/smsgatewaybackend/internal/smsgateway/repositories"
|
||||
"bitbucket.org/soft-c/gohelpers/pkg/crypto"
|
||||
"github.com/jaevor/go-nanoid"
|
||||
)
|
||||
|
||||
type AuthService struct {
|
||||
users *repositories.UsersRepository
|
||||
devices *repositories.DevicesRepository
|
||||
|
||||
idgen func() string
|
||||
}
|
||||
|
||||
func (s *AuthService) RegisterUser(login, password string) (models.User, error) {
|
||||
user := models.User{
|
||||
ID: login,
|
||||
}
|
||||
|
||||
var err error
|
||||
if user.PasswordHash, err = crypto.MakeBCryptHash(password); err != nil {
|
||||
return user, err
|
||||
}
|
||||
|
||||
if err = s.users.Insert(&user); err != nil {
|
||||
return user, fmt.Errorf("can't create user")
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func (s *AuthService) RegisterDevice(userID, name, pushToken string) (models.Device, error) {
|
||||
device := models.Device{
|
||||
ID: s.idgen(),
|
||||
Name: name,
|
||||
AuthToken: s.idgen(),
|
||||
PushToken: pushToken,
|
||||
UserID: userID,
|
||||
}
|
||||
|
||||
return device, s.devices.Insert(&device)
|
||||
}
|
||||
|
||||
func (s *AuthService) AuthorizeDevice(token string) (models.Device, error) {
|
||||
return s.devices.GetByToken(token)
|
||||
}
|
||||
|
||||
func NewAuthService(users *repositories.UsersRepository, devices *repositories.DevicesRepository) *AuthService {
|
||||
idgen, _ := nanoid.Standard(21)
|
||||
|
||||
return &AuthService{
|
||||
users: users,
|
||||
devices: devices,
|
||||
idgen: idgen,
|
||||
}
|
||||
}
|
||||
51
internal/smsgateway/services/messages.go
Normal file
51
internal/smsgateway/services/messages.go
Normal file
@ -0,0 +1,51 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"bitbucket.org/capcom6/smsgatewaybackend/internal/smsgateway/models"
|
||||
"bitbucket.org/capcom6/smsgatewaybackend/internal/smsgateway/repositories"
|
||||
"bitbucket.org/capcom6/smsgatewaybackend/pkg/smsgateway"
|
||||
"github.com/jaevor/go-nanoid"
|
||||
)
|
||||
|
||||
type MessagesService struct {
|
||||
messages *repositories.MessagesRepository
|
||||
|
||||
idgen func() string
|
||||
}
|
||||
|
||||
func (s *MessagesService) SelectPending(deviceID string) ([]smsgateway.Message, error) {
|
||||
messages, err := s.messages.SelectPending(deviceID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make([]smsgateway.Message, len(messages))
|
||||
for i, v := range messages {
|
||||
result[i] = smsgateway.Message{
|
||||
ID: v.ExtID,
|
||||
Message: v.Message,
|
||||
PhoneNumbers: s.recipientsToDomain(v.Recipients),
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s *MessagesService) recipientsToDomain(input []models.MessageRecipient) []string {
|
||||
output := make([]string, len(input))
|
||||
|
||||
for i, v := range input {
|
||||
output[i] = v.PhoneNumber
|
||||
}
|
||||
|
||||
return output
|
||||
}
|
||||
|
||||
func NewMessagesService(messages *repositories.MessagesRepository) *MessagesService {
|
||||
idgen, _ := nanoid.Standard(21)
|
||||
|
||||
return &MessagesService{
|
||||
messages: messages,
|
||||
idgen: idgen,
|
||||
}
|
||||
}
|
||||
27
pkg/smsgateway/domain.go
Normal file
27
pkg/smsgateway/domain.go
Normal file
@ -0,0 +1,27 @@
|
||||
package smsgateway
|
||||
|
||||
type ProcessState string
|
||||
|
||||
const (
|
||||
MessageStatePending ProcessState = "Pending"
|
||||
MessageStateSent ProcessState = "Sent"
|
||||
MessageStateDelivered ProcessState = "Delivered"
|
||||
MessageStateFailed ProcessState = "Failed"
|
||||
)
|
||||
|
||||
type Message struct {
|
||||
ID string `json:"id,omitempty" validate:"omitempty,max=36"`
|
||||
Message string `json:"message" validate:"required,max=256"`
|
||||
PhoneNumbers []string `json:"phoneNumbers" validate:"required,min=1,max=100"`
|
||||
}
|
||||
|
||||
type MessageState struct {
|
||||
ID string `json:"id,omitempty" validate:"omitempty,max=36"`
|
||||
State ProcessState `json:"state" validate:"required"`
|
||||
Recipients []RecipientState `json:"recipients" validate:"required,min=1,dive"`
|
||||
}
|
||||
|
||||
type RecipientState struct {
|
||||
PhoneNumber string `json:"phoneNumber" validate:"required,len=11"`
|
||||
State ProcessState `json:"state" validate:"required"`
|
||||
}
|
||||
6
pkg/smsgateway/requests.go
Normal file
6
pkg/smsgateway/requests.go
Normal file
@ -0,0 +1,6 @@
|
||||
package smsgateway
|
||||
|
||||
type MobileRegisterRequest struct {
|
||||
Name string `json:"name,omitempty" validate:"omitempty,max=128"`
|
||||
PushToken string `json:"pushToken" validate:"omitempty,max=256"`
|
||||
}
|
||||
8
pkg/smsgateway/responses.go
Normal file
8
pkg/smsgateway/responses.go
Normal file
@ -0,0 +1,8 @@
|
||||
package smsgateway
|
||||
|
||||
type MobileRegisterResponse struct {
|
||||
Id string `json:"id"`
|
||||
Token string `json:"token"`
|
||||
Login string `json:"login"`
|
||||
Password string `json:"password"`
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user