From 1671490485bcdeb7689faabf757e3a8ac09d5826 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20Schw=C3=B6rer?= Date: Sun, 13 Nov 2022 22:31:28 +0100 Subject: [PATCH] implement a bit of the register.php call (and the DB schema) --- server/.idea/dataSources.xml | 12 +++ server/.idea/sqldialects.xml | 7 ++ server/api/handler/compat.go | 161 ++++++++++++++++++++++++++-------- server/cmd/scnserver/main.go | 3 +- server/common/ginresp/resp.go | 4 +- server/db/database.go | 64 +++++++++++++- server/db/schema_1.0.sql | 38 ++++++++ server/db/schema_2.0.sql | 47 ++++++++++ server/go.mod | 1 + server/go.sum | 2 + server/logic/application.go | 48 ++++++++++ server/swagger/swagger.json | 143 +++++++++++++----------------- server/swagger/swagger.yaml | 118 +++++++++++-------------- 13 files changed, 460 insertions(+), 188 deletions(-) create mode 100644 server/.idea/dataSources.xml create mode 100644 server/.idea/sqldialects.xml create mode 100644 server/db/schema_1.0.sql create mode 100644 server/db/schema_2.0.sql 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