fix: Fix JSON validation not working (#682)

This commit is contained in:
Rémi Marseault 2023-02-28 06:24:28 +01:00 committed by GitHub
parent 4e0cc41eb6
commit 2784ab97cf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 225 additions and 255 deletions

100
package-lock.json generated
View file

@ -8,10 +8,10 @@
"name": "vuetorrent",
"version": "1.3.2",
"dependencies": {
"ajv": "^8.12.0",
"apexcharts": "^3.35.0",
"axios": "^0.26.1",
"dayjs": "^1.10.4",
"jsonschema": "^1.4.1",
"lodash": "^4.17.21",
"quick-score": "^0.2.0",
"typeface-roboto": "^1.1.13",
@ -1865,6 +1865,28 @@
"url": "https://opencollective.com/eslint"
}
},
"node_modules/@eslint/eslintrc/node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dev": true,
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
"dev": true
},
"node_modules/@eslint/js": {
"version": "8.35.0",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.35.0.tgz",
@ -2641,14 +2663,13 @@
}
},
"node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dev": true,
"version": "8.12.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
"integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"json-schema-traverse": "^1.0.0",
"require-from-string": "^2.0.2",
"uri-js": "^4.2.2"
},
"funding": {
@ -4082,6 +4103,22 @@
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
"node_modules/eslint/node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dev": true,
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/eslint/node_modules/eslint-scope": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz",
@ -4104,6 +4141,12 @@
"node": ">=4.0"
}
},
"node_modules/eslint/node_modules/json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
"dev": true
},
"node_modules/espree": {
"version": "9.4.1",
"resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz",
@ -4215,8 +4258,7 @@
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"dev": true
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
},
"node_modules/fast-diff": {
"version": "1.2.0",
@ -5341,10 +5383,9 @@
"dev": true
},
"node_modules/json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
"dev": true
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
},
"node_modules/json-stable-stringify-without-jsonify": {
"version": "1.0.1",
@ -5394,14 +5435,6 @@
"node": ">=0.10.0"
}
},
"node_modules/jsonschema": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.1.tgz",
"integrity": "sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==",
"engines": {
"node": "*"
}
},
"node_modules/kind-of": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
@ -5959,7 +5992,6 @@
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
"integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
"dev": true,
"engines": {
"node": ">=6"
}
@ -6120,7 +6152,6 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
@ -7081,7 +7112,6 @@
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
"dev": true,
"dependencies": {
"punycode": "^2.1.0"
}
@ -7670,22 +7700,6 @@
"integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
"dev": true
},
"node_modules/workbox-build/node_modules/ajv": {
"version": "8.12.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
"integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
"dev": true,
"dependencies": {
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
"require-from-string": "^2.0.2",
"uri-js": "^4.2.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/workbox-build/node_modules/estree-walker": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz",
@ -7712,12 +7726,6 @@
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/workbox-build/node_modules/json-schema-traverse": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
"dev": true
},
"node_modules/workbox-build/node_modules/magic-string": {
"version": "0.25.9",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz",

View file

@ -11,10 +11,10 @@
"start": "npm run dev"
},
"dependencies": {
"ajv": "^8.12.0",
"apexcharts": "^3.35.0",
"axios": "^0.26.1",
"dayjs": "^1.10.4",
"jsonschema": "^1.4.1",
"lodash": "^4.17.21",
"quick-score": "^0.2.0",
"typeface-roboto": "^1.1.13",

View file

@ -226,8 +226,8 @@ import { Qbit } from '@/services/qbit'
import { LOCALES } from '@/lang/locales'
import { General } from '@/mixins'
import { TitleOptions } from '@/enums/vuetorrent'
import { validate } from 'jsonschema'
import { StoreState } from '@/schemas'
import Ajv from 'ajv'
import { StoreStateSchema } from '@/schemas'
export default {
name: 'VueTorrent-General',
@ -257,16 +257,14 @@ export default {
},
importSettings() {
let isValidJson = true
let userState
try {
userState = JSON.parse(this.settingsField)
let validatorResult = validate(userState, StoreState)
console.log(userState)
console.log(validatorResult)
if (!validatorResult.valid)
isValidJson = false
const userState = JSON.parse(this.settingsField)
const ajv = new Ajv()
const validate = ajv.compile(StoreStateSchema)
isValidJson = validate(userState)
} catch (e) {
console.log(e)
console.error(e)
isValidJson = false
}

View file

@ -0,0 +1,23 @@
export enum DashboardProperty {
SIZE = 'Size',
PROGRESS = 'Progress',
DOWNLOAD = 'Download',
UPLOAD = 'Upload',
DOWNLOADED = 'Downloaded',
DIRECTORY = 'Directory',
UPLOADED = 'Uploaded',
ETA = 'ETA',
PEERS = 'Peers',
SEEDS = 'Seeds',
STATUS = 'Status',
RAIO = 'Ratio',
TRACKER = 'Tracker',
CATEGORY = 'Category',
TAGS = 'Tags',
ADDED_ON = 'AddedOn',
AVAILABILITY = 'Availability',
LAST_ACTIVITY = 'LastActivity',
COMPLETED_ON = 'CompletedOn',
GLOBAL_SPEED = 'GlobalSpeed',
GLOBAL_VOLUME = 'GlobalVolume'
}

View file

@ -1,4 +1,5 @@
import { DashboardProperty } from './DashboardProperty'
import { TorrentState } from './TorrentState'
import { TitleOptions } from './TitleOptions'
export { TorrentState, TitleOptions }
export { DashboardProperty, TorrentState, TitleOptions }

View file

@ -1,170 +0,0 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"sort_options": {
"type": "object",
"properties": {
"isCustomSortEnabled": {
"type": "boolean"
},
"sort": {
"type": "string"
},
"reverse": {
"type": "boolean"
},
"filter": {
"type": ["string", "null"]
},
"category": {
"type": ["string", "null"]
},
"tag": {
"type": ["string", "null"]
},
"tracker": {
"type": ["string", "null"]
}
},
"required": [
"isCustomSortEnabled",
"sort",
"reverse",
"filter",
"category",
"tag",
"tracker"
]
},
"webuiSettings": {
"type": "object",
"properties": {
"lang": {
"type": "string"
},
"darkTheme": {
"type": "boolean"
},
"showFreeSpace": {
"type": "boolean"
},
"showSpeedGraph": {
"type": "boolean"
},
"showSessionStat": {
"type": "boolean"
},
"showAlltimeStat": {
"type": "boolean"
},
"showCurrentSpeed": {
"type": "boolean"
},
"showTrackerFilter": {
"type": "boolean"
},
"showSpeedInTitle": {
"type": "boolean"
},
"deleteWithFiles": {
"type": "boolean"
},
"title": {
"type": "string"
},
"rightDrawer": {
"type": "boolean"
},
"topPagination": {
"type": "boolean"
},
"paginationSize": {
"type": "integer"
},
"dateFormat": {
"type": "string"
},
"openSideBarOnStart": {
"type": "boolean"
},
"busyTorrentProperties": {
"type": "array",
"items": [
{
"type": "object",
"properties": {
"name": {
"type": "string"
},
"active": {
"type": "boolean"
},
"label": {
"type": "string"
}
},
"required": [
"name",
"active",
"label"
]
}
]
},
"doneTorrentProperties": {
"type": "array",
"items": [
{
"type": "object",
"properties": {
"name": {
"type": "string"
},
"active": {
"type": "boolean"
},
"label": {
"type": "string"
}
},
"required": [
"name",
"active",
"label"
]
}
]
}
},
"required": [
"lang",
"darkTheme",
"showFreeSpace",
"showSpeedGraph",
"showSessionStat",
"showAlltimeStat",
"showCurrentSpeed",
"showTrackerFilter",
"showSpeedInTitle",
"deleteWithFiles",
"title",
"rightDrawer",
"topPagination",
"paginationSize",
"dateFormat",
"openSideBarOnStart",
"busyTorrentProperties",
"doneTorrentProperties"
]
},
"authenticated": {
"type": "boolean"
}
},
"required": [
"sort_options",
"webuiSettings",
"authenticated"
]
}

110
src/schemas/StoreState.ts Normal file
View file

@ -0,0 +1,110 @@
import { JSONSchemaType } from 'ajv'
import { StoreState } from '@/types/vuetorrent'
import { DashboardProperty, TitleOptions } from '@/enums/vuetorrent'
export const StoreStateSchema: JSONSchemaType<StoreState> = {
type: "object",
properties: {
authenticated: {type: "boolean"},
sort_options: {
type: "object",
properties: {
isCustomSortEnabled: {type: "boolean"},
sort: {type: "string"},
reverse: {type: "boolean"},
filter: {type: "string", nullable: true},
category: {type: "string", nullable: true},
tag: {type: "string", nullable: true},
tracker: {type: "string", nullable: true},
},
required: [
"isCustomSortEnabled",
"sort",
"reverse",
"filter",
"category",
"tag",
"tracker"
]
},
webuiSettings: {
type: "object",
properties: {
lang: {type: "string"},
darkTheme: {type: "boolean"},
showFreeSpace: {type: "boolean"},
showSpeedGraph: {type: "boolean"},
showSessionStat: {type: "boolean"},
showAlltimeStat: {type: "boolean"},
showCurrentSpeed: {type: "boolean"},
showTrackerFilter: {type: "boolean"},
showSpeedInTitle: {type: "boolean"},
deleteWithFiles: {type: "boolean"},
title: {
type: "string",
enum: [
TitleOptions.DEFAULT,
TitleOptions.GLOBAL_SPEED,
TitleOptions.FIRST_TORRENT_STATUS
]
},
rightDrawer: {type: "boolean"},
topPagination: {type: "boolean"},
paginationSize: {type: "number"},
dateFormat: {type: "string"},
openSideBarOnStart: {type: "boolean"},
busyTorrentProperties: {$ref: "/schemas/dashboardProperties"},
doneTorrentProperties: {$ref: "/schemas/dashboardProperties"}
}
}
},
required: [
"sort_options",
"webuiSettings",
"authenticated"
],
additionalProperties: false,
$defs: {
DashboardProperties: {
$id: "/schemas/dashboardProperties",
type: "array",
uniqueItems: true,
minItems: 21,
maxItems: 21,
items: {
type: "object",
properties: {
name: {
type: "string",
enum: [
DashboardProperty.SIZE,
DashboardProperty.PROGRESS,
DashboardProperty.DOWNLOAD,
DashboardProperty.UPLOAD,
DashboardProperty.DOWNLOADED,
DashboardProperty.DIRECTORY,
DashboardProperty.UPLOADED,
DashboardProperty.ETA,
DashboardProperty.PEERS,
DashboardProperty.SEEDS,
DashboardProperty.STATUS,
DashboardProperty.RAIO,
DashboardProperty.TRACKER,
DashboardProperty.CATEGORY,
DashboardProperty.TAGS,
DashboardProperty.ADDED_ON,
DashboardProperty.AVAILABILITY,
DashboardProperty.LAST_ACTIVITY,
DashboardProperty.COMPLETED_ON,
DashboardProperty.GLOBAL_SPEED,
DashboardProperty.GLOBAL_VOLUME
]
},
active: {type: "boolean"}
},
required: ["name", "active"]
}
}
}
}

View file

@ -1,3 +1,3 @@
import StoreState from './StoreState.json'
import {StoreStateSchema} from './StoreState'
export { StoreState }
export { StoreStateSchema }

View file

@ -6,8 +6,8 @@ import getters from './getters'
import mutations from './mutations'
import type { StoreState } from '@/types/vuetorrent'
import { Status } from '@/models'
import { TitleOptions } from '@/enums/vuetorrent'
import {AppPreferences} from "@/types/qbit/models";
import { TitleOptions, DashboardProperty } from '@/enums/vuetorrent'
import {AppPreferences} from '@/types/qbit/models'
const vuexPersist = new VuexPersist<StoreState>({
key: 'vuetorrent',
@ -23,27 +23,27 @@ Vue.use(Vuex)
// noinspection DuplicatedCode
const propertiesTemplate = [
{ name: 'Size', active: true },
{ name: 'Progress', active: true },
{ name: 'Download', active: true },
{ name: 'Upload', active: true },
{ name: 'Downloaded', active: true },
{ name: 'Directory', active: false },
{ name: 'Uploaded', active: true },
{ name: 'ETA', active: true },
{ name: 'Peers', active: true },
{ name: 'Seeds', active: true },
{ name: 'Status', active: true },
{ name: 'Ratio', active: true },
{ name: 'Tracker', active: false },
{ name: 'Category', active: true },
{ name: 'Tags', active: true },
{ name: 'AddedOn', active: true },
{ name: 'Availability', active: true },
{ name: 'LastActivity', active: false },
{ name: 'CompletedOn', active: false },
{ name: 'GlobalSpeed', active: false },
{ name: 'GlobalVolume', active: false }
{ name: DashboardProperty.SIZE, active: true },
{ name: DashboardProperty.PROGRESS, active: true },
{ name: DashboardProperty.DOWNLOAD, active: true },
{ name: DashboardProperty.UPLOAD, active: true },
{ name: DashboardProperty.DOWNLOADED, active: true },
{ name: DashboardProperty.DIRECTORY, active: false },
{ name: DashboardProperty.UPLOADED, active: true },
{ name: DashboardProperty.ETA, active: true },
{ name: DashboardProperty.PEERS, active: true },
{ name: DashboardProperty.SEEDS, active: true },
{ name: DashboardProperty.STATUS, active: true },
{ name: DashboardProperty.RAIO, active: true },
{ name: DashboardProperty.TRACKER, active: false },
{ name: DashboardProperty.CATEGORY, active: true },
{ name: DashboardProperty.TAGS, active: true },
{ name: DashboardProperty.ADDED_ON, active: true },
{ name: DashboardProperty.AVAILABILITY, active: true },
{ name: DashboardProperty.LAST_ACTIVITY, active: false },
{ name: DashboardProperty.COMPLETED_ON, active: false },
{ name: DashboardProperty.GLOBAL_SPEED, active: false },
{ name: DashboardProperty.GLOBAL_VOLUME, active: false }
]
export default new Vuex.Store<StoreState>({

View file

@ -1,7 +1,7 @@
import type { TitleOptions } from '@/enums/vuetorrent'
import type { DashboardProperty, TitleOptions } from '@/enums/vuetorrent'
export interface TorrentProperty {
name: string
name: DashboardProperty
active: boolean
}