mirror of
https://github.com/louislam/uptime-kuma.git
synced 2025-02-05 01:15:38 -05:00
Add api-spec.json5
This commit is contained in:
parent
6d2f624242
commit
d4f9acee6a
68
extra/api-spec.json5
Normal file
68
extra/api-spec.json5
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "getPushExample",
|
||||||
|
"description": "Get a push example.",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"name": "language",
|
||||||
|
"type": "string",
|
||||||
|
"description": "The programming language such as `javascript-fetch` or `python`. See the directory ./extra/push-examples for a list of available languages."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"returnType": "response-json",
|
||||||
|
"okReturn": [
|
||||||
|
{
|
||||||
|
"name": "code",
|
||||||
|
"type": "string",
|
||||||
|
"description": "The push example."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"possibleErrorReasons": [
|
||||||
|
"The parameter `language` is not available"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "checkApprise",
|
||||||
|
"description": "Check if the apprise library is installed.",
|
||||||
|
"params": [],
|
||||||
|
"returnType": "boolean",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "getSettings",
|
||||||
|
"description": "",
|
||||||
|
"params": [],
|
||||||
|
"returnType": "response-json",
|
||||||
|
"okReturn": [
|
||||||
|
{
|
||||||
|
"name": "data",
|
||||||
|
"type": "object",
|
||||||
|
"description": "The setting object. It does not contain default values."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"possibleErrorReasons": [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "changePassword",
|
||||||
|
"description": "",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"name": "password",
|
||||||
|
"type": "object",
|
||||||
|
"description": "The password object with the following properties: `currentPassword` and `newPassword`"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"returnType": "response-json",
|
||||||
|
"okReturn": [
|
||||||
|
{
|
||||||
|
"name": "data",
|
||||||
|
"type": "object",
|
||||||
|
"description": "The setting object. It does not contain default values."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"possibleErrorReasons": [
|
||||||
|
"Incorrect current password",
|
||||||
|
"Invalid new password",
|
||||||
|
"Password is too weak"
|
||||||
|
],
|
||||||
|
}
|
||||||
|
]
|
2
package-lock.json
generated
2
package-lock.json
generated
@ -39,6 +39,7 @@
|
|||||||
"iconv-lite": "~0.6.3",
|
"iconv-lite": "~0.6.3",
|
||||||
"isomorphic-ws": "^5.0.0",
|
"isomorphic-ws": "^5.0.0",
|
||||||
"jsesc": "~3.0.2",
|
"jsesc": "~3.0.2",
|
||||||
|
"json5": "~2.2.3",
|
||||||
"jsonata": "^2.0.3",
|
"jsonata": "^2.0.3",
|
||||||
"jsonwebtoken": "~9.0.0",
|
"jsonwebtoken": "~9.0.0",
|
||||||
"jwt-decode": "~3.1.2",
|
"jwt-decode": "~3.1.2",
|
||||||
@ -13206,7 +13207,6 @@
|
|||||||
"version": "2.2.3",
|
"version": "2.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
|
||||||
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
|
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
|
||||||
"dev": true,
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"json5": "lib/cli.js"
|
"json5": "lib/cli.js"
|
||||||
},
|
},
|
||||||
|
@ -106,6 +106,7 @@
|
|||||||
"iconv-lite": "~0.6.3",
|
"iconv-lite": "~0.6.3",
|
||||||
"isomorphic-ws": "^5.0.0",
|
"isomorphic-ws": "^5.0.0",
|
||||||
"jsesc": "~3.0.2",
|
"jsesc": "~3.0.2",
|
||||||
|
"json5": "~2.2.3",
|
||||||
"jsonata": "^2.0.3",
|
"jsonata": "^2.0.3",
|
||||||
"jsonwebtoken": "~9.0.0",
|
"jsonwebtoken": "~9.0.0",
|
||||||
"jwt-decode": "~3.1.2",
|
"jwt-decode": "~3.1.2",
|
||||||
|
@ -16,6 +16,9 @@ const ioClient = require("socket.io-client").io;
|
|||||||
const Socket = require("socket.io-client").Socket;
|
const Socket = require("socket.io-client").Socket;
|
||||||
const { headerAuthMiddleware } = require("../auth");
|
const { headerAuthMiddleware } = require("../auth");
|
||||||
const jwt = require("jsonwebtoken");
|
const jwt = require("jsonwebtoken");
|
||||||
|
const fs = require("fs");
|
||||||
|
const JSON5 = require("json5");
|
||||||
|
const apiSpec = JSON5.parse(fs.readFileSync("./extra/api-spec.json5", "utf8"));
|
||||||
|
|
||||||
let router = express.Router();
|
let router = express.Router();
|
||||||
|
|
||||||
@ -142,11 +145,11 @@ router.post("/api", headerAuthMiddleware, async (request, response) => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
let result = await socketClientHandler(socket, token, requestData);
|
let result = await socketClientHandler(socket, token, requestData);
|
||||||
let status = 404;
|
let status = 200;
|
||||||
if (result.status) {
|
if (result.status) {
|
||||||
status = result.status;
|
status = result.status;
|
||||||
} else if (result.ok) {
|
} else if (typeof result === "object" && result.ok === false) {
|
||||||
status = 200;
|
status = 404;
|
||||||
}
|
}
|
||||||
response.status(status).json(result);
|
response.status(status).json(result);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -170,6 +173,50 @@ function socketClientHandler(socket, token, requestData) {
|
|||||||
socket.on("connect", () => {
|
socket.on("connect", () => {
|
||||||
socket.emit("loginByToken", token, (res) => {
|
socket.emit("loginByToken", token, (res) => {
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
|
let matched = false;
|
||||||
|
|
||||||
|
// Find the action in the API spec
|
||||||
|
for (let actionObj of apiSpec) {
|
||||||
|
|
||||||
|
// Find it
|
||||||
|
if (action === actionObj.name) {
|
||||||
|
matched = true;
|
||||||
|
let flatParams = [];
|
||||||
|
|
||||||
|
// Check if required parameters are provided
|
||||||
|
if (actionObj.params.length > 0 && !params) {
|
||||||
|
reject({
|
||||||
|
status: 400,
|
||||||
|
ok: false,
|
||||||
|
msg: "Missing \"params\" property in request body",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if required parameters are valid
|
||||||
|
for (let paramObj of actionObj.params) {
|
||||||
|
let value = params[paramObj.name];
|
||||||
|
|
||||||
|
// Check if required parameter is in a correct data type
|
||||||
|
if (typeof value !== paramObj.type) {
|
||||||
|
reject({
|
||||||
|
status: 400,
|
||||||
|
ok: false,
|
||||||
|
msg: `Parameter "${paramObj.name}" should be "${paramObj.type}". Got "${typeof value}" instead.`
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
flatParams.push(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.emit(actionObj.name, ...flatParams, (res) => {
|
||||||
|
resolve(res);
|
||||||
|
});
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (action === "getPushExample") {
|
if (action === "getPushExample") {
|
||||||
if (params.length <= 0) {
|
if (params.length <= 0) {
|
||||||
@ -183,8 +230,9 @@ function socketClientHandler(socket, token, requestData) {
|
|||||||
resolve(res);
|
resolve(res);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
if (!matched) {
|
||||||
reject({
|
reject({
|
||||||
status: 404,
|
status: 404,
|
||||||
ok: false,
|
ok: false,
|
||||||
|
@ -1255,6 +1255,10 @@ let needSetup = false;
|
|||||||
try {
|
try {
|
||||||
checkLogin(socket);
|
checkLogin(socket);
|
||||||
|
|
||||||
|
if (typeof password.currentPassword === "undefined") {
|
||||||
|
throw new Error("Incorrect current password");
|
||||||
|
}
|
||||||
|
|
||||||
if (!password.newPassword) {
|
if (!password.newPassword) {
|
||||||
throw new Error("Invalid new password");
|
throw new Error("Invalid new password");
|
||||||
}
|
}
|
||||||
|
@ -833,7 +833,7 @@ exports.checkLogin = (socket) => {
|
|||||||
*/
|
*/
|
||||||
exports.doubleCheckPassword = async (socket, currentPassword) => {
|
exports.doubleCheckPassword = async (socket, currentPassword) => {
|
||||||
if (typeof currentPassword !== "string") {
|
if (typeof currentPassword !== "string") {
|
||||||
throw new Error("Wrong data type?");
|
throw new Error("Wrong data type of current password");
|
||||||
}
|
}
|
||||||
|
|
||||||
let user = await R.findOne("user", " id = ? AND active = 1 ", [
|
let user = await R.findOne("user", " id = ? AND active = 1 ", [
|
||||||
|
@ -4,8 +4,40 @@ Content-Type: application/json
|
|||||||
|
|
||||||
{
|
{
|
||||||
"action": "getPushExample",
|
"action": "getPushExample",
|
||||||
"params": [
|
"params": {
|
||||||
"javascript-fetch"
|
"language": "javascript-fetch"
|
||||||
]
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
###
|
###
|
||||||
|
POST http://localhost:3001/api
|
||||||
|
Authorization: Bearer uk1_1HaQRETls-E5KlhB6yCtf8WJRW57KwFMuKkya-Tj
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"action": "checkApprise"
|
||||||
|
}
|
||||||
|
|
||||||
|
###
|
||||||
|
POST http://localhost:3001/api
|
||||||
|
Authorization: Bearer uk1_1HaQRETls-E5KlhB6yCtf8WJRW57KwFMuKkya-Tj
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"action": "getSettings"
|
||||||
|
}
|
||||||
|
|
||||||
|
###
|
||||||
|
POST http://localhost:3001/api
|
||||||
|
Authorization: Bearer uk1_1HaQRETls-E5KlhB6yCtf8WJRW57KwFMuKkya-Tj
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"action": "changePassword",
|
||||||
|
"params": {
|
||||||
|
"password": {
|
||||||
|
"currentPassword": "123456",
|
||||||
|
"newPassword": "1sfdsf234567"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user