0001-toulouse_axel-lock-unlock-locked-endpoints-38133.patch
passerelle/contrib/toulouse_axel/migrations/0003_auto_20191205_0948.py | ||
---|---|---|
1 |
# -*- coding: utf-8 -*- |
|
2 |
from __future__ import unicode_literals |
|
3 | ||
4 |
from django.db import migrations, models |
|
5 |
import django.db.models.deletion |
|
6 | ||
7 | ||
8 |
class Migration(migrations.Migration): |
|
9 | ||
10 |
dependencies = [ |
|
11 |
('toulouse_axel', '0002_auto_20191122_0946'), |
|
12 |
] |
|
13 | ||
14 |
operations = [ |
|
15 |
migrations.CreateModel( |
|
16 |
name='Lock', |
|
17 |
fields=[ |
|
18 |
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
|
19 |
('key', models.CharField(max_length=256)), |
|
20 |
('lock_date', models.DateTimeField(auto_now_add=True)), |
|
21 |
('locker', models.CharField(blank=True, max_length=256)), |
|
22 |
('resource', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='toulouse_axel.ToulouseAxel')), |
|
23 |
], |
|
24 |
), |
|
25 |
migrations.AlterUniqueTogether( |
|
26 |
name='lock', |
|
27 |
unique_together=set([('resource', 'key')]), |
|
28 |
), |
|
29 |
] |
passerelle/contrib/toulouse_axel/models.py | ||
---|---|---|
132 | 132 |
LINK_SCHEMA['properties'].pop('IDPERSONNE') |
133 | 133 |
LINK_SCHEMA['required'].remove('IDPERSONNE') |
134 | 134 | |
135 |
@endpoint( |
|
136 |
description=_('Lock a resource'), |
|
137 |
perm='can_access', |
|
138 |
parameters={ |
|
139 |
'key': {'description': _('Key of the resource to lock')}, |
|
140 |
'locker': {'description': _('Identifier of the locker (can be empty)')} |
|
141 |
}) |
|
142 |
def lock(self, request, key, locker): |
|
143 |
if not key: |
|
144 |
raise APIError('key is empty', err='bad-request', http_status=400) |
|
145 |
lock, created = Lock.objects.get_or_create(resource=self, key=key, defaults={'locker': locker}) |
|
146 |
return {'key': key, 'locked': True, 'locker': lock.locker, 'lock_date': lock.lock_date} |
|
147 | ||
148 |
@endpoint( |
|
149 |
description=_('Unlock a resource'), |
|
150 |
perm='can_access', |
|
151 |
parameters={ |
|
152 |
'key': {'description': _('Key of the resource to unlock')}, |
|
153 |
}) |
|
154 |
def unlock(self, request, key): |
|
155 |
try: |
|
156 |
lock = Lock.objects.get(resource=self, key=key) |
|
157 |
lock.delete() |
|
158 |
return {'key': key, 'locked': False, 'locker': lock.locker, 'lock_date': lock.lock_date} |
|
159 |
except Lock.DoesNotExist: |
|
160 |
return {'key': key, 'locked': False} |
|
161 | ||
162 |
@endpoint( |
|
163 |
description=_('Get the lock status of a resource'), |
|
164 |
perm='can_access', |
|
165 |
parameters={ |
|
166 |
'key': {'description': _('Key of the resource')}, |
|
167 |
}) |
|
168 |
def locked(self, request, key): |
|
169 |
try: |
|
170 |
lock = Lock.objects.get(resource=self, key=key) |
|
171 |
return {'key': key, 'locked': True, 'locker': lock.locker, 'lock_date': lock.lock_date} |
|
172 |
except Lock.DoesNotExist: |
|
173 |
return {'key': key, 'locked': False} |
|
174 | ||
135 | 175 |
@endpoint( |
136 | 176 |
description=_('Create link between user and Toulouse Axel'), |
137 | 177 |
perm='can_access', |
... | ... | |
216 | 256 | |
217 | 257 |
class Meta: |
218 | 258 |
unique_together = ('resource', 'name_id') |
259 | ||
260 | ||
261 |
class Lock(models.Model): |
|
262 |
resource = models.ForeignKey(ToulouseAxel, on_delete=models.CASCADE) |
|
263 |
key = models.CharField(max_length=256) |
|
264 |
lock_date = models.DateTimeField(auto_now_add=True) |
|
265 |
locker = models.CharField(max_length=256, blank=True) |
|
266 | ||
267 |
class Meta: |
|
268 |
unique_together = ('resource', 'key') |
tests/test_toulouse_axel.py | ||
---|---|---|
23 | 23 |
from passerelle.contrib.toulouse_axel.models import ( |
24 | 24 |
AxelError, |
25 | 25 |
Link, |
26 |
Lock, |
|
26 | 27 |
ToulouseAxel, |
27 | 28 |
ref_famille_dui, |
28 | 29 |
ref_verif_dui, |
... | ... | |
48 | 49 |
} |
49 | 50 | |
50 | 51 | |
52 |
def test_lock(app, resource): |
|
53 |
resp = app.get('/toulouse-axel/test/lock?key=&locker=', status=400) |
|
54 |
assert resp.json['err_desc'] == "key is empty" |
|
55 | ||
56 |
assert Lock.objects.count() == 0 |
|
57 |
resp = app.get('/toulouse-axel/test/lock?key=foobar&locker=') |
|
58 |
assert resp.json['err'] == 0 |
|
59 |
assert resp.json['key'] == 'foobar' |
|
60 |
assert resp.json['locked'] is True |
|
61 |
assert resp.json['locker'] == '' |
|
62 |
assert resp.json['lock_date'] is not None |
|
63 |
lock_date = resp.json['lock_date'] |
|
64 |
lock = Lock.objects.latest('pk') |
|
65 |
assert lock.resource == resource |
|
66 |
assert lock.key == 'foobar' |
|
67 |
assert lock.locker == '' |
|
68 | ||
69 |
# again |
|
70 |
resp = app.get('/toulouse-axel/test/lock?key=foobar&locker=') |
|
71 |
assert resp.json['err'] == 0 |
|
72 |
assert resp.json['key'] == 'foobar' |
|
73 |
assert resp.json['locked'] is True |
|
74 |
assert Lock.objects.count() == 1 |
|
75 |
assert resp.json['locker'] == '' |
|
76 |
assert resp.json['lock_date'] == lock_date |
|
77 | ||
78 | ||
79 |
def test_lock_with_locker(app, resource): |
|
80 |
assert Lock.objects.count() == 0 |
|
81 |
resp = app.get('/toulouse-axel/test/lock?key=foobar&locker=something') |
|
82 |
assert resp.json['err'] == 0 |
|
83 |
assert resp.json['key'] == 'foobar' |
|
84 |
assert resp.json['locked'] is True |
|
85 |
assert resp.json['locker'] == 'something' |
|
86 |
assert resp.json['lock_date'] is not None |
|
87 |
lock_date = resp.json['lock_date'] |
|
88 |
lock = Lock.objects.latest('pk') |
|
89 |
assert lock.resource == resource |
|
90 |
assert lock.key == 'foobar' |
|
91 |
assert lock.locker == 'something' |
|
92 | ||
93 |
# again |
|
94 |
resp = app.get('/toulouse-axel/test/lock?key=foobar&locker=') |
|
95 |
assert resp.json['err'] == 0 |
|
96 |
assert resp.json['key'] == 'foobar' |
|
97 |
assert resp.json['locked'] is True |
|
98 |
assert Lock.objects.count() == 1 |
|
99 |
assert resp.json['locker'] == 'something' |
|
100 |
assert resp.json['lock_date'] == lock_date |
|
101 | ||
102 | ||
103 |
def test_unlock(app, resource): |
|
104 |
Lock.objects.create(resource=resource, key='foobar', locker='something') |
|
105 |
resp = app.get('/toulouse-axel/test/unlock?key=foobar') |
|
106 |
assert resp.json['err'] == 0 |
|
107 |
assert resp.json['key'] == 'foobar' |
|
108 |
assert resp.json['locked'] is False |
|
109 |
assert resp.json['locker'] == 'something' |
|
110 |
assert resp.json['lock_date'] is not None |
|
111 |
assert Lock.objects.count() == 0 |
|
112 | ||
113 |
# again |
|
114 |
resp = app.get('/toulouse-axel/test/unlock?key=foobar') |
|
115 |
assert resp.json['err'] == 0 |
|
116 |
assert resp.json['key'] == 'foobar' |
|
117 |
assert resp.json['locked'] is False |
|
118 |
assert 'locker' not in resp.json |
|
119 |
assert 'lock_date' not in resp.json |
|
120 |
assert Lock.objects.count() == 0 |
|
121 | ||
122 | ||
123 |
def test_locked(app, resource): |
|
124 |
assert Lock.objects.count() == 0 |
|
125 |
resp = app.get('/toulouse-axel/test/locked?key=foobar') |
|
126 |
assert resp.json['err'] == 0 |
|
127 |
assert resp.json['key'] == 'foobar' |
|
128 |
assert resp.json['locked'] is False |
|
129 |
assert 'locker' not in resp.json |
|
130 |
assert 'lock_date' not in resp.json |
|
131 | ||
132 |
Lock.objects.create(resource=resource, key='foobar', locker='something') |
|
133 |
resp = app.get('/toulouse-axel/test/locked?key=foobar') |
|
134 |
assert resp.json['err'] == 0 |
|
135 |
assert resp.json['key'] == 'foobar' |
|
136 |
assert resp.json['locked'] is True |
|
137 |
assert resp.json['locker'] == 'something' |
|
138 |
assert resp.json['lock_date'] is not None |
|
139 | ||
140 | ||
51 | 141 |
def test_operation_status_error(resource): |
52 | 142 |
resp = ''' |
53 | 143 |
<?xml version="1.0"?> |
54 |
- |