Welcome | Get started | Dive | Contribute | Topics | Reference | Changes | More
Uploads with expiration date management¶
The lino_xl.lib.uploads
plugin extends lino.modlib.uploads
by
adding “expiration date management” for uploads. This is used by social agents
(“coaches”) to manage certain documents about their “clients”. For example the
coach might want to get a reminder when the driving license of one of their
clients is about to expire.
This plugin requires the lino_xl.lib.clients
plugin.
Side note: Code snippets (lines starting with >>>
) in this document get
tested as part of our development workflow. The following
initialization snippet tells you which demo project is being used in
this document.
>>> import lino
>>> lino.startup('lino_book.projects.avanti1.settings')
>>> from lino.api.doctest import *
Although this plugin requires the lino_xl.lib.clients
plugin, it does not
declare this dependency because making it automatic would
cause changes in the menu item ordering in Lino Welfare.
The plugin has two custom settings, which are the default values for the
MyExpiringUploads
table:
>>> dd.plugins.uploads.expiring_start
-30
>>> dd.plugins.uploads.expiring_end
365
The demo_coach is the user who uploaded all demo uploads.
>>> dd.plugins.clients.demo_coach
'nathalie'
We have two social workers Nathalie and Nelly.
>>> rt.show("users.AllUsers")
========== ===================== ============ ===========
Username User type First name Last name
---------- --------------------- ------------ -----------
audrey 300 (Auditor)
laura 100 (Teacher) Laura Lieblig
martina 400 (Coordinator)
nathalie 200 (Social worker)
nelly 200 (Social worker)
robin 900 (Administrator) Robin Rood
rolf 900 (Administrator) Rolf Rompen
romain 900 (Administrator) Romain Raffault
sandra 410 (Secretary)
========== ===================== ============ ===========
>>> rt.login('robin').show("uploads.Uploads", column_names="id user project project__user end_date needed")
==== ============= ============================= ================= ============= ========
ID Uploaded by Client Primary coach Valid until Needed
---- ------------- ----------------------------- ----------------- ------------- --------
10 nathalie ABDALLAH Aáish (127/robin) Robin Rood 22/03/2018 Yes
9 nathalie ABDALLAH Aáish (127/robin) Robin Rood 22/03/2018 No
8 nathalie ABDALLA Aádil (120/rolf) Rolf Rompen 12/03/2018 No
7 nathalie ABDALLA Aádil (120/rolf) Rolf Rompen 12/03/2018 No
6 nathalie ABBASI Aáishá (118/romain) Romain Raffault 02/03/2018 No
5 nathalie ABBASI Aáishá (118/romain) Romain Raffault 02/03/2018 No
4 nathalie ABBAS Aábid (115/nelly) nelly 20/02/2018 Yes
3 nathalie ABBAS Aábid (115/nelly) nelly 20/02/2018 Yes
2 nathalie ABAD Aábdeen (114/nathalie) nathalie 10/02/2018 Yes
1 nathalie ABAD Aábdeen (114/nathalie) nathalie 10/02/2018 Yes
==== ============= ============================= ================= ============= ========
Note that uploads #4 and #3 were not uploaded by the client’s primary coach.
>>> obj = rt.models.uploads.Upload.objects.get(pk=3)
>>> prj = rt.models.avanti.Client.objects.get(pk=114)
>>> rec = rt.login("nathalie").spawn(uploads.UploadsByProject, master_instance=prj).elem2rec_detailed(obj)
>>> print(rec['disable_delete'])
None
Nelly (another social worker) and Sandra (secretary) can also modify the upload
>>> rec = rt.login("nelly").spawn(uploads.UploadsByProject, master_instance=prj).elem2rec_detailed(obj)
>>> print(rec['disable_delete'])
None
>>> rec = rt.login("sandra").spawn(uploads.UploadsByProject, master_instance=prj).elem2rec_detailed(obj)
>>> print(rec['disable_delete'])
None
But Laura (a teacher) cannot edit them:
>>> rec = rt.login("laura").spawn(uploads.UploadsByProject, master_instance=prj).elem2rec_detailed(obj)
>>> print(rec['disable_delete'])
You have no permission to delete this row.
Note about security. You might wonder why Sandra is able to see data that she isn’t allow to see:
>>> print(rec['data']['project'])
ABBAS Aábid (115/nelly)
This is not a security issue because we are at the command line interface where access rights are not verified. If Sandra would do a manual AJAX call, she would not be able to see data that she isn’t allow to see. Here is the proof:
>>> test_client.force_login(rt.login("laura").user)
>>> url = "/api/avanti/Clients?fmt=json&&limit=23&start=0"
>>> test_client.get(url)
Forbidden (Permission denied): /api/avanti/Clients
Traceback (most recent call last):
...
django.core.exceptions.PermissionDenied: As 100 (Teacher) you have no view permission for this action.
<HttpResponseForbidden status_code=403, "text/html; charset=utf-8">
>>> url = "/api/avanti/uploads.UploadsByProject?fmt=json&&limit=23&start=0&mt=31&mk=114"
>>> test_client.get(url)
Not Found: /api/avanti/uploads.UploadsByProject
<HttpResponseNotFound status_code=404, "text/html; charset=utf-8">
Extended uploads¶
- class lino_xl.lib.uploads.Upload¶
Extends
lino.modlib.uploads.Upload
by adding some fields.- start_date¶
- end_date¶
Date until which the original document is valid.
- needed¶
Whether the responsible user should be reminded when validity of this upload reaches its end.
My expiring upload files¶
When you want Lino to remind you when some important document (e.g. a driving
licence) is about to expire, then you should store the document’s expiry date in
the Upload.end_date
field and check the Upload.needed
field.
- class lino_xl.lib.uploads.MyExpiringUploads¶
Shows the upload files that are marked as
Upload.needed
and whoseUpload.end_date
is within a given period.
>>> rt.login(dd.plugins.clients.demo_coach).show("uploads.MyExpiringUploads")
============================= ================== ==================== ============= ============ ============= ========
Client Upload type Description Uploaded by Valid from Valid until Needed
----------------------------- ------------------ -------------------- ------------- ------------ ------------- --------
ABAD Aábdeen (114/nathalie) Residence permit Residence permit 1 nathalie 10/02/2018 Yes
ABAD Aábdeen (114/nathalie) Work permit Work permit 2 nathalie 10/02/2018 Yes
============================= ================== ==================== ============= ============ ============= ========
>>> rt.login('sandra').show("uploads.MyExpiringUploads")
No data to display