mirror of
https://github.com/louislam/uptime-kuma.git
synced 2024-11-27 16:54:04 +00:00
Add api-spec.json5
This commit is contained in:
parent
6d2f624242
commit
d4f9acee6a
7 changed files with 162 additions and 9 deletions
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",
|
||||
"isomorphic-ws": "^5.0.0",
|
||||
"jsesc": "~3.0.2",
|
||||
"json5": "~2.2.3",
|
||||
"jsonata": "^2.0.3",
|
||||
"jsonwebtoken": "~9.0.0",
|
||||
"jwt-decode": "~3.1.2",
|
||||
|
@ -13206,7 +13207,6 @@
|
|||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
|
||||
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"json5": "lib/cli.js"
|
||||
},
|
||||
|
|
|
@ -106,6 +106,7 @@
|
|||
"iconv-lite": "~0.6.3",
|
||||
"isomorphic-ws": "^5.0.0",
|
||||
"jsesc": "~3.0.2",
|
||||
"json5": "~2.2.3",
|
||||
"jsonata": "^2.0.3",
|
||||
"jsonwebtoken": "~9.0.0",
|
||||
"jwt-decode": "~3.1.2",
|
||||
|
|
|
@ -16,6 +16,9 @@ const ioClient = require("socket.io-client").io;
|
|||
const Socket = require("socket.io-client").Socket;
|
||||
const { headerAuthMiddleware } = require("../auth");
|
||||
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();
|
||||
|
||||
|
@ -142,11 +145,11 @@ router.post("/api", headerAuthMiddleware, async (request, response) => {
|
|||
|
||||
try {
|
||||
let result = await socketClientHandler(socket, token, requestData);
|
||||
let status = 404;
|
||||
let status = 200;
|
||||
if (result.status) {
|
||||
status = result.status;
|
||||
} else if (result.ok) {
|
||||
status = 200;
|
||||
} else if (typeof result === "object" && result.ok === false) {
|
||||
status = 404;
|
||||
}
|
||||
response.status(status).json(result);
|
||||
} catch (e) {
|
||||
|
@ -170,6 +173,50 @@ function socketClientHandler(socket, token, requestData) {
|
|||
socket.on("connect", () => {
|
||||
socket.emit("loginByToken", token, (res) => {
|
||||
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 (params.length <= 0) {
|
||||
|
@ -183,8 +230,9 @@ function socketClientHandler(socket, token, requestData) {
|
|||
resolve(res);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if (!matched) {
|
||||
reject({
|
||||
status: 404,
|
||||
ok: false,
|
||||
|
|
|
@ -1255,6 +1255,10 @@ let needSetup = false;
|
|||
try {
|
||||
checkLogin(socket);
|
||||
|
||||
if (typeof password.currentPassword === "undefined") {
|
||||
throw new Error("Incorrect current password");
|
||||
}
|
||||
|
||||
if (!password.newPassword) {
|
||||
throw new Error("Invalid new password");
|
||||
}
|
||||
|
|
|
@ -833,7 +833,7 @@ exports.checkLogin = (socket) => {
|
|||
*/
|
||||
exports.doubleCheckPassword = async (socket, currentPassword) => {
|
||||
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 ", [
|
||||
|
|
|
@ -4,8 +4,40 @@ Content-Type: application/json
|
|||
|
||||
{
|
||||
"action": "getPushExample",
|
||||
"params": [
|
||||
"javascript-fetch"
|
||||
]
|
||||
"params": {
|
||||
"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…
Reference in a new issue