seibert-media/teamvault

Creating secrets via API broken

Closed this issue · 2 comments

vain commented

On a fresh install on Ubuntu 14.04, this happens when trying to create a secret via "/api/secrets" and the following JSON:

{
    "access_policy": "any",
    "allowed_users": ["bob"],
    "description": "apitest",
    "name": "apitest",
    "needs_changing_on_leave": true,
    "password": "test",
    "url": "http://www.heise.de"
}

Error:

[2015-04-20 16:02:23,804] ERROR base: Internal Server Error: /api/secrets/
Traceback (most recent call last):
  File "/usr/local/lib/python3.4/dist-packages/django/db/backends/utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
psycopg2.IntegrityError: duplicate key value violates unique constraint "secrets_secret_pkey"
DETAIL:  Key (id)=(1) already exists.


The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/local/lib/python3.4/dist-packages/django/core/handlers/base.py", line 132, in get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/local/lib/python3.4/dist-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
    return view_func(*args, **kwargs)
  File "/usr/local/lib/python3.4/dist-packages/django/views/generic/base.py", line 71, in view
    return self.dispatch(request, *args, **kwargs)
  File "/usr/local/lib/python3.4/dist-packages/rest_framework/views.py", line 452, in dispatch
    response = self.handle_exception(exc)
  File "/usr/local/lib/python3.4/dist-packages/rest_framework/views.py", line 449, in dispatch
    response = handler(request, *args, **kwargs)
  File "/usr/local/lib/python3.4/dist-packages/rest_framework/generics.py", line 244, in post
    return self.create(request, *args, **kwargs)
  File "/usr/local/lib/python3.4/dist-packages/rest_framework/mixins.py", line 20, in create
    self.perform_create(serializer)
  File "/srv/teamvault/src/teamvault/apps/secrets/api.py", line 387, in perform_create
    instance = serializer.save()
  File "/usr/local/lib/python3.4/dist-packages/rest_framework/serializers.py", line 165, in save
    self.instance = self.create(validated_data)
  File "/srv/teamvault/src/teamvault/apps/secrets/api.py", line 267, in create
    instance = self.Meta.model.objects.create(**validated_data)
  File "/usr/local/lib/python3.4/dist-packages/django/db/models/manager.py", line 127, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/usr/local/lib/python3.4/dist-packages/django/db/models/query.py", line 348, in create
    obj.save(force_insert=True, using=self.db)
  File "/srv/teamvault/src/teamvault/apps/secrets/models.py", line 56, in save
    return super(HashIDModel, self).save(*args, **kwargs)
  File "/usr/local/lib/python3.4/dist-packages/django/db/models/base.py", line 710, in save
    force_update=force_update, update_fields=update_fields)
  File "/usr/local/lib/python3.4/dist-packages/django/db/models/base.py", line 738, in save_base
    updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
  File "/usr/local/lib/python3.4/dist-packages/django/db/models/base.py", line 822, in _save_table
    result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
  File "/usr/local/lib/python3.4/dist-packages/django/db/models/base.py", line 861, in _do_insert
    using=using, raw=raw)
  File "/usr/local/lib/python3.4/dist-packages/django/db/models/manager.py", line 127, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/usr/local/lib/python3.4/dist-packages/django/db/models/query.py", line 920, in _insert
    return query.get_compiler(using=using).execute_sql(return_id)
  File "/usr/local/lib/python3.4/dist-packages/django/db/models/sql/compiler.py", line 963, in execute_sql
    cursor.execute(sql, params)
  File "/usr/local/lib/python3.4/dist-packages/django/db/backends/utils.py", line 79, in execute
    return super(CursorDebugWrapper, self).execute(sql, params)
  File "/usr/local/lib/python3.4/dist-packages/django/db/backends/utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
  File "/usr/local/lib/python3.4/dist-packages/django/db/utils.py", line 97, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File "/usr/local/lib/python3.4/dist-packages/django/utils/six.py", line 658, in reraise
    raise value.with_traceback(tb)
  File "/usr/local/lib/python3.4/dist-packages/django/db/backends/utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
django.db.utils.IntegrityError: duplicate key value violates unique constraint "secrets_secret_pkey"
DETAIL:  Key (id)=(1) already exists.

Note that creating secrets using the web interfaces works fine.

vain commented

For whatever reason, one API call results in two INSERTs:

[2015-04-22 10:45:59,107] DEBUG utils: (0.001) INSERT INTO "secrets_secret" ("hashid", "access_policy", "content_type", "created", "created_by_id", "current_revision_id", "description", "filename", "last_read", "name", "needs_changing_on_leave", "status", "url", "username", "search_index") VALUES (NULL, 2, 1, '2015-04-22T08:45:59.106973+00:00'::timestamptz, 3, NULL, 'apitest2', NULL, '2015-04-22T08:45:59.106739+00:00'::timestamptz, 'apitest2', true, 1, 'http://www.heise.de', NULL, '') RETURNING "secrets_secret"."id"; args=(None, 2, 1, datetime.datetime(2015, 4, 22, 8, 45, 59, 106973, tzinfo=<UTC>), 3, None, 'apitest2', None, datetime.datetime(2015, 4, 22, 8, 45, 59, 106739, tzinfo=<UTC>), 'apitest2', True, 1, 'http://www.heise.de', None, '')
[2015-04-22 10:45:59,109] DEBUG utils: (0.001) UPDATE "secrets_secret" SET "search_index" = setweight(to_tsvector('pg_catalog.english', coalesce("secrets_secret"."filename", '')), 'C') || setweight(to_tsvector('pg_catalog.english', coalesce("secrets_secret"."description", '')), 'B') || setweight(to_tsvector('pg_catalog.english', coalesce("secrets_secret"."name", '')), 'A') WHERE "id" IN (2);; args=[2]
[2015-04-22 10:45:59,111] DEBUG utils: (0.000) INSERT INTO "secrets_secret" ("id", "hashid", "access_policy", "content_type", "created", "created_by_id", "current_revision_id", "description", "filename", "last_read", "name", "needs_changing_on_leave", "status", "url", "username", "search_index") VALUES (2, 'YQzJQE', 2, 1, '2015-04-22T08:45:59.110827+00:00'::timestamptz, 3, NULL, 'apitest2', NULL, '2015-04-22T08:45:59.106739+00:00'::timestamptz, 'apitest2', true, 1, 'http://www.heise.de', NULL, ''); args=(2, 'YQzJQE', 2, 1, datetime.datetime(2015, 4, 22, 8, 45, 59, 110827, tzinfo=<UTC>), 3, None, 'apitest2', None, datetime.datetime(2015, 4, 22, 8, 45, 59, 106739, tzinfo=<UTC>), 'apitest2', True, 1, 'http://www.heise.de', None, '')

The second one fails because the first one already created a row with id 2.

It’s broken since using hashids (c9faef0).

I’m a at loss here. Any help would be greatly appreciated. :)

vain commented

Hooray! Fix confirmed. :-)