summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEgor Yurtaev <yurtaev.egor@gmail.com>2014-12-04 18:47:21 +0600
committerEgor Yurtaev <yurtaev.egor@gmail.com>2014-12-25 12:56:47 +0600
commit6494f9adbd021ce60eb8b3e7adcef99bcc91c6a1 (patch)
tree42ae37420ae96c6f71aa2837e27f53c0cc757d07
parentcdface5a74454742dd1498a13ee8be0dc4926288 (diff)
downloadomaha-server-6494f9adbd021ce60eb8b3e7adcef99bcc91c6a1.zip
omaha-server-6494f9adbd021ce60eb8b3e7adcef99bcc91c6a1.tar.gz
omaha-server-6494f9adbd021ce60eb8b3e7adcef99bcc91c6a1.tar.bz2
add 'crash' app
-rw-r--r--omaha_server/.coveragerc2
-rw-r--r--omaha_server/crash/__init__.py0
-rw-r--r--omaha_server/crash/admin.py30
-rw-r--r--omaha_server/crash/forms.py28
-rw-r--r--omaha_server/crash/migrations/0001_initial.py34
-rw-r--r--omaha_server/crash/migrations/__init__.py0
-rw-r--r--omaha_server/crash/models.py31
-rw-r--r--omaha_server/crash/tests/__init__.py0
-rw-r--r--omaha_server/crash/tests/test_models.py45
-rw-r--r--omaha_server/crash/tests/test_views.py51
-rw-r--r--omaha_server/crash/urls.py28
-rw-r--r--omaha_server/crash/views.py48
-rw-r--r--omaha_server/omaha_server/settings.py2
-rw-r--r--omaha_server/omaha_server/settings_test.py2
-rw-r--r--omaha_server/omaha_server/urls.py1
15 files changed, 301 insertions, 1 deletions
diff --git a/omaha_server/.coveragerc b/omaha_server/.coveragerc
index 61e020e..0f4ac3c 100644
--- a/omaha_server/.coveragerc
+++ b/omaha_server/.coveragerc
@@ -6,4 +6,6 @@ omit =
omaha/models.py
omaha/forms.py
omaha/admin.py
+ crash/admin.py
+ crash/models.py
data_file = ../.coverage \ No newline at end of file
diff --git a/omaha_server/crash/__init__.py b/omaha_server/crash/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/omaha_server/crash/__init__.py
diff --git a/omaha_server/crash/admin.py b/omaha_server/crash/admin.py
new file mode 100644
index 0000000..d32d5be
--- /dev/null
+++ b/omaha_server/crash/admin.py
@@ -0,0 +1,30 @@
+# coding: utf8
+
+"""
+This software is licensed under the Apache 2 license, quoted below.
+
+Copyright 2014 Crystalnix Limited
+
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+"""
+
+from django.contrib import admin
+from models import Crash
+
+
+@admin.register(Crash)
+class CrashAdmin(admin.ModelAdmin):
+ list_display = ('app_id', 'user_id', 'created', 'modified',)
+ list_display_links = ('app_id', 'user_id', 'created', 'modified',)
+ list_filter = ('created',)
+ search_fields = ('app_id', 'user_id',)
diff --git a/omaha_server/crash/forms.py b/omaha_server/crash/forms.py
new file mode 100644
index 0000000..c6e0ee5
--- /dev/null
+++ b/omaha_server/crash/forms.py
@@ -0,0 +1,28 @@
+# coding: utf8
+
+"""
+This software is licensed under the Apache 2 license, quoted below.
+
+Copyright 2014 Crystalnix Limited
+
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+"""
+
+from django import forms
+from models import Crash
+
+
+class CrashFrom(forms.ModelForm):
+ class Meta:
+ model = Crash
+ exclude = []
diff --git a/omaha_server/crash/migrations/0001_initial.py b/omaha_server/crash/migrations/0001_initial.py
new file mode 100644
index 0000000..f456fc4
--- /dev/null
+++ b/omaha_server/crash/migrations/0001_initial.py
@@ -0,0 +1,34 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+import django.utils.timezone
+import jsonfield.fields
+import django_extensions.db.fields
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Crash',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('created', django_extensions.db.fields.CreationDateTimeField(default=django.utils.timezone.now, verbose_name='created', editable=False, blank=True)),
+ ('modified', django_extensions.db.fields.ModificationDateTimeField(default=django.utils.timezone.now, verbose_name='modified', editable=False, blank=True)),
+ ('mini_dump', models.FileField(upload_to=b'minidump/%Y/%m/%d')),
+ ('app_id', models.CharField(max_length=38, null=True, blank=True)),
+ ('user_id', models.CharField(max_length=38, null=True, blank=True)),
+ ('meta', jsonfield.fields.JSONField(help_text=b'JSON format', null=True, verbose_name=b'Meta-information', blank=True)),
+ ],
+ options={
+ 'ordering': ('-modified', '-created'),
+ 'abstract': False,
+ 'get_latest_by': 'modified',
+ },
+ bases=(models.Model,),
+ ),
+ ]
diff --git a/omaha_server/crash/migrations/__init__.py b/omaha_server/crash/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/omaha_server/crash/migrations/__init__.py
diff --git a/omaha_server/crash/models.py b/omaha_server/crash/models.py
new file mode 100644
index 0000000..263ae82
--- /dev/null
+++ b/omaha_server/crash/models.py
@@ -0,0 +1,31 @@
+# coding: utf8
+
+"""
+This software is licensed under the Apache 2 license, quoted below.
+
+Copyright 2014 Crystalnix Limited
+
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+"""
+
+from django.db import models
+from django_extensions.db.models import TimeStampedModel
+
+from jsonfield import JSONField
+
+
+class Crash(TimeStampedModel):
+ mini_dump = models.FileField(upload_to='minidump/%Y/%m/%d')
+ app_id = models.CharField(max_length=38, null=True, blank=True)
+ user_id = models.CharField(max_length=38, null=True, blank=True)
+ meta = JSONField(verbose_name='Meta-information', help_text='JSON format', null=True, blank=True)
diff --git a/omaha_server/crash/tests/__init__.py b/omaha_server/crash/tests/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/omaha_server/crash/tests/__init__.py
diff --git a/omaha_server/crash/tests/test_models.py b/omaha_server/crash/tests/test_models.py
new file mode 100644
index 0000000..5a3e160
--- /dev/null
+++ b/omaha_server/crash/tests/test_models.py
@@ -0,0 +1,45 @@
+# coding: utf8
+
+"""
+This software is licensed under the Apache 2 license, quoted below.
+
+Copyright 2014 Crystalnix Limited
+
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+"""
+
+from django import test
+from django.core.files.uploadedfile import SimpleUploadedFile
+
+from crash.models import Crash
+
+
+class CrashModelTest(test.TestCase):
+ def test_model(self):
+ meta = dict(
+ lang='en',
+ version='1.0.0.1',
+ )
+ app_id = '{D0AB2EBC-931B-4013-9FEB-C9C4C2225C8C}',
+ user_id = '{2882CF9B-D9C2-4edb-9AAF-8ED5FCF366F7}',
+ obj = Crash.objects.create(
+ app_id=app_id,
+ user_id=user_id,
+ mini_dump=SimpleUploadedFile('./dump.dat', False),
+ meta=meta,
+ )
+
+ self.assertTrue(obj)
+ self.assertDictEqual(obj.meta, meta)
+ self.assertEqual(obj.app_id, app_id)
+ self.assertEqual(obj.user_id, user_id)
diff --git a/omaha_server/crash/tests/test_views.py b/omaha_server/crash/tests/test_views.py
new file mode 100644
index 0000000..7db7f5b
--- /dev/null
+++ b/omaha_server/crash/tests/test_views.py
@@ -0,0 +1,51 @@
+# coding: utf8
+
+"""
+This software is licensed under the Apache 2 license, quoted below.
+
+Copyright 2014 Crystalnix Limited
+
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+"""
+
+from django import test
+from django.core.files.uploadedfile import SimpleUploadedFile
+from django.core.urlresolvers import reverse
+
+from crash.models import Crash
+
+
+class CrashViewTest(test.TestCase):
+ def test_view(self):
+ meta = dict(
+ lang='en',
+ version='1.0.0.1',
+ )
+ mini_dump_file = SimpleUploadedFile("minidump.dat", "content")
+ form_data = dict(
+ app_id='{D0AB2EBC-931B-4013-9FEB-C9C4C2225C8C}',
+ user_id='{2882CF9B-D9C2-4edb-9AAF-8ED5FCF366F7}',
+ mini_dump=mini_dump_file,
+ )
+
+ form_data.update(meta)
+
+ self.assertEqual(Crash.objects.all().count(), 0)
+ response = self.client.post(reverse('crash'), form_data)
+ self.assertEqual(response.status_code, 201)
+ self.assertEqual(Crash.objects.all().count(), 1)
+ obj = Crash.objects.get()
+ self.assertEqual(response.content, str(obj.pk))
+ self.assertDictEqual(obj.meta, meta)
+ self.assertEqual(obj.app_id, form_data['app_id'])
+ self.assertEqual(obj.user_id, form_data['user_id'])
diff --git a/omaha_server/crash/urls.py b/omaha_server/crash/urls.py
new file mode 100644
index 0000000..1cef528
--- /dev/null
+++ b/omaha_server/crash/urls.py
@@ -0,0 +1,28 @@
+# coding: utf8
+
+"""
+This software is licensed under the Apache 2 license, quoted below.
+
+Copyright 2014 Crystalnix Limited
+
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+"""
+
+from django.conf.urls import patterns, url
+
+from views import CrashFormView
+
+
+urlpatterns = patterns('',
+ url(r'^service/crash_report/$', CrashFormView.as_view(), name='crash'),
+)
diff --git a/omaha_server/crash/views.py b/omaha_server/crash/views.py
new file mode 100644
index 0000000..7f86e24
--- /dev/null
+++ b/omaha_server/crash/views.py
@@ -0,0 +1,48 @@
+# coding: utf8
+
+"""
+This software is licensed under the Apache 2 license, quoted below.
+
+Copyright 2014 Crystalnix Limited
+
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations under
+the License.
+"""
+
+import json
+
+from django.views.generic import FormView
+from django.views.decorators.csrf import csrf_exempt
+from django.http import HttpResponse
+from forms import CrashFrom
+
+
+class CrashFormView(FormView):
+ http_method_names = ('post',)
+ form_class = CrashFrom
+
+ @csrf_exempt
+ def dispatch(self, *args, **kwargs):
+ return super(CrashFormView, self).dispatch(*args, **kwargs)
+
+ def form_valid(self, form):
+ meta = self.request.POST.dict()
+ meta.pop("app_id", None)
+ meta.pop("user_id", None)
+ obj = form.save(commit=False)
+ if meta:
+ obj.meta = meta
+ obj.save()
+ return HttpResponse(obj.pk, status=201)
+
+ def form_invalid(self, form):
+ return HttpResponse(json.dumps(form.errors), status=400, content_type='application/json')
diff --git a/omaha_server/omaha_server/settings.py b/omaha_server/omaha_server/settings.py
index 59d44ed..e8e3362 100644
--- a/omaha_server/omaha_server/settings.py
+++ b/omaha_server/omaha_server/settings.py
@@ -26,6 +26,7 @@ SUIT_CONFIG = {
'MENU': (
'sites',
{'app': 'omaha', 'label': 'Omaha', 'icon': 'icon-refresh'},
+ {'app': 'crash', 'label': 'Crash reports', 'icon': 'icon-fire'},
{'label': 'Statistics', 'url': 'omaha_statistics', 'icon': 'icon-star'},
),
}
@@ -68,6 +69,7 @@ INSTALLED_APPS = (
'django_tables2',
'omaha',
+ 'crash',
)
MIDDLEWARE_CLASSES = (
diff --git a/omaha_server/omaha_server/settings_test.py b/omaha_server/omaha_server/settings_test.py
index c1dbc45..7c40832 100644
--- a/omaha_server/omaha_server/settings_test.py
+++ b/omaha_server/omaha_server/settings_test.py
@@ -13,7 +13,7 @@ TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'
NOSE_ARGS = [
'--with-coverage',
- '--cover-package=omaha_server,omaha',
+ '--cover-package=omaha_server,omaha,crash',
'--cover-inclusive',
'--with-doctest',
]
diff --git a/omaha_server/omaha_server/urls.py b/omaha_server/omaha_server/urls.py
index e334ef2..abd5ac2 100644
--- a/omaha_server/omaha_server/urls.py
+++ b/omaha_server/omaha_server/urls.py
@@ -5,6 +5,7 @@ from django.contrib import admin
urlpatterns = patterns('',
url(r'', include('omaha.urls')),
+ url(r'', include('crash.urls')),
url(r'^admin/', include(admin.site.urls)),
)