diff --git a/server/.idea/dataSources.xml b/server/.idea/dataSources.xml
new file mode 100644
index 0000000..9f38ede
--- /dev/null
+++ b/server/.idea/dataSources.xml
@@ -0,0 +1,12 @@
+
+
+
+
+ sqlite.xerial
+ true
+ org.sqlite.JDBC
+ jdbc:sqlite:identifier.sqlite
+ $ProjectFileDir$
+
+
+
\ No newline at end of file
diff --git a/server/.idea/sqldialects.xml b/server/.idea/sqldialects.xml
new file mode 100644
index 0000000..a5d08e4
--- /dev/null
+++ b/server/.idea/sqldialects.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/server/api/handler/compat.go b/server/api/handler/compat.go
index 66b19a7..9bee99a 100644
--- a/server/api/handler/compat.go
+++ b/server/api/handler/compat.go
@@ -5,7 +5,13 @@ import (
"blackforestbytes.com/simplecloudnotifier/api/models"
"blackforestbytes.com/simplecloudnotifier/common/ginresp"
"blackforestbytes.com/simplecloudnotifier/logic"
+ "context"
+ "database/sql"
+ "fmt"
"github.com/gin-gonic/gin"
+ "net/http"
+ "strconv"
+ "time"
)
type CompatHandler struct {
@@ -21,6 +27,7 @@ func NewCompatHandler(app *logic.Application) CompatHandler {
// Register swaggerdoc
//
// @Summary Register a new account
+// @ID compat-register
// @Param fcm_token query string true "the (android) fcm token"
// @Param pro query string true "if the user is a paid account" Enums(true, false)
// @Param pro_token query string true "the (android) IAP token"
@@ -29,28 +36,101 @@ func NewCompatHandler(app *logic.Application) CompatHandler {
// @Router /register.php [get]
func (h CompatHandler) Register(g *gin.Context) ginresp.HTTPResponse {
type query struct {
- FCMToken string `form:"fcm_token"`
- Pro string `form:"pro"`
- ProToken string `form:"pro_token"`
+ FCMToken *string `form:"fcm_token"`
+ Pro *string `form:"pro"`
+ ProToken *string `form:"pro_token"`
}
type response struct {
- Success string `json:"success"`
+ Success bool `json:"success"`
Message string `json:"message"`
UserID string `json:"user_id"`
UserKey string `json:"user_key"`
- QuotaUsed string `json:"quota"`
- QuotaMax string `json:"quota_max"`
- IsPro string `json:"is_pro"`
+ QuotaUsed int `json:"quota"`
+ QuotaMax int `json:"quota_max"`
+ IsPro int `json:"is_pro"`
}
- //TODO
+ ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+ defer cancel()
- return ginresp.NotImplemented(0)
+ var q query
+ if err := g.ShouldBindQuery(&q); err != nil {
+ return ginresp.InternAPIError(0, "Failed to read arguments")
+ }
+
+ if q.FCMToken == nil {
+ return ginresp.InternAPIError(0, "Missing parameter [[fcm_token]]")
+ }
+ if q.Pro == nil {
+ return ginresp.InternAPIError(0, "Missing parameter [[pro]]")
+ }
+ if q.ProToken == nil {
+ return ginresp.InternAPIError(0, "Missing parameter [[pro_token]]")
+ }
+
+ isProInt := 0
+ isProBool := false
+ if *q.Pro == "true" {
+ isProInt = 1
+ isProBool = true
+ } else {
+ q.ProToken = nil
+ }
+
+ if isProBool {
+ ptok, err := h.app.VerifyProToken(*q.ProToken)
+ if err != nil {
+ return ginresp.InternAPIError(0, fmt.Sprintf("Failed to query purchaste status: %v", err))
+ }
+
+ if !ptok {
+ return ginresp.InternAPIError(0, "Purchase token could not be verified")
+ }
+ }
+
+ userKey := h.app.GenerateRandomAuthKey()
+
+ return h.app.RunTransaction(ctx, nil, func(tx *sql.Tx) (ginresp.HTTPResponse, bool) {
+
+ res, err := tx.ExecContext(ctx, "INSERT INTO users (user_key, fcm_token, is_pro, pro_token, timestamp_accessed) VALUES (?, ?, ?, ?, NOW())", userKey, *q.FCMToken, isProInt, q.ProToken)
+ if err != nil {
+ return ginresp.InternAPIError(0, fmt.Sprintf("Failed to create user: %v", err)), false
+ }
+
+ userId, err := res.LastInsertId()
+ if err != nil {
+ return ginresp.InternAPIError(0, fmt.Sprintf("Failed to get user_id: %v", err)), false
+ }
+
+ _, err = tx.ExecContext(ctx, "UPDATE users SET fcm_token=NULL WHERE user_id <> ? AND fcm_token=?", userId, q.FCMToken)
+ if err != nil {
+ return ginresp.InternAPIError(0, fmt.Sprintf("Failed to update fcm: %v", err)), false
+ }
+
+ if isProInt == 1 {
+ _, err := tx.ExecContext(ctx, "UPDATE users SET is_pro=0, pro_token=NULL WHERE user_id <> ? AND pro_token = ?", userId, q.ProToken)
+ if err != nil {
+ return ginresp.InternAPIError(0, fmt.Sprintf("Failed to update ispro: %v", err)), false
+ }
+ }
+
+ return ginresp.JSON(http.StatusOK, response{
+ Success: true,
+ Message: "New user registered",
+ UserID: strconv.FormatInt(userId, 10),
+ UserKey: userKey,
+ QuotaUsed: 0,
+ QuotaMax: h.app.QuotaMax(isProBool),
+ IsPro: isProInt,
+ }), true
+
+ })
}
// Info swaggerdoc
//
// @Summary Get information about the current user
+// @ID compat-info
// @Param user_id query string true "the user_id"
// @Param user_key query string true "the user_key"
// @Success 200 {object} handler.Info.response
@@ -75,12 +155,13 @@ func (h CompatHandler) Info(g *gin.Context) ginresp.HTTPResponse {
//TODO
- return ginresp.NotImplemented(0)
+ return ginresp.InternAPIError(0, "NotImplemented")
}
// Ack swaggerdoc
//
// @Summary Acknowledge that a message was received
+// @ID compat-ack
// @Param user_id query string true "the user_id"
// @Param user_key query string true "the user_key"
// @Param scn_msg_id query string true "the message id"
@@ -102,12 +183,13 @@ func (h CompatHandler) Ack(g *gin.Context) ginresp.HTTPResponse {
//TODO
- return ginresp.NotImplemented(0)
+ return ginresp.InternAPIError(0, "NotImplemented")
}
// Requery swaggerdoc
//
// @Summary Return all not-acknowledged messages
+// @ID compat-requery
// @Param user_id query string true "the user_id"
// @Param user_key query string true "the user_key"
// @Success 200 {object} handler.Requery.response
@@ -127,12 +209,13 @@ func (h CompatHandler) Requery(g *gin.Context) ginresp.HTTPResponse {
//TODO
- return ginresp.NotImplemented(0)
+ return ginresp.InternAPIError(0, "NotImplemented")
}
// Update swaggerdoc
//
// @Summary Set the fcm-token (android)
+// @ID compat-update
// @Param user_id query string true "the user_id"
// @Param user_key query string true "the user_key"
// @Param fcm_token query string true "the (android) fcm token"
@@ -157,12 +240,13 @@ func (h CompatHandler) Update(g *gin.Context) ginresp.HTTPResponse {
//TODO
- return ginresp.NotImplemented(0)
+ return ginresp.InternAPIError(0, "NotImplemented")
}
// Expand swaggerdoc
//
// @Summary Get a whole (potentially truncated) message
+// @ID compat-expand
// @Success 200 {object} handler.Expand.response
// @Failure 500 {object} ginresp.internAPIError
// @Router /expand.php [get]
@@ -180,12 +264,13 @@ func (h CompatHandler) Expand(g *gin.Context) ginresp.HTTPResponse {
//TODO
- return ginresp.NotImplemented(0)
+ return ginresp.InternAPIError(0, "NotImplemented")
}
// Upgrade swaggerdoc
//
// @Summary Upgrade a free account to a paid account
+// @ID compat-upgrade
// @Param user_id query string true "the user_id"
// @Param user_key query string true "the user_key"
// @Param pro query string true "if the user is a paid account" Enums(true, false)
@@ -208,33 +293,39 @@ func (h CompatHandler) Upgrade(g *gin.Context) ginresp.HTTPResponse {
//TODO
- return ginresp.NotImplemented(0)
+ return ginresp.InternAPIError(0, "NotImplemented")
}
// Send swaggerdoc
//
-// @Summary Send a message
-// @Description all aeguments can either be supplied in the query or in the json body
-// @Param user_id query string true "the user_id"
-// @Param user_key query string true "the user_key"
-// @Param title query string true "The message title"
-// @Param content query string false "The message content"
-// @Param priority query string false "The message priority" Enum(0, 1, 2)
-// @Param msg_id query string false "The message idempotency id"
-// @Param timestamp query string false "The message timestamp"
-// @Param user_id body string true "the user_id"
-// @Param user_key body string true "the user_key"
-// @Param title body string true "The message title"
-// @Param content body string false "The message content"
-// @Param priority body string false "The message priority" Enum(0, 1, 2)
-// @Param msg_id body string false "The message idempotency id"
-// @Param timestamp body string false "The message timestamp"
-// @Success 200 {object} handler.Send.response
-// @Failure 500 {object} ginresp.sendAPIError
-// @Router /send.php [post]
+// @Summary Send a message
+// @Description (all arguments can either be supplied in the query or in the json body)
+// @ID compat-send
+// @Accept json
+// @Produce json
+// @Param _ query handler.Send.query false " "
+// @Param post_body body handler.Send.body false " "
+// @Success 200 {object} handler.Send.response
+// @Failure 500 {object} ginresp.sendAPIError
+// @Router /send.php [post]
func (h CompatHandler) Send(g *gin.Context) ginresp.HTTPResponse {
type query struct {
- //TODO
+ UserID string `form:"user_id" required:"true"`
+ UserKey string `form:"user_key" required:"true"`
+ Title string `form:"title" required:"true"`
+ Content *string `form:"content"`
+ Priority *string `form:"priority"`
+ MessageID *string `form:"msg_id"`
+ Timestamp *string `form:"timestamp"`
+ }
+ type body struct {
+ UserID string `json:"user_id" required:"true"`
+ UserKey string `json:"user_key" required:"true"`
+ Title string `json:"title" required:"true"`
+ Content *string `json:"content"`
+ Priority *string `json:"priority"`
+ MessageID *string `json:"msg_id"`
+ Timestamp *string `json:"timestamp"`
}
type response struct {
Success string `json:"success"`
diff --git a/server/cmd/scnserver/main.go b/server/cmd/scnserver/main.go
index 36281af..5c1287b 100644
--- a/server/cmd/scnserver/main.go
+++ b/server/cmd/scnserver/main.go
@@ -7,6 +7,7 @@ import (
"blackforestbytes.com/simplecloudnotifier/common/ginext"
"blackforestbytes.com/simplecloudnotifier/db"
"blackforestbytes.com/simplecloudnotifier/logic"
+ "context"
"fmt"
"github.com/rs/zerolog/log"
)
@@ -18,7 +19,7 @@ func main() {
log.Info().Msg(fmt.Sprintf("Starting with config-namespace <%s>", conf.Namespace))
- sqlite, err := db.NewDatabase(conf)
+ sqlite, err := db.NewDatabase(context.Background(), conf)
if err != nil {
panic(err)
}
diff --git a/server/common/ginresp/resp.go b/server/common/ginresp/resp.go
index f8f7b9a..a0c368f 100644
--- a/server/common/ginresp/resp.go
+++ b/server/common/ginresp/resp.go
@@ -76,8 +76,8 @@ func InternalError(e error) HTTPResponse {
return &errHTTPResponse{statusCode: http.StatusInternalServerError, data: errBody{Success: false, Message: e.Error()}}
}
-func NotImplemented(errid int) HTTPResponse {
- return &errHTTPResponse{statusCode: http.StatusInternalServerError, data: internAPIError{Success: false, ErrorID: errid, Message: "NotImplemented"}}
+func InternAPIError(errid int, msg string) HTTPResponse {
+ return &errHTTPResponse{statusCode: http.StatusInternalServerError, data: internAPIError{Success: false, ErrorID: errid, Message: msg}}
}
func SendAPIError(errorid apierr.APIError, highlight int, msg string) HTTPResponse {
diff --git a/server/db/database.go b/server/db/database.go
index 12d57be..532ae20 100644
--- a/server/db/database.go
+++ b/server/db/database.go
@@ -2,10 +2,70 @@ package db
import (
scn "blackforestbytes.com/simplecloudnotifier"
+ "context"
"database/sql"
+ _ "embed"
+ "errors"
+ "fmt"
_ "github.com/mattn/go-sqlite3"
)
-func NewDatabase(conf scn.Config) (*sql.DB, error) {
- return sql.Open("sqlite3", conf.DBFile)
+//go:embed schema_1.0.sql
+var schema_1_0 string
+
+//go:embed schema_2.0.sql
+var schema_2_0 string
+
+func NewDatabase(ctx context.Context, conf scn.Config) (*sql.DB, error) {
+ db, err := sql.Open("sqlite3", conf.DBFile)
+ if err != nil {
+ return nil, err
+ }
+
+ schema, err := getSchemaFromDB(ctx, db)
+ if schema == 0 {
+
+ _, err = db.ExecContext(ctx, schema_1_0)
+ if err != nil {
+ return nil, err
+ }
+
+ return db, nil
+
+ } else if schema == 1 {
+ return nil, errors.New("cannot autom. upgrade schema 1")
+ } else if schema == 2 {
+ return db, nil
+ } else {
+ return nil, errors.New(fmt.Sprintf("Unknown DB schema: %d", schema))
+ }
+
+}
+
+func getSchemaFromDB(ctx context.Context, db *sql.DB) (int, error) {
+
+ r1, err := db.QueryContext(ctx, "SELECT name FROM sqlite_master WHERE type='table' AND name='meta'")
+ if err != nil {
+ return 0, err
+ }
+
+ if !r1.Next() {
+ return 0, nil
+ }
+
+ r2, err := db.QueryContext(ctx, "SELECT value_int FROM meta WHERE key='schema'")
+ if err != nil {
+ return 0, err
+ }
+ if !r2.Next() {
+ return 0, errors.New("no schema entry in meta table")
+ }
+
+ var schema int
+ err = r2.Scan(&schema)
+ if err != nil {
+ return 0, err
+ }
+
+ return schema, nil
}
diff --git a/server/db/schema_1.0.sql b/server/db/schema_1.0.sql
new file mode 100644
index 0000000..504798d
--- /dev/null
+++ b/server/db/schema_1.0.sql
@@ -0,0 +1,38 @@
+DROP TABLE IF EXISTS `users`;
+CREATE TABLE `users`
+(
+ `user_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `user_key` VARCHAR(64) NOT NULL,
+ `fcm_token` VARCHAR(256) NULL DEFAULT NULL,
+ `messages_sent` INT(11) NOT NULL DEFAULT '0',
+ `timestamp_created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `timestamp_accessed` DATETIME NULL DEFAULT NULL,
+
+ `quota_today` INT(11) NOT NULL DEFAULT '0',
+ `quota_day` DATE NULL DEFAULT NULL,
+
+ `is_pro` BIT NOT NULL DEFAULT 0,
+ `pro_token` VARCHAR(256) NULL DEFAULT NULL,
+
+ PRIMARY KEY (`user_id`)
+);
+
+DROP TABLE IF EXISTS `messages`;
+CREATE TABLE `messages`
+(
+ `scn_message_id` INT(11) NOT NULL AUTO_INCREMENT,
+ `sender_user_id` INT(11) NOT NULL,
+
+ `timestamp_real` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `ack` TINYINT(1) NOT NULL DEFAULT 0,
+
+ `title` VARCHAR(256) NOT NULL,
+ `content` LONGTEXT NULL,
+ `priority` INT(11) NOT NULL,
+ `sendtime` BIGINT UNSIGNED NOT NULL,
+
+ `fcm_message_id` VARCHAR(256) NULL,
+ `usr_message_id` VARCHAR(256) NULL,
+
+ PRIMARY KEY (`scn_message_id`)
+);
\ No newline at end of file
diff --git a/server/db/schema_2.0.sql b/server/db/schema_2.0.sql
new file mode 100644
index 0000000..2032092
--- /dev/null
+++ b/server/db/schema_2.0.sql
@@ -0,0 +1,47 @@
+CREATE TABLE `users`
+(
+ `user_id` INTEGER AUTO_INCREMENT,
+ `user_key` TEXT NOT NULL,
+ `fcm_token` TEXT NULL DEFAULT NULL,
+ `messages_sent` INTEGER NOT NULL DEFAULT '0',
+ `timestamp_created` TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `timestamp_accessed` TEXT NULL DEFAULT NULL,
+
+ `quota_today` INTEGER NOT NULL DEFAULT '0',
+ `quota_day` TEXT NULL DEFAULT NULL,
+
+ `is_pro` INTEGER NOT NULL DEFAULT 0,
+ `pro_token` TEXT NULL DEFAULT NULL,
+
+ PRIMARY KEY (`user_id`)
+);
+
+CREATE TABLE `messages`
+(
+ `scn_message_id` INTEGER AUTO_INCREMENT,
+ `sender_user_id` INTEGER NOT NULL,
+
+ `timestamp_real` TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ `ack` INTEGER NOT NULL DEFAULT 0,
+
+ `title` TEXT NOT NULL,
+ `content` TEXT NULL,
+ `priority` INTEGER NOT NULL,
+ `sendtime` INTEGER NOT NULL,
+
+ `fcm_message_id` TEXT NULL,
+ `usr_message_id` TEXT NULL,
+
+ PRIMARY KEY (`scn_message_id`)
+);
+
+CREATE TABLE `meta`
+(
+ `key` TEXT NOT NULL,
+ `value_int` INTEGER NULL,
+ `value_txt` TEXT NULL,
+
+ PRIMARY KEY (`key`)
+);
+
+INSERT INTO meta (key, value_int) VALUES ('schema', 2)
\ No newline at end of file
diff --git a/server/go.mod b/server/go.mod
index c4c04a7..df8fd17 100644
--- a/server/go.mod
+++ b/server/go.mod
@@ -32,6 +32,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.0.1 // indirect
github.com/ugorji/go/codec v1.2.7 // indirect
+ gogs.mikescher.com/BlackForestBytes/goext v0.0.17 // indirect
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect
golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
golang.org/x/sys v0.1.0 // indirect
diff --git a/server/go.sum b/server/go.sum
index 9e02733..b207928 100644
--- a/server/go.sum
+++ b/server/go.sum
@@ -90,6 +90,8 @@ github.com/swaggo/swag v1.8.7/go.mod h1:ezQVUUhly8dludpVk+/PuwJWvLLanB13ygV5Pr9e
github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
+gogs.mikescher.com/BlackForestBytes/goext v0.0.17 h1:jsfbvII7aa0SH9qY0fnXBdtNnQe1YY3DgXDThEwLICc=
+gogs.mikescher.com/BlackForestBytes/goext v0.0.17/go.mod h1:TMBOjo3FRFh/GiTT0z3nwLmgcFJB87oSF2VMs4XUCTQ=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
diff --git a/server/logic/application.go b/server/logic/application.go
index aa61672..91adbe5 100644
--- a/server/logic/application.go
+++ b/server/logic/application.go
@@ -2,10 +2,13 @@ package logic
import (
scn "blackforestbytes.com/simplecloudnotifier"
+ "blackforestbytes.com/simplecloudnotifier/common/ginresp"
"context"
"database/sql"
+ "fmt"
"github.com/gin-gonic/gin"
"github.com/rs/zerolog/log"
+ "math/rand"
"net"
"net/http"
"os"
@@ -61,3 +64,48 @@ func (app *Application) Run() {
}
}
+
+func (app *Application) GenerateRandomAuthKey() string {
+ charset := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
+ k := ""
+ for i := 0; i < 64; i++ {
+ k += string(charset[rand.Int()%len(charset)])
+ }
+ return k
+}
+
+func (app *Application) RunTransaction(ctx context.Context, opt *sql.TxOptions, fn func(tx *sql.Tx) (ginresp.HTTPResponse, bool)) ginresp.HTTPResponse {
+
+ tx, err := app.Database.BeginTx(ctx, opt)
+ if err != nil {
+ return ginresp.InternAPIError(0, fmt.Sprintf("Failed to create transaction: %v", err))
+ }
+
+ res, commit := fn(tx)
+
+ if commit {
+ err = tx.Commit()
+ if err != nil {
+ return ginresp.InternAPIError(0, fmt.Sprintf("Failed to commit transaction: %v", err))
+ }
+ } else {
+ err = tx.Rollback()
+ if err != nil {
+ return ginresp.InternAPIError(0, fmt.Sprintf("Failed to rollback transaction: %v", err))
+ }
+ }
+
+ return res
+}
+
+func (app *Application) QuotaMax(ispro bool) int {
+ if ispro {
+ return 1000
+ } else {
+ return 50
+ }
+}
+
+func (app *Application) VerifyProToken(token string) (bool, error) {
+ return false, nil //TODO implement pro verification
+}
diff --git a/server/swagger/swagger.json b/server/swagger/swagger.json
index df5327e..75d4068 100644
--- a/server/swagger/swagger.json
+++ b/server/swagger/swagger.json
@@ -12,6 +12,7 @@
"/ack.php": {
"get": {
"summary": "Acknowledge that a message was received",
+ "operationId": "compat-ack",
"parameters": [
{
"type": "string",
@@ -72,6 +73,7 @@
"/expand.php": {
"get": {
"summary": "Get a whole (potentially truncated) message",
+ "operationId": "compat-expand",
"responses": {
"200": {
"description": "OK",
@@ -109,6 +111,7 @@
"/info.php": {
"get": {
"summary": "Get information about the current user",
+ "operationId": "compat-info",
"parameters": [
{
"type": "string",
@@ -226,6 +229,7 @@
"/register.php": {
"get": {
"summary": "Register a new account",
+ "operationId": "compat-register",
"parameters": [
{
"type": "string",
@@ -272,6 +276,7 @@
"/requery.php": {
"get": {
"summary": "Return all not-acknowledged messages",
+ "operationId": "compat-requery",
"parameters": [
{
"type": "string",
@@ -306,111 +311,57 @@
},
"/send.php": {
"post": {
- "description": "all aeguments can either be supplied in the query or in the json body",
+ "description": "(all arguments can either be supplied in the query or in the json body)",
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
"summary": "Send a message",
+ "operationId": "compat-send",
"parameters": [
{
"type": "string",
- "description": "the user_id",
- "name": "user_id",
- "in": "query",
- "required": true
- },
- {
- "type": "string",
- "description": "the user_key",
- "name": "user_key",
- "in": "query",
- "required": true
- },
- {
- "type": "string",
- "description": "The message title",
- "name": "title",
- "in": "query",
- "required": true
- },
- {
- "type": "string",
- "description": "The message content",
"name": "content",
"in": "query"
},
{
"type": "string",
- "description": "The message priority",
+ "name": "messageID",
+ "in": "query"
+ },
+ {
+ "type": "string",
"name": "priority",
"in": "query"
},
{
"type": "string",
- "description": "The message idempotency id",
- "name": "msg_id",
- "in": "query"
- },
- {
- "type": "string",
- "description": "The message timestamp",
"name": "timestamp",
"in": "query"
},
{
- "description": "the user_id",
- "name": "user_id",
- "in": "body",
- "required": true,
- "schema": {
- "type": "string"
- }
- },
- {
- "description": "the user_key",
- "name": "user_key",
- "in": "body",
- "required": true,
- "schema": {
- "type": "string"
- }
- },
- {
- "description": "The message title",
+ "type": "string",
"name": "title",
- "in": "body",
- "required": true,
- "schema": {
- "type": "string"
- }
+ "in": "query"
},
{
- "description": "The message content",
- "name": "content",
- "in": "body",
- "schema": {
- "type": "string"
- }
+ "type": "string",
+ "name": "userID",
+ "in": "query"
},
{
- "description": "The message priority",
- "name": "priority",
- "in": "body",
- "schema": {
- "type": "string"
- }
+ "type": "string",
+ "name": "userKey",
+ "in": "query"
},
{
- "description": "The message idempotency id",
- "name": "msg_id",
+ "description": " ",
+ "name": "post_body",
"in": "body",
"schema": {
- "type": "string"
- }
- },
- {
- "description": "The message timestamp",
- "name": "timestamp",
- "in": "body",
- "schema": {
- "type": "string"
+ "$ref": "#/definitions/handler.Send.body"
}
}
],
@@ -433,6 +384,7 @@
"/update.php": {
"get": {
"summary": "Set the fcm-token (android)",
+ "operationId": "compat-update",
"parameters": [
{
"type": "string",
@@ -475,6 +427,7 @@
"/upgrade.php": {
"get": {
"summary": "Upgrade a free account to a paid account",
+ "operationId": "compat-upgrade",
"parameters": [
{
"type": "string",
@@ -661,19 +614,19 @@
"type": "object",
"properties": {
"is_pro": {
- "type": "string"
+ "type": "integer"
},
"message": {
"type": "string"
},
"quota": {
- "type": "string"
+ "type": "integer"
},
"quota_max": {
- "type": "string"
+ "type": "integer"
},
"success": {
- "type": "string"
+ "type": "boolean"
},
"user_id": {
"type": "string"
@@ -703,6 +656,32 @@
}
}
},
+ "handler.Send.body": {
+ "type": "object",
+ "properties": {
+ "content": {
+ "type": "string"
+ },
+ "msg_id": {
+ "type": "string"
+ },
+ "priority": {
+ "type": "string"
+ },
+ "timestamp": {
+ "type": "string"
+ },
+ "title": {
+ "type": "string"
+ },
+ "user_id": {
+ "type": "string"
+ },
+ "user_key": {
+ "type": "string"
+ }
+ }
+ },
"handler.Send.response": {
"type": "object",
"properties": {
diff --git a/server/swagger/swagger.yaml b/server/swagger/swagger.yaml
index 86dc98c..7f9a6ce 100644
--- a/server/swagger/swagger.yaml
+++ b/server/swagger/swagger.yaml
@@ -87,15 +87,15 @@ definitions:
handler.Register.response:
properties:
is_pro:
- type: string
+ type: integer
message:
type: string
quota:
- type: string
+ type: integer
quota_max:
- type: string
+ type: integer
success:
- type: string
+ type: boolean
user_id:
type: string
user_key:
@@ -114,6 +114,23 @@ definitions:
success:
type: string
type: object
+ handler.Send.body:
+ properties:
+ content:
+ type: string
+ msg_id:
+ type: string
+ priority:
+ type: string
+ timestamp:
+ type: string
+ title:
+ type: string
+ user_id:
+ type: string
+ user_key:
+ type: string
+ type: object
handler.Send.response:
properties:
message:
@@ -212,6 +229,7 @@ info:
paths:
/ack.php:
get:
+ operationId: compat-ack
parameters:
- description: the user_id
in: query
@@ -251,6 +269,7 @@ paths:
$ref: '#/definitions/ginresp.errBody'
/expand.php:
get:
+ operationId: compat-expand
responses:
"200":
description: OK
@@ -274,6 +293,7 @@ paths:
$ref: '#/definitions/ginresp.errBody'
/info.php:
get:
+ operationId: compat-info
parameters:
- description: the user_id
in: query
@@ -348,6 +368,7 @@ paths:
$ref: '#/definitions/ginresp.errBody'
/register.php:
get:
+ operationId: compat-register
parameters:
- description: the (android) fcm token
in: query
@@ -379,6 +400,7 @@ paths:
summary: Register a new account
/requery.php:
get:
+ operationId: compat-requery
parameters:
- description: the user_id
in: query
@@ -402,78 +424,40 @@ paths:
summary: Return all not-acknowledged messages
/send.php:
post:
- description: all aeguments can either be supplied in the query or in the json
- body
+ consumes:
+ - application/json
+ description: (all arguments can either be supplied in the query or in the json
+ body)
+ operationId: compat-send
parameters:
- - description: the user_id
- in: query
- name: user_id
- required: true
- type: string
- - description: the user_key
- in: query
- name: user_key
- required: true
- type: string
- - description: The message title
- in: query
- name: title
- required: true
- type: string
- - description: The message content
- in: query
+ - in: query
name: content
type: string
- - description: The message priority
- in: query
+ - in: query
+ name: messageID
+ type: string
+ - in: query
name: priority
type: string
- - description: The message idempotency id
- in: query
- name: msg_id
- type: string
- - description: The message timestamp
- in: query
+ - in: query
name: timestamp
type: string
- - description: the user_id
- in: body
- name: user_id
- required: true
- schema:
- type: string
- - description: the user_key
- in: body
- name: user_key
- required: true
- schema:
- type: string
- - description: The message title
- in: body
+ - in: query
name: title
- required: true
- schema:
- type: string
- - description: The message content
+ type: string
+ - in: query
+ name: userID
+ type: string
+ - in: query
+ name: userKey
+ type: string
+ - description: ' '
in: body
- name: content
+ name: post_body
schema:
- type: string
- - description: The message priority
- in: body
- name: priority
- schema:
- type: string
- - description: The message idempotency id
- in: body
- name: msg_id
- schema:
- type: string
- - description: The message timestamp
- in: body
- name: timestamp
- schema:
- type: string
+ $ref: '#/definitions/handler.Send.body'
+ produces:
+ - application/json
responses:
"200":
description: OK
@@ -486,6 +470,7 @@ paths:
summary: Send a message
/update.php:
get:
+ operationId: compat-update
parameters:
- description: the user_id
in: query
@@ -514,6 +499,7 @@ paths:
summary: Set the fcm-token (android)
/upgrade.php:
get:
+ operationId: compat-upgrade
parameters:
- description: the user_id
in: query