added template for new golang backend

This commit is contained in:
2022-11-13 19:17:07 +01:00
parent bd11d7973c
commit 0e58a5c5f0
36 changed files with 2908 additions and 0 deletions

27
server/swagger/index.html Normal file
View File

@@ -0,0 +1,27 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>API Documentation</title>
<link rel="stylesheet" href="swagger-ui.css" />
</head>
<body>
<div id="swagger-ui"></div>
<script src="swagger-ui-bundle.js" crossorigin></script>
<script src="swagger-ui-standalone-preset.js" crossorigin></script>
<script>
window.onload = () => {
window.ui = SwaggerUIBundle({
url: './swagger.json',
dom_id: '#swagger-ui',
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
layout: "StandaloneLayout"
});
};
</script>
</body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

68
server/swagger/swagger.go Normal file
View File

@@ -0,0 +1,68 @@
package swagger
import (
"blackforestbytes.com/simplecloudnotifier/common/ginresp"
"embed"
_ "embed"
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
//go:embed index.html
//go:embed swagger.json
//go:embed swagger.yaml
//go:embed swagger-ui-bundle.js
//go:embed swagger-ui.css
//go:embed swagger-ui-standalone-preset.js
var assets embed.FS
func getAsset(fn string) ([]byte, string, bool) {
data, err := assets.ReadFile(fn)
if err != nil {
return nil, "", false
}
mime := "text/plain"
lowerFN := strings.ToLower(fn)
if strings.HasSuffix(lowerFN, ".html") || strings.HasSuffix(lowerFN, ".htm") {
mime = "text/html"
} else if strings.HasSuffix(lowerFN, ".css") {
mime = "text/css"
} else if strings.HasSuffix(lowerFN, ".js") {
mime = "text/javascript"
} else if strings.HasSuffix(lowerFN, ".json") {
mime = "application/json"
} else if strings.HasSuffix(lowerFN, ".jpeg") || strings.HasSuffix(lowerFN, ".jpg") {
mime = "image/jpeg"
} else if strings.HasSuffix(lowerFN, ".png") {
mime = "image/png"
} else if strings.HasSuffix(lowerFN, ".svg") {
mime = "image/svg+xml"
}
return data, mime, true
}
func Handle(g *gin.Context) ginresp.HTTPResponse {
type uri struct {
Filename string `uri:"fn"`
}
var u uri
if err := g.ShouldBindUri(&u); err != nil {
return ginresp.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
}
if u.Filename == "" {
index, _, _ := getAsset("index.html")
return ginresp.Data(http.StatusOK, "text/html", index)
}
if data, mime, ok := getAsset(u.Filename); ok {
return ginresp.Data(http.StatusOK, mime, data)
}
return ginresp.JSON(http.StatusNotFound, gin.H{"error": "AssetNotFound", "filename": u.Filename})
}

844
server/swagger/swagger.json Normal file
View File

@@ -0,0 +1,844 @@
{
"swagger": "2.0",
"info": {
"description": "API for SCN",
"title": "SimpleCloudNotifier API",
"contact": {},
"version": "2.0"
},
"host": "scn.blackforestbytes.com",
"basePath": "/api/",
"paths": {
"/ack.php": {
"get": {
"summary": "Acknowledge that a message was received",
"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 id",
"name": "scn_msg_id",
"in": "query",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/handler.Ack.response"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ginresp.internAPIError"
}
}
}
}
},
"/db-test": {
"get": {
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/handler.DatabaseTest.response"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ginresp.errBody"
}
}
}
}
},
"/expand.php": {
"get": {
"summary": "Get a whole (potentially truncated) message",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/handler.Expand.response"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ginresp.internAPIError"
}
}
}
}
},
"/health": {
"get": {
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/handler.Health.response"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ginresp.errBody"
}
}
}
}
},
"/info.php": {
"get": {
"summary": "Get information about the current user",
"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
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/handler.Info.response"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ginresp.internAPIError"
}
}
}
}
},
"/ping": {
"get": {
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/handler.pingResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ginresp.errBody"
}
}
}
},
"put": {
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/handler.pingResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ginresp.errBody"
}
}
}
},
"post": {
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/handler.pingResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ginresp.errBody"
}
}
}
},
"delete": {
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/handler.pingResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ginresp.errBody"
}
}
}
},
"patch": {
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/handler.pingResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ginresp.errBody"
}
}
}
}
},
"/register.php": {
"get": {
"summary": "Register a new account",
"parameters": [
{
"type": "string",
"description": "the (android) fcm token",
"name": "fcm_token",
"in": "query",
"required": true
},
{
"enum": [
"true",
"false"
],
"type": "string",
"description": "if the user is a paid account",
"name": "pro",
"in": "query",
"required": true
},
{
"type": "string",
"description": "the (android) IAP token",
"name": "pro_token",
"in": "query",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/handler.Register.response"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ginresp.internAPIError"
}
}
}
}
},
"/requery.php": {
"get": {
"summary": "Return all not-acknowledged messages",
"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
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/handler.Requery.response"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ginresp.internAPIError"
}
}
}
}
},
"/send.php": {
"post": {
"description": "all aeguments can either be supplied in the query or in the json body",
"summary": "Send a message",
"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": "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",
"name": "title",
"in": "body",
"required": true,
"schema": {
"type": "string"
}
},
{
"description": "The message content",
"name": "content",
"in": "body",
"schema": {
"type": "string"
}
},
{
"description": "The message priority",
"name": "priority",
"in": "body",
"schema": {
"type": "string"
}
},
{
"description": "The message idempotency id",
"name": "msg_id",
"in": "body",
"schema": {
"type": "string"
}
},
{
"description": "The message timestamp",
"name": "timestamp",
"in": "body",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/handler.Send.response"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ginresp.sendAPIError"
}
}
}
}
},
"/update.php": {
"get": {
"summary": "Set the fcm-token (android)",
"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 (android) fcm token",
"name": "fcm_token",
"in": "query",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/handler.Update.response"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ginresp.internAPIError"
}
}
}
}
},
"/upgrade.php": {
"get": {
"summary": "Upgrade a free account to a paid account",
"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
},
{
"enum": [
"true",
"false"
],
"type": "string",
"description": "if the user is a paid account",
"name": "pro",
"in": "query",
"required": true
},
{
"type": "string",
"description": "the (android) IAP token",
"name": "pro_token",
"in": "query",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/handler.Upgrade.response"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/ginresp.internAPIError"
}
}
}
}
}
},
"definitions": {
"ginresp.errBody": {
"type": "object",
"properties": {
"message": {
"type": "string"
},
"success": {
"type": "boolean"
}
}
},
"ginresp.internAPIError": {
"type": "object",
"properties": {
"errid": {
"type": "integer"
},
"message": {
"type": "string"
},
"success": {
"type": "boolean"
}
}
},
"ginresp.sendAPIError": {
"type": "object",
"properties": {
"errhighlight": {
"type": "integer"
},
"error": {
"type": "integer"
},
"message": {
"type": "string"
},
"success": {
"type": "boolean"
}
}
},
"handler.Ack.response": {
"type": "object",
"properties": {
"message": {
"type": "string"
},
"new_ack": {
"type": "integer"
},
"prev_ack": {
"type": "integer"
},
"success": {
"type": "string"
}
}
},
"handler.DatabaseTest.response": {
"type": "object",
"properties": {
"libVersion": {
"type": "string"
},
"libVersionNumber": {
"type": "integer"
},
"sourceID": {
"type": "string"
},
"success": {
"type": "boolean"
}
}
},
"handler.Expand.response": {
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/models.ShortCompatMessage"
},
"message": {
"type": "string"
},
"success": {
"type": "string"
}
}
},
"handler.Health.response": {
"type": "object",
"properties": {
"status": {
"type": "string"
}
}
},
"handler.Info.response": {
"type": "object",
"properties": {
"fcm_token_set": {
"type": "boolean"
},
"is_pro": {
"type": "string"
},
"message": {
"type": "string"
},
"quota": {
"type": "string"
},
"quota_max": {
"type": "string"
},
"success": {
"type": "string"
},
"unack_count": {
"type": "integer"
},
"user_id": {
"type": "string"
},
"user_key": {
"type": "string"
}
}
},
"handler.Register.response": {
"type": "object",
"properties": {
"is_pro": {
"type": "string"
},
"message": {
"type": "string"
},
"quota": {
"type": "string"
},
"quota_max": {
"type": "string"
},
"success": {
"type": "string"
},
"user_id": {
"type": "string"
},
"user_key": {
"type": "string"
}
}
},
"handler.Requery.response": {
"type": "object",
"properties": {
"count": {
"type": "integer"
},
"data": {
"type": "array",
"items": {
"$ref": "#/definitions/models.CompatMessage"
}
},
"message": {
"type": "string"
},
"success": {
"type": "string"
}
}
},
"handler.Send.response": {
"type": "object",
"properties": {
"message": {
"type": "string"
},
"success": {
"type": "string"
}
}
},
"handler.Update.response": {
"type": "object",
"properties": {
"is_pro": {
"type": "string"
},
"message": {
"type": "string"
},
"quota": {
"type": "string"
},
"quota_max": {
"type": "string"
},
"success": {
"type": "string"
},
"user_id": {
"type": "string"
},
"user_key": {
"type": "string"
}
}
},
"handler.Upgrade.response": {
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/models.ShortCompatMessage"
},
"message": {
"type": "string"
},
"success": {
"type": "string"
}
}
},
"handler.pingResponse": {
"type": "object",
"properties": {
"info": {
"$ref": "#/definitions/handler.pingResponseInfo"
},
"message": {
"type": "string"
}
}
},
"handler.pingResponseInfo": {
"type": "object",
"properties": {
"addr": {
"type": "string"
},
"headers": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "string"
}
}
},
"method": {
"type": "string"
},
"request": {
"type": "string"
},
"uri": {
"type": "string"
}
}
},
"models.CompatMessage": {
"type": "object",
"properties": {
"body": {
"type": "string"
},
"priority": {
"type": "integer"
},
"scn_msg_id": {
"type": "string"
},
"timestamp": {
"type": "integer"
},
"title": {
"type": "string"
},
"usr_msg_id": {
"type": "string"
}
}
},
"models.ShortCompatMessage": {
"type": "object",
"properties": {
"body": {
"type": "string"
},
"priority": {
"type": "integer"
},
"scn_msg_id": {
"type": "string"
},
"timestamp": {
"type": "integer"
},
"title": {
"type": "string"
},
"trimmed": {
"type": "boolean"
},
"usr_msg_id": {
"type": "string"
}
}
}
}
}

551
server/swagger/swagger.yaml Normal file
View File

@@ -0,0 +1,551 @@
basePath: /api/
definitions:
ginresp.errBody:
properties:
message:
type: string
success:
type: boolean
type: object
ginresp.internAPIError:
properties:
errid:
type: integer
message:
type: string
success:
type: boolean
type: object
ginresp.sendAPIError:
properties:
errhighlight:
type: integer
error:
type: integer
message:
type: string
success:
type: boolean
type: object
handler.Ack.response:
properties:
message:
type: string
new_ack:
type: integer
prev_ack:
type: integer
success:
type: string
type: object
handler.DatabaseTest.response:
properties:
libVersion:
type: string
libVersionNumber:
type: integer
sourceID:
type: string
success:
type: boolean
type: object
handler.Expand.response:
properties:
data:
$ref: '#/definitions/models.ShortCompatMessage'
message:
type: string
success:
type: string
type: object
handler.Health.response:
properties:
status:
type: string
type: object
handler.Info.response:
properties:
fcm_token_set:
type: boolean
is_pro:
type: string
message:
type: string
quota:
type: string
quota_max:
type: string
success:
type: string
unack_count:
type: integer
user_id:
type: string
user_key:
type: string
type: object
handler.Register.response:
properties:
is_pro:
type: string
message:
type: string
quota:
type: string
quota_max:
type: string
success:
type: string
user_id:
type: string
user_key:
type: string
type: object
handler.Requery.response:
properties:
count:
type: integer
data:
items:
$ref: '#/definitions/models.CompatMessage'
type: array
message:
type: string
success:
type: string
type: object
handler.Send.response:
properties:
message:
type: string
success:
type: string
type: object
handler.Update.response:
properties:
is_pro:
type: string
message:
type: string
quota:
type: string
quota_max:
type: string
success:
type: string
user_id:
type: string
user_key:
type: string
type: object
handler.Upgrade.response:
properties:
data:
$ref: '#/definitions/models.ShortCompatMessage'
message:
type: string
success:
type: string
type: object
handler.pingResponse:
properties:
info:
$ref: '#/definitions/handler.pingResponseInfo'
message:
type: string
type: object
handler.pingResponseInfo:
properties:
addr:
type: string
headers:
additionalProperties:
items:
type: string
type: array
type: object
method:
type: string
request:
type: string
uri:
type: string
type: object
models.CompatMessage:
properties:
body:
type: string
priority:
type: integer
scn_msg_id:
type: string
timestamp:
type: integer
title:
type: string
usr_msg_id:
type: string
type: object
models.ShortCompatMessage:
properties:
body:
type: string
priority:
type: integer
scn_msg_id:
type: string
timestamp:
type: integer
title:
type: string
trimmed:
type: boolean
usr_msg_id:
type: string
type: object
host: scn.blackforestbytes.com
info:
contact: {}
description: API for SCN
title: SimpleCloudNotifier API
version: "2.0"
paths:
/ack.php:
get:
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 id
in: query
name: scn_msg_id
required: true
type: string
responses:
"200":
description: OK
schema:
$ref: '#/definitions/handler.Ack.response'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/ginresp.internAPIError'
summary: Acknowledge that a message was received
/db-test:
get:
responses:
"200":
description: OK
schema:
$ref: '#/definitions/handler.DatabaseTest.response'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/ginresp.errBody'
/expand.php:
get:
responses:
"200":
description: OK
schema:
$ref: '#/definitions/handler.Expand.response'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/ginresp.internAPIError'
summary: Get a whole (potentially truncated) message
/health:
get:
responses:
"200":
description: OK
schema:
$ref: '#/definitions/handler.Health.response'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/ginresp.errBody'
/info.php:
get:
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
responses:
"200":
description: OK
schema:
$ref: '#/definitions/handler.Info.response'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/ginresp.internAPIError'
summary: Get information about the current user
/ping:
delete:
responses:
"200":
description: OK
schema:
$ref: '#/definitions/handler.pingResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/ginresp.errBody'
get:
responses:
"200":
description: OK
schema:
$ref: '#/definitions/handler.pingResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/ginresp.errBody'
patch:
responses:
"200":
description: OK
schema:
$ref: '#/definitions/handler.pingResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/ginresp.errBody'
post:
responses:
"200":
description: OK
schema:
$ref: '#/definitions/handler.pingResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/ginresp.errBody'
put:
responses:
"200":
description: OK
schema:
$ref: '#/definitions/handler.pingResponse'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/ginresp.errBody'
/register.php:
get:
parameters:
- description: the (android) fcm token
in: query
name: fcm_token
required: true
type: string
- description: if the user is a paid account
enum:
- "true"
- "false"
in: query
name: pro
required: true
type: string
- description: the (android) IAP token
in: query
name: pro_token
required: true
type: string
responses:
"200":
description: OK
schema:
$ref: '#/definitions/handler.Register.response'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/ginresp.internAPIError'
summary: Register a new account
/requery.php:
get:
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
responses:
"200":
description: OK
schema:
$ref: '#/definitions/handler.Requery.response'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/ginresp.internAPIError'
summary: Return all not-acknowledged messages
/send.php:
post:
description: all aeguments can either be supplied in the query or in the json
body
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
name: content
type: string
- description: The message priority
in: query
name: priority
type: string
- description: The message idempotency id
in: query
name: msg_id
type: string
- description: The message timestamp
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
name: title
required: true
schema:
type: string
- description: The message content
in: body
name: content
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
responses:
"200":
description: OK
schema:
$ref: '#/definitions/handler.Send.response'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/ginresp.sendAPIError'
summary: Send a message
/update.php:
get:
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 (android) fcm token
in: query
name: fcm_token
required: true
type: string
responses:
"200":
description: OK
schema:
$ref: '#/definitions/handler.Update.response'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/ginresp.internAPIError'
summary: Set the fcm-token (android)
/upgrade.php:
get:
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: if the user is a paid account
enum:
- "true"
- "false"
in: query
name: pro
required: true
type: string
- description: the (android) IAP token
in: query
name: pro_token
required: true
type: string
responses:
"200":
description: OK
schema:
$ref: '#/definitions/handler.Upgrade.response'
"500":
description: Internal Server Error
schema:
$ref: '#/definitions/ginresp.internAPIError'
summary: Upgrade a free account to a paid account
swagger: "2.0"