Skip to content

Commit

Permalink
RESTful API (#389)
Browse files Browse the repository at this point in the history
  • Loading branch information
nmanovic authored Apr 23, 2019
1 parent 7ed31ca commit ae6a489
Show file tree
Hide file tree
Showing 107 changed files with 10,492 additions and 18,821 deletions.
5 changes: 5 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,16 @@
"airbnb",
],
"rules": {
"no-new": [0],
"class-methods-use-this": [0],
"no-restricted-properties": [0, {
"object": "Math",
"property": "pow",
}],
"no-param-reassign": [0],
"no-underscore-dangle": ["error", { "allowAfterThis": true }],
"no-restricted-syntax": [0, {"selector": "ForOfStatement"}],
"no-continue": [0],
"no-unsafe-innerhtml/no-unsafe-innerhtml": 1,
// This rule actual for user input data on the node.js environment mainly.
"security/detect-object-injection": 0,
Expand Down
87 changes: 51 additions & 36 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"version": "0.2.0",
"configurations": [
{
"name": "CVAT Server",
"name": "server",
"type": "python",
"request": "launch",
"stopOnEntry": false,
Expand All @@ -15,19 +15,14 @@
"args": [
"runserver",
"--noreload",
"--nothreading",
"--insecure",
"127.0.0.1:7000"
],
"debugOptions": [
"RedirectOutput",
"DjangoDebugging"
],
"cwd": "${workspaceFolder}",
"envFile": "${workspaceFolder}/.env",
"django": true,
"cwd": "${workspaceFolder}"
},
{
"name": "CVAT Client",
"name": "client",
"type": "chrome",
"request": "launch",
"url": "http://localhost:7000/",
Expand All @@ -40,7 +35,7 @@
}
},
{
"name": "CVAT RQ - default",
"name": "RQ - default",
"type": "python",
"request": "launch",
"stopOnEntry": false,
Expand All @@ -53,17 +48,12 @@
"--worker-class",
"cvat.simpleworker.SimpleWorker",
],
"debugOptions": [
"RedirectOutput",
"DjangoDebugging"
],
"django": true,
"cwd": "${workspaceFolder}",
"env": {},
"envFile": "${workspaceFolder}/.env",

"env": {}
},
{
"name": "CVAT RQ - low",
"name": "RQ - low",
"type": "python",
"request": "launch",
"debugStdLib": true,
Expand All @@ -76,16 +66,12 @@
"--worker-class",
"cvat.simpleworker.SimpleWorker",
],
"debugOptions": [
"RedirectOutput",
"DjangoDebugging"
],
"django": true,
"cwd": "${workspaceFolder}",
"env": {},
"envFile": "${workspaceFolder}/.env",
"env": {}
},
{
"name": "CVAT git",
"name": "git",
"type": "python",
"request": "launch",
"debugStdLib": true,
Expand All @@ -95,24 +81,53 @@
"args": [
"update_git_states"
],
"debugOptions": [
"RedirectOutput",
"DjangoDebugging"
"django": true,
"cwd": "${workspaceFolder}",
"env": {}
},
{
"name": "migrate",
"type": "python",
"request": "launch",
"debugStdLib": true,
"stopOnEntry": false,
"pythonPath": "${config:python.pythonPath}",
"program": "${workspaceRoot}/manage.py",
"args": [
"migrate"
],
"django": true,
"cwd": "${workspaceFolder}",
"env": {}
},
{
"name": "tests",
"type": "python",
"request": "launch",
"debugStdLib": true,
"stopOnEntry": false,
"pythonPath": "${config:python.pythonPath}",
"program": "${workspaceRoot}/manage.py",
"args": [
"test",
"--settings",
"cvat.settings.testing",
"cvat/apps/engine",
],
"django": true,
"cwd": "${workspaceFolder}",
"env": {},
"envFile": "${workspaceFolder}/.env",
"env": {}
},
],
"compounds": [
{
"name": "CVAT Debugging",
"name": "debugging",
"configurations": [
"CVAT Client",
"CVAT Server",
"CVAT RQ - default",
"CVAT RQ - low",
"CVAT git",
"client",
"server",
"RQ - default",
"RQ - low",
"git",
]
}
]
Expand Down
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Ability to rotate images/video in the client part (Ctrl+R, Shift+Ctrl+R shortcuts) (#305)
- The ReID application for automatic bounding box merging has been added (#299)
- Keyboard shortcuts to switch next/previous default shape type (box, polygon etc) [Alt + <, Alt + >] (#316)
- Converter for VOC now supports interpolation tracks
- Converter for VOC now supports interpolation tracks
- REST API (/api/v1/*, /api/docs)
- Semi-automatic semantic segmentation with the [Deep Extreme Cut](http://www.vision.ee.ethz.ch/~cvlsegmentation/dextr/) work

### Changed
Expand Down
51 changes: 35 additions & 16 deletions components/analytics/logstash/logstash.conf
Original file line number Diff line number Diff line change
Expand Up @@ -10,62 +10,81 @@ filter {
# 1. Decode the event from json in 'message' field
# 2. Remove unnecessary field from it
# 3. Type it as client

mutate {
rename => { "message" => "source_message" }
}

json {
source => "message"
source => "source_message"
}

date {
match => ["timestamp", "UNIX", "UNIX_MS"]
remove_field => "timestamp"
match => ["time", "ISO8601"]
remove_field => "time"
}

if [event] == "Send exception" {
if [payload] {
ruby {
code => "
event.get('payload').each { |key, value|
event.set(key, value)
}
"
}
}

if [name] == "Send exception" {
aggregate {
task_id => "%{userid}_%{application}_%{message}_%{filename}_%{line}"
task_id => "%{username}_%{message}_%{filename}_%{line}"
code => "
require 'time'

map['userid'] ||= event.get('userid');
map['application'] ||= event.get('application');
map['username'] ||= event.get('username');
map['error'] ||= event.get('message');
map['filename'] ||= event.get('filename');
map['line'] ||= event.get('line');
map['task'] ||= event.get('task');

map['task_id'] ||= event.get('task_id');
map['job_id'] ||= event.get('job_id');
map['error_count'] ||= 0;
map['error_count'] += 1;

map['aggregated_stack'] ||= '';
map['aggregated_stack'] += event.get('stack') + '\n\n\n';"

map['aggregated_stack'] += event.get('stack') + '\n\n\n';
"
timeout => 3600
timeout_tags => ['aggregated_exception']
push_map_as_event_on_timeout => true
}
}

prune {
blacklist_names => ["level", "host", "logger_name", "message", "path",
"port", "stack_info"]
blacklist_names => ["level", "host", "logger_name", "path",
"port", "stack_info", "payload", "source_message"]
}

mutate {
replace => { "type" => "client" }
copy => {
"job_id" => "task"
"username" => "userid"
"name" => "event"
}
}
} else if [logger_name] =~ /cvat.server/ {
# 1. Remove 'logger_name' field and create 'task' field
# 2. Remove unnecessary field from it
# 3. Type it as server
if [logger_name] =~ /cvat\.server\.task_[0-9]+/ {
mutate {
rename => { "logger_name" => "task" }
gsub => [ "task", "cvat.server.task_", "" ]
rename => { "logger_name" => "task_id" }
gsub => [ "task_id", "cvat.server.task_", "" ]
}

# Need to split the mutate because otherwise the conversion
# doesn't work.
mutate {
convert => { "task" => "integer" }
convert => { "task_id" => "integer" }
}
}

Expand Down
5 changes: 5 additions & 0 deletions cvat/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,8 @@
#
# SPDX-License-Identifier: MIT

from cvat.utils.version import get_version

VERSION = (0, 4, 0, 'alpha', 0)

__version__ = get_version(VERSION)
68 changes: 68 additions & 0 deletions cvat/apps/authentication/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@

import os
from django.conf import settings
from django.db.models import Q
import rules
from . import AUTH_ROLE
from rest_framework.permissions import BasePermission

def register_signals():
from django.db.models.signals import post_migrate, post_save
Expand Down Expand Up @@ -67,6 +69,11 @@ def is_job_annotator(db_user, db_job):
return has_rights

# AUTH PERMISSIONS RULES
rules.add_perm('engine.role.user', has_user_role)
rules.add_perm('engine.role.admin', has_admin_role)
rules.add_perm('engine.role.annotator', has_annotator_role)
rules.add_perm('engine.role.observer', has_observer_role)

rules.add_perm('engine.task.create', has_admin_role | has_user_role)
rules.add_perm('engine.task.access', has_admin_role | has_observer_role |
is_task_owner | is_task_annotator)
Expand All @@ -78,3 +85,64 @@ def is_job_annotator(db_user, db_job):
is_job_owner | is_job_annotator)
rules.add_perm('engine.job.change', has_admin_role | is_job_owner |
is_job_annotator)

class AdminRolePermission(BasePermission):
# pylint: disable=no-self-use
def has_permission(self, request, view):
return request.user.has_perm("engine.role.admin")

class UserRolePermission(BasePermission):
# pylint: disable=no-self-use
def has_permission(self, request, view):
return request.user.has_perm("engine.role.user")

class AnnotatorRolePermission(BasePermission):
# pylint: disable=no-self-use
def has_permission(self, request, view):
return request.user.has_perm("engine.role.annotator")

class ObserverRolePermission(BasePermission):
# pylint: disable=no-self-use
def has_permission(self, request, view):
return request.user.has_perm("engine.role.observer")

class TaskCreatePermission(BasePermission):
# pylint: disable=no-self-use
def has_permission(self, request, view):
return request.user.has_perm("engine.task.create")

class TaskAccessPermission(BasePermission):
# pylint: disable=no-self-use
def has_object_permission(self, request, view, obj):
return request.user.has_perm("engine.task.access", obj)

class TaskGetQuerySetMixin(object):
def get_queryset(self):
queryset = super().get_queryset()
user = self.request.user
# Don't filter queryset for admin, observer and detail methods
if has_admin_role(user) or has_observer_role(user) or self.detail:
return queryset
else:
return queryset.filter(Q(owner=user) | Q(assignee=user) |
Q(segment__job__assignee=user) | Q(assignee=None)).distinct()

class TaskChangePermission(BasePermission):
# pylint: disable=no-self-use
def has_object_permission(self, request, view, obj):
return request.user.has_perm("engine.task.change", obj)

class TaskDeletePermission(BasePermission):
# pylint: disable=no-self-use
def has_object_permission(self, request, view, obj):
return request.user.has_perm("engine.task.delete", obj)

class JobAccessPermission(BasePermission):
# pylint: disable=no-self-use
def has_object_permission(self, request, view, obj):
return request.user.has_perm("engine.job.access", obj)

class JobChangePermission(BasePermission):
# pylint: disable=no-self-use
def has_object_permission(self, request, view, obj):
return request.user.has_perm("engine.job.change", obj)
Loading

0 comments on commit ae6a489

Please sign in to comment.