[CVAT-UI] Better labels validation and fixed React warning (#1727)

* Better validation

* Temporary ID generation for created labels and attributes (fixes React warning)

* Updated version and changelog

* Fixed bug with existing labels
main
Boris Sekachev 6 years ago committed by GitHub
parent b4600be3f7
commit 3adaf7eaec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Shortcut to change color of an activated shape in new UI (Enter) (<https://github.com/opencv/cvat/pull/1683>)
- Shortcut to switch split mode (<https://github.com/opencv/cvat/pull/1683>)
- Built-in search for labels when create an object or change a label (<https://github.com/opencv/cvat/pull/1683>)
- Better validation of labels and attributes in raw viewer (<https://github.com/opencv/cvat/pull/1727>)
### Changed
- Removed information about e-mail from the basic user information (<https://github.com/opencv/cvat/pull/1627>)
@ -32,6 +33,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Wrong rexex for account name validation (<https://github.com/opencv/cvat/pull/1667>)
- Wrong description on register view for the username field (<https://github.com/opencv/cvat/pull/1667>)
- Wrong resolution for resizing a shape (<https://github.com/opencv/cvat/pull/1667>)
- React warning because of not unique keys in labels viewer (<https://github.com/opencv/cvat/pull/1727>)
### Security
- SQL injection in Django `CVE-2020-9402` (<https://github.com/opencv/cvat/pull/1657>)

@ -1,6 +1,6 @@
{
"name": "cvat-ui",
"version": "1.3.0",
"version": "1.3.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

@ -1,6 +1,6 @@
{
"name": "cvat-ui",
"version": "1.3.0",
"version": "1.3.1",
"description": "CVAT single-page application",
"main": "src/index.tsx",
"scripts": {

@ -18,6 +18,59 @@ export interface Label {
let id = 0;
function validateParsedAttribute(attr: Attribute): void {
if (typeof (attr.name) !== 'string') {
throw new Error(`Type of attribute name must be a string. Got value ${attr.name}`);
}
if (!['number', 'undefined'].includes(typeof (attr.id))) {
throw new Error(`Attribute: "${attr.name}". `
+ `Type of attribute id must be a number or undefined. Got value ${attr.id}`);
}
if (!['checkbox', 'number', 'text', 'radio', 'select'].includes((attr.input_type || '').toLowerCase())) {
throw new Error(`Attribute: "${attr.name}". `
+ `Unknown input type: ${attr.input_type}`);
}
if (typeof (attr.mutable) !== 'boolean') {
throw new Error(`Attribute: "${attr.name}". `
+ `Mutable flag must be a boolean value. Got value ${attr.mutable}`);
}
if (!Array.isArray(attr.values)) {
throw new Error(`Attribute: "${attr.name}". `
+ `Attribute values must be an array. Got type ${typeof (attr.values)}`);
}
for (const value of attr.values) {
if (typeof (value) !== 'string') {
throw new Error(`Attribute: "${attr.name}". `
+ `Each value must be a string. Got value ${value}`);
}
}
}
export function validateParsedLabel(label: Label): void {
if (typeof (label.name) !== 'string') {
throw new Error(`Type of label name must be a string. Got value ${label.name}`);
}
if (!['number', 'undefined'].includes(typeof (label.id))) {
throw new Error(`Label "${label.name}". `
+ `Type of label id must be only a number or undefined. Got value ${label.id}`);
}
if (!Array.isArray(label.attributes)) {
throw new Error(`Label "${label.name}". `
+ `attributes must be an array. Got type ${typeof (label.attributes)}`);
}
for (const attr of label.attributes) {
validateParsedAttribute(attr);
}
}
export function idGenerator(): number {
return --id;
}

@ -12,6 +12,8 @@ import Form, { FormComponentProps } from 'antd/lib/form/Form';
import {
Label,
Attribute,
validateParsedLabel,
idGenerator,
} from './common';
type Props = FormComponentProps & {
@ -22,7 +24,18 @@ type Props = FormComponentProps & {
class RawViewer extends React.PureComponent<Props> {
private validateLabels = (_: any, value: string, callback: any): void => {
try {
JSON.parse(value);
const parsed = JSON.parse(value);
if (!Array.isArray(parsed)) {
callback('Field is expected to be a JSON array');
}
for (const label of parsed) {
try {
validateParsedLabel(label);
} catch (error) {
callback(error.toString());
}
}
} catch (error) {
callback(error.toString());
}
@ -39,7 +52,14 @@ class RawViewer extends React.PureComponent<Props> {
e.preventDefault();
form.validateFields((error, values): void => {
if (!error) {
onSubmit(JSON.parse(values.labels));
const parsed = JSON.parse(values.labels);
for (const label of parsed) {
label.id = label.id || idGenerator();
for (const attr of label.attributes) {
attr.id = attr.id || idGenerator();
}
}
onSubmit(parsed);
}
});
};

Loading…
Cancel
Save