auth setup fixes

This commit is contained in:
CyferShepard
2024-04-07 15:59:08 +02:00
parent 6342610e84
commit b2ba7768c8
9 changed files with 257 additions and 159 deletions

View File

@@ -412,9 +412,6 @@ class JellyfinAPI {
}
async validateSettings(url, apikey) {
if (!this.configReady) {
return [];
}
try {
const response = await axios.get(url, {
headers: {

View File

@@ -897,26 +897,4 @@ router.post("/deletePlaybackActivity", async (req, res) => {
}
});
//Jellyfin related functions
router.post("/validateSettings", async (req, res) => {
const { url, apikey } = req.body;
if (url === undefined || apikey === undefined) {
res.status(400);
res.send("URL or API Key not provided");
return;
}
var _url = url;
_url = _url.replace(/\/web\/index\.html#!\/home\.html$/, "");
if (!/^https?:\/\//i.test(url)) {
_url = "http://" + url;
}
_url = _url.replace(/\/$/, "") + "/system/configuration";
const validation = await Jellyfin.validateSettings(_url, apikey);
res.send(validation);
});
module.exports = router;

View File

@@ -83,4 +83,33 @@ router.post("/createuser", async (req, res) => {
}
});
router.post("/configSetup", async (req, res) => {
try {
const { JF_HOST, JF_API_KEY } = req.body;
const config = await new configClass().getConfig();
if (JF_HOST === undefined && JF_API_KEY === undefined) {
res.status(400);
res.send("JF_HOST and JF_API_KEY are required for configuration");
return;
}
const { rows: getConfig } = await db.query('SELECT * FROM app_config where "ID"=1');
if (config.state != null && config.state < 2) {
let query = 'UPDATE app_config SET "JF_HOST"=$1, "JF_API_KEY"=$2 where "ID"=1';
if (getConfig.length === 0) {
query = 'INSERT INTO app_config ("ID","JF_HOST","JF_API_KEY","APP_USER","APP_PASSWORD") VALUES (1,$1,$2,null,null)';
}
const { rows } = await db.query(query, [JF_HOST, JF_API_KEY]);
res.send(rows);
} else {
res.sendStatus(500);
}
} catch (error) {
console.log(error);
}
});
module.exports = router;

View File

@@ -1,14 +1,11 @@
const db = require("../db");
const moment = require('moment');
const taskstate = require('../logging/taskstate');
const moment = require("moment");
const taskstate = require("../logging/taskstate");
const {jf_logging_columns,jf_logging_mapping,} = require("../models/jf_logging");
const { jf_logging_columns, jf_logging_mapping } = require("../models/jf_logging");
const express = require("express");
const router = express.Router();
// #swagger.tags = ['Logs']
router.get("/getLogs", async (req, res) => {
try {
const { rows } = await db.query(`SELECT * FROM jf_logging order by "TimeRun" desc LIMIT 50 `);
@@ -18,72 +15,54 @@ router.get("/getLogs", async (req, res) => {
}
});
async function insertLog(uuid,triggertype,taskType)
{
async function insertLog(uuid, triggertype, taskType) {
try {
let startTime = moment();
const log=
{
"Id":uuid,
"Name":taskType,
"Type":"Task",
"ExecutionType":triggertype,
"Duration":0,
"TimeRun":startTime,
"Log":JSON.stringify([{}]),
"Result":taskstate.RUNNING
const log = {
Id: uuid,
Name: taskType,
Type: "Task",
ExecutionType: triggertype,
Duration: 0,
TimeRun: startTime,
Log: JSON.stringify([{}]),
Result: taskstate.RUNNING,
};
await db.insertBulk("jf_logging",log,jf_logging_columns);
} catch (error) {
console.log(error);
return [];
}
await db.insertBulk("jf_logging", log, jf_logging_columns);
} catch (error) {
console.log(error);
return [];
}
}
async function updateLog(uuid,data,taskstate)
{
async function updateLog(uuid, data, taskstate) {
try {
const { rows:task } = await db.query(
`SELECT "TimeRun" FROM jf_logging WHERE "Id" = '${uuid}';`
);
const { rows: task } = await db.query(`SELECT "TimeRun" FROM jf_logging WHERE "Id" = '${uuid}';`);
if (task.length === 0) {
console.log("Unable to find task to update");
}else{
} else {
let endtime = moment();
let startTime = moment(task[0].TimeRun);
let duration = endtime.diff(startTime, 'seconds');
const log=
{
"Id":uuid,
"Name":"NULL Placeholder",
"Type":"Task",
"ExecutionType":"NULL Placeholder",
"Duration":duration,
"TimeRun":startTime,
"Log":JSON.stringify(data),
"Result":taskstate
let duration = endtime.diff(startTime, "seconds");
const log = {
Id: uuid,
Name: "NULL Placeholder",
Type: "Task",
ExecutionType: "NULL Placeholder",
Duration: duration,
TimeRun: startTime,
Log: JSON.stringify(data),
Result: taskstate,
};
await db.insertBulk("jf_logging",log,jf_logging_columns);
}
} catch (error) {
console.log(error);
return [];
}
await db.insertBulk("jf_logging", log, jf_logging_columns);
}
} catch (error) {
console.log(error);
return [];
}
}
module.exports =
{router,insertLog,updateLog};
module.exports = { router, insertLog, updateLog };

View File

@@ -163,4 +163,48 @@ router.get("/getRecentlyAdded", async (req, res) => {
}
});
//Jellyfin related functions
router.post("/validateSettings", async (req, res) => {
const { url, apikey } = req.body;
if (url === undefined || apikey === undefined) {
res.status(400);
res.send("URL or API Key not provided");
return;
}
const urlRegex = new RegExp(
"^((http|https):\\/\\/)?" + // optional protocol
"((([a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])\\.)+" + // subdomain
"([a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])" + // domain name
"|([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}))" + // OR ip (v4) address
"(\\:[0-9]+)?$", // port
"i" // case-insensitive
);
const isValidUrl = (string) => urlRegex.test(string);
console.log(url, isValidUrl(url));
if (!isValidUrl(url)) {
res.status(400);
res.send({
isValid: false,
errorMessage: "Invalid URL",
});
return;
}
var _url = url;
_url = _url.replace(/\/web\/index\.html#!\/home\.html$/, "");
if (!/^https?:\/\//i.test(url)) {
_url = "http://" + url;
}
_url = _url.replace(/\/$/, "") + "/system/configuration";
const validation = await Jellyfin.validateSettings(_url, apikey);
res.send(validation);
});
module.exports = router;

View File

@@ -19,10 +19,10 @@ const knexConfig = require("./migrations");
const authRouter = require("./routes/auth");
const apiRouter = require("./routes/api");
const proxyRouter = require("./routes/proxy");
const syncRouter = require("./routes/sync");
const { router: syncRouter } = require("./routes/sync");
const statsRouter = require("./routes/stats");
const backupRouter = require("./routes/backup");
const logRouter = require("./routes/logging");
const { router: backupRouter } = require("./routes/backup");
const { router: logRouter } = require("./routes/logging");
const utilsRouter = require("./routes/utils");
// tasks
@@ -61,16 +61,16 @@ app.use("/proxy", proxyRouter, () => {
app.use("/api", authenticate, apiRouter, () => {
/* #swagger.tags = ['API']*/
}); // mount the API router at /api, with JWT middleware
app.use("/sync", authenticate, syncRouter.router, () => {
app.use("/sync", authenticate, syncRouter, () => {
/* #swagger.tags = ['Sync']*/
}); // mount the API router at /sync, with JWT middleware
app.use("/stats", authenticate, statsRouter, () => {
/* #swagger.tags = ['Stats']*/
}); // mount the API router at /stats, with JWT middleware
app.use("/backup", authenticate, backupRouter.router, () => {
app.use("/backup", authenticate, backupRouter, () => {
/* #swagger.tags = ['Backup']*/
}); // mount the API router at /backup, with JWT middleware
app.use("/logs", authenticate, logRouter.router, () => {
app.use("/logs", authenticate, logRouter, () => {
/* #swagger.tags = ['Logs']*/
}); // mount the API router at /logs, with JWT middleware
app.use("/utils", authenticate, utilsRouter, () => {

View File

@@ -1,55 +1,58 @@
const swaggerAutogen = require('swagger-autogen')();
const swaggerAutogen = require("swagger-autogen")();
const outputFile = './swagger.json';
const endpointsFiles = ['./server.js'];
const outputFile = "./swagger.json";
const endpointsFiles = ["./server.js"];
const config = {
info: {
title: 'Jellystat API Documentation',
description: '',
info: {
title: "Jellystat API Documentation",
description: "",
},
tags: [
{
name: "API",
description: "Jellystat API Endpoints",
},
tags: [
{
name: 'API',
description: 'Jellystat API Endpoints',
},
{
name: 'Auth',
description: 'Jellystat Auth Endpoints',
},
{
name: 'Proxy',
description: 'Jellyfin Proxied Endpoints',
},
{
name: 'Stats',
description: 'Jellystat Statisitc Endpoints',
},
{
name: 'Backup',
description: 'Jellystat Backup/Restore Endpoints',
},
{
name: 'Logs',
description: 'Jellystat Log Endpoints',
},
],
host: '',
schemes: ['http', 'https'],
securityDefinitions: {
apiKey: {
type: 'apiKey',
name: 'x-api-token',
in: 'header',
},
{
name: "Auth",
description: "Jellystat Auth Endpoints",
},
security: [
{
apiKey: [],
},
],
{
name: "Proxy",
description: "Jellyfin Proxied Endpoints",
},
{
name: "Stats",
description: "Jellystat Statisitc Endpoints",
},
{
name: "Sync",
description: "Jellystat Sync Endpoints",
},
{
name: "Backup",
description: "Jellystat Backup/Restore Endpoints",
},
{
name: "Logs",
description: "Jellystat Log Endpoints",
},
],
host: "",
schemes: ["http", "https"],
securityDefinitions: {
apiKey: {
type: "apiKey",
name: "x-api-token",
in: "header",
},
},
security: [
{
apiKey: [],
},
],
};
module.exports = config;
swaggerAutogen(outputFile, endpointsFiles, config);

View File

@@ -24,6 +24,10 @@
"name": "Stats",
"description": "Jellystat Statisitc Endpoints"
},
{
"name": "Sync",
"description": "Jellystat Sync Endpoints"
},
{
"name": "Backup",
"description": "Jellystat Backup/Restore Endpoints"
@@ -90,6 +94,9 @@
"responses": {
"200": {
"description": "OK"
},
"500": {
"description": "Internal Server Error"
}
}
}
@@ -130,6 +137,42 @@
}
}
},
"/auth/configSetup": {
"post": {
"tags": [
"Auth"
],
"description": "",
"parameters": [
{
"name": "body",
"in": "body",
"schema": {
"type": "object",
"properties": {
"JF_HOST": {
"example": "any"
},
"JF_API_KEY": {
"example": "any"
}
}
}
}
],
"responses": {
"200": {
"description": "OK"
},
"400": {
"description": "Bad Request"
},
"500": {
"description": "Internal Server Error"
}
}
}
},
"/proxy/web/assets/img/devices/": {
"get": {
"tags": [
@@ -312,6 +355,39 @@
}
}
},
"/proxy/validateSettings": {
"post": {
"tags": [
"Proxy"
],
"description": "",
"parameters": [
{
"name": "body",
"in": "body",
"schema": {
"type": "object",
"properties": {
"url": {
"example": "any"
},
"apikey": {
"example": "any"
}
}
}
}
],
"responses": {
"200": {
"description": "OK"
},
"400": {
"description": "Bad Request"
}
}
}
},
"/api/getconfig": {
"get": {
"tags": [
@@ -1874,7 +1950,7 @@
}
}
},
"/api/validateSettings": {
"/api/deletePlaybackActivity": {
"post": {
"tags": [
"API"
@@ -1902,10 +1978,7 @@
"schema": {
"type": "object",
"properties": {
"url": {
"example": "any"
},
"apikey": {
"ids": {
"example": "any"
}
}
@@ -1927,6 +2000,9 @@
},
"404": {
"description": "Not Found"
},
"503": {
"description": "Service Unavailable"
}
}
}

View File

@@ -38,21 +38,18 @@ function Setup() {
}
async function validateSettings(_url, _apikey) {
const result = await axios.post(
"/api/validateSettings",
{
const result = await axios
.post("/proxy/validateSettings", {
url: _url,
apikey: _apikey,
},
{
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
}
);
})
.catch((error) => {
return error.response;
});
let data = result.data;
console.log(result);
console.log(data);
return { isValid: data.isValid, errorMessage: data.errorMessage };
}
@@ -70,12 +67,7 @@ function Setup() {
// Send a POST request to /api/setconfig/ with the updated configuration
axios
.post("/api/setconfig/", formValues, {
headers: {
Authorization: `Bearer ${config.token}`,
"Content-Type": "application/json",
},
})
.post("/auth/configSetup/", formValues)
.then(async () => {
setsubmitButtonText(i18next.t("SETTINGS_SAVED"));
setProcessing(false);