1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
|
%global _empty_manifest_terminate_build 0
Name: python-spkcspider
Version: 0.30
Release: 1
Summary: A secure, decentral platform for maintaining your online identity
License: MIT
URL: https://spkcspider.net
Source0: https://mirrors.aliyun.com/pypi/web/packages/4b/03/652291261dcfbe8fe39228690a52539cc0e2f24391246c3dfe2e0e502de1/spkcspider-0.30.tar.gz
BuildArch: noarch
Requires: python3-django
Requires: python3-django-simple-jsonfield
Requires: python3-requests
Requires: python3-certifi
Requires: python3-bleach
Requires: python3-rdflib
Requires: python3-html5lib
Requires: python3-cryptography
Requires: python3-django-ranged-response
Requires: python3-django-widget-tweaks
Requires: python3-django-next-prev
Requires: python3-django-fast-ratelimit
Requires: python3-django-simple-captcha
Requires: python3-flipflop
Requires: python3-mysqlclient
Requires: python3-django-mysql
Requires: python3-psycopg2
Requires: python3-celery
Requires: python3-sqlalchemy
Requires: python3-spkcspider-domainauth
Requires: python3-django-webtest
Requires: python3-WSGIProxy2
%description
spkcspider provides a digital visiting card which can e.g. be used for authentication, shopping and payment. For this a multifactor authentication is provided.
It keeps your online data safe while shopping by just providing a link to a potion of your data. Doing this, the user may can provide some knocking mechanism (e.g. has to provide some code, tan) to protect the content.
Further features and advantages of spkcspider are:
* cross device configuration without saving user data on webshop/service.
This makes them easily DSGVO compatible without adjustments
* Address Data have to changed only on one place if you move. This is especially useful if you move a lot
Also if you travel and want to buy something on the way.
* Verification of data is possible.
* Privacy: private servers are easily set up (only requirement: cgi), also compatible to tor
* Travelling: some people don't respect common rules for privacy. This tool allows you to keep your digital life private.
* You don't have it on the device
* You can hide your data with the travel mode (against the worst kind of inspectors)
* Note: traces could be still existent (like "recently-used" feature, bookmarks)
* for governments: use psychology instead of breaking into systems! The only victims are law-abidding citizens.
# Installation
This project can either be used as a standalone project (clone repo) or as a set of reusable apps (setup.py installation).
## Build Requirements
* npm
* pip >=19 (and poetry)
## Poetry (within virtual environment)
~~~~ sh
poetry install
# for installing with extras specify -E extra1 -E extra2
~~~~
## Pip
~~~~ sh
pip install .
~~~~
## Setup
~~~~ sh
npm install --no-save
./manager.py migrate
./manager.py collectstatic
# or simply use
./tools/install_deps.sh
~~~~
## Caveats
allow_domain_mode NULL errors:
some migration failed and now it is neccessary to redo them manually
connect to database and execute:
ALTER TABLE spider_base_usercomponent DROP COLUMN allow_domain_mode;
ALTER TABLE spider_base_assignedcontent DROP COLUMN allow_domain_mode;
this doesn't work in sqlite3 (
export data (and remove allow_domain_mode if specified)
recreate db file
import data
see: http://www.sqlitetutorial.net/sqlite-alter-table/ why you don't want to try it manually
)
Mysql works with some special settings:
Require mysql to use utf8 charset
To unbreak tests, use 'CHARSET': 'utf8':
~~~~ python
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'TEST': {
'CHARSET': 'utf8'
}
}
}
~~~~
### Possibilities how to add utf8 charset to mysql:
* use 'read_default_file' and add "default-character-set = utf8" in config
* create database with "CHARACTER SET utf8"
* see: https://docs.djangoproject.com/en/dev/ref/databases/#mysql-notes
### \_\_old crashes object creation:
downgrade sqlite3 to 3.25 or upgrade django to at least 2.1.5/2.0.10
importing data:
set:
UPDATE_DYNAMIC_AFTER_MIGRATION = False
before importing data (with loaddata), update dynamic creates data
### keep pathes if switching from cgi
~~~~
location /cgi-bin/cgihandler.fcgi {
rewrite /cgi-bin/cgihandler.fcgi/?(.*)$ https://new.spkcspider.net/$1 redirect ;
}
~~~~
### logging
In this model tokens are transferred as GET parameters. Consider disabling the
logging of GET parameters (at least the sensible ones) or better:
disable logging of succeeding requests
nginx filter tokens only (hard):
~~~~
location / {
set $filtered_request $request;
if ($filtered_request ~ (.*)token=[^&]*(.*)) {
set $filtered_request $1token=****$2;
}
}
log_format filtered_combined '$remote_addr - $remote_user [$time_local] '
'"$filtered_request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
access_log /var/logs/nginx-access.log filtered_combined;
~~~~
nginx filter GET parameters:
~~~~
log_format filtered_combined '$remote_addr - $remote_user [$time_local] '
'"$uri" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
access_log /var/logs/nginx-access.log filtered_combined;
~~~~
apache filter GET parameters:
~~~~
LogFormat "%h %l %u %t \"%m %U %H\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" combined
~~~~
### localization
Don't use path based localization! This breaks the whole model.
Pathes should be unique for validation. Localisation in curl requests
can be archieved by headers.
# External usage
There are special GET parameters for controlling spkcspider:
* page=<int>: page number
* token=xy: token as GET parameter, if invalid: retrieve token as GET parameter
* token=prefer: uses invalid mechanic, easier to see what it does
* raw=true: optimize output for machines, use turtle format
* raw=embed: embed content of components, use turtle format
* id=id&id=id: limit content ids (Content lists only)
* search=foo&search=!notfoo: search case insensitive a string
* search=\_unlisted: List "unlisted" content if owner, special user (doesn't work in public list).
* protection=false: fail if protections are required
* protection=xy&protection=yx...: protections to use
* intention=auth: try to login with UserComponent authentication (falls back to login redirect)
* referrer=<url>: activate referrer mode
* intention=domain: domain verify referrer mode
* intention=sl: server-less referrer mode
* payload=<foo>: passed on successful requests (including post), e.g. for sessionid
* intention=login: referrer uses spkcspider for login (note: referrer should be the one where the user is logging in, check referrer field for that)
* intention=persist: referrer can persist data on webserver
* embed_big=true: only for staff and superuser: Overrides maximal size of files which are embedded in graphs (only for default helper)
## special header
* Content-Type/Accept=application/json: some forms are rendered as json (currently only deletion form)
## Referrer
* normal referrer mode: send token to referrer, client verifies with hash that he sent the token.
* server-less referrer mode (sl): token is transferred as GET parameter and no POST request is made (less secure as client sees token and client is not authenticated)
* domain referrer mode (domain): referrer domain is add to token. Doesn't work with other intentions (but "live" mode is active as no filter will be created) and works only if domain_mode is for context active (e.g. feature or access context (content)). Can be automated, doesn't require user approval. Useful for tag updates (only active if feature requests domain mode).
### special intentions:
* sl: activates server less mode
* live: filter live instead using fixed ids
## search parameters
* search also searches UserComponents name and description fields
* can only be used with "list"-views
* items can be negated with !foo
* strict infofield search can be activated with \_
* !!foo escapes a !foo item
* \_\_foo escapes a \_foo item
* !\_ negates a strict infofield search
* \_unlisted is a special search: it lists with "unlisted" marked contents
verified_by urls should return last verification date for a hash
## raw mode
raw mode can follow references even in other components because it is readonly.
Otherwise security could be compromised.
## Important Features
* Persistence: Allow referrer to save data (used and activated by persistent features)
* WebConfig: Allow remote websites and servers to save config data on your server (requires Persistence)
* TmpConfig: Allow remote websites and servers to save config data on your server, attached to temporary tokens (means: they are gone after a while)
# internal API
## Structure
### spider:
For spiders and contents
* spkcspider.apps.spider: store User Components, common base, WARNING: has spider_base namespace to not break existing apps
* spkcspider.apps.spider_accounts: user implementation suitable for the spiders. You can supply your own user model instead.
* spkcspider.apps.spider_filets: File and Text Content types
* spkcspider.apps.spider_keys: Public keys and anchors
* spkcspider.apps.spider_tags: verified information tags
* spkcspider.apps.spider_webcfg: WebConfig Feature
* spkcspider: contains spkcspider url detection and wsgi handler
### verifier:
Base reference implementation of a verifier.
spkcspider.apps.verifier: verifier base utils WARNING: has spider_verifier namespace to not break existing apps
## info field syntax
The info field is a simple key value storage. The syntax is (strip the spaces):
flag syntax: \\x1e key \\x1e
key value syntax: \\x1e key=value \\x1e
Note: I use the semantic ascii seperators \\x1e. Why? Sperating with an non-printable character eases escaping and sanitizing.
Note 2: I reverted from using \\x1f instead of = because the info field is used in searchs
Why not a json field? Django has no uniform json field for every db adapter yet.
## forms
* forms.initial: will be used for rdf
* field.initial: only for initialization
## authentication/privileges
* request.is_staff: requesting user used staff rights to access view (not true in ComponentPublicIndex)
* request.is_owner: requesting user owns the components
* request.is_special_user: requesting user owns the components or is_staff
* request.protections: int: enough protections were fullfilled, maximal measured strength, list: protections which failed, False: no access; access with protections not possible
## Special Scopes
* add: create content, with AssignedContent form
* update: update content
* raw_update: update Content, without AssignedContent form, adds second raw update mode (raw_add is not existent, can be archieved by returning HttpResponse in add scope)
* export: export data (import not implemented yet)
* view: present content to untrusted parties
## strength (component)
* 0: no protection. Complete content visible
* 1-3: protection strength which can be provided by protections. Meta data (names, descriptions) visible, inclusion in sitemap, public components
* 4: login only, user password. Still with inclusion of metadata
* 5: public attribute not set. No inclusion in sitemap or public components index anymore
* 6-8: protections + public attribute not set
* 9: login only, user password + public attribute not set
* 10: index, login only, special protected. Protections are used for login. Content here can be made unique per user by using unique per component attribute
= extra["strength"] on token (if available elsewise treat as zero):
the strength of the usercomponent for which it was created at the creation point
## strength (protection)
* 0: no protection
* 1-3: weak, medium, strong
* 4: do component authentication
= extra["prot_strength"] on token (if available elsewise treat as zero):
the strength of protections which was passed for creating the token
Note: access tokens created by admin have strength 0
## get usercomponent/content from url/urlpart for features
Use UserComponent.objects.from_url_part(url) / AssignedContent.from_url_part(url, [matchers]) for that
or use a domain_mode or persistent token.
Note: the difference between a domain_mode and a persistent token is, that the domain_mode token has a variable lifetime (user specific but defaults to 7 days)
Note: AssignedContent.objects.from_url_part(url) returns tuple: (matched feature/content, content which contains content/feature or None)
# API Breaks
* >0.5: settings rename\*\_ TLD_PARAMS_MAPPING to \*\_REQUEST_KWARGS_MAP with new syntax (hosts are allowed, tlds start with .)
* Note: port arguments are stripped, localhost matches localhost:80, localhost:8000, ...
* >=0.18: change order of filter parameters, nearly all filters start with request (for compatibility with (django) decorators)
* >=0.21: huge change in python API, http API should be backward compatible
* >=0.22: switch to datacontent (except in rare special cases like in SpiderTag), 3party modules will break if they used BaseContent
# TODO
* implement UploadTextareaWidget
* maybe: status codes if forms fail should represent it
* fix RDF export and view of spider_tags
* examples
* documentation
* test admin
* cleanup travelprotection: either no trigger_passwords if no trigger action is selected, or depend for trigger on trigger_passwords
* partly done, missing in frontend
* Localisation
* harmonize punctation
* css theme instead inline style
## Later
* verify subproperties without resource:
* delay hash calculation if Bnode, then create hash from hashable hash of bnode
* this case currently doesn't happen as embed/raw is solely used and no bigger no-contents are currently in use
* delayed deletion of user (disable and strength 9 everywhere)
* maybe: make quota type overridable (maybe add extra nonsaved quota: other or use 0)
* create client side script for import (pushing to server, index token for auth?)
* use browerside javascript?
* textfilet etherpad like synchronization
* pw protection: add migration tool for changed SECRET_KEY
* log changes
* improve protections, add protections
### Implement Web Comments
* every internal page can be annotated (to keep contact to author)
* send as message?
* CommentBox?
* Comment: url, subcommentlist, commenttext, reactionlist (reaction, counter)
* view: load iframe with original content?
* js for loading subcomments (only 1 level), sanitize!
* you see only the comments of your friends
* implement with messaging? Would keep comments private
* Later/Maybe:
* way to register your comment url on webpage, so others can see all comments
* social media stuff: find content via comments and likes
* annotation of other pages
# Thanks
* Default theme uses Font Awesome by Dave Gandy - http://fontawesome.io
* Some text fields use Trumbowyg by Alexander Demode
* Django team for their excellent product
%package -n python3-spkcspider
Summary: A secure, decentral platform for maintaining your online identity
Provides: python-spkcspider
BuildRequires: python3-devel
BuildRequires: python3-setuptools
BuildRequires: python3-pip
%description -n python3-spkcspider
spkcspider provides a digital visiting card which can e.g. be used for authentication, shopping and payment. For this a multifactor authentication is provided.
It keeps your online data safe while shopping by just providing a link to a potion of your data. Doing this, the user may can provide some knocking mechanism (e.g. has to provide some code, tan) to protect the content.
Further features and advantages of spkcspider are:
* cross device configuration without saving user data on webshop/service.
This makes them easily DSGVO compatible without adjustments
* Address Data have to changed only on one place if you move. This is especially useful if you move a lot
Also if you travel and want to buy something on the way.
* Verification of data is possible.
* Privacy: private servers are easily set up (only requirement: cgi), also compatible to tor
* Travelling: some people don't respect common rules for privacy. This tool allows you to keep your digital life private.
* You don't have it on the device
* You can hide your data with the travel mode (against the worst kind of inspectors)
* Note: traces could be still existent (like "recently-used" feature, bookmarks)
* for governments: use psychology instead of breaking into systems! The only victims are law-abidding citizens.
# Installation
This project can either be used as a standalone project (clone repo) or as a set of reusable apps (setup.py installation).
## Build Requirements
* npm
* pip >=19 (and poetry)
## Poetry (within virtual environment)
~~~~ sh
poetry install
# for installing with extras specify -E extra1 -E extra2
~~~~
## Pip
~~~~ sh
pip install .
~~~~
## Setup
~~~~ sh
npm install --no-save
./manager.py migrate
./manager.py collectstatic
# or simply use
./tools/install_deps.sh
~~~~
## Caveats
allow_domain_mode NULL errors:
some migration failed and now it is neccessary to redo them manually
connect to database and execute:
ALTER TABLE spider_base_usercomponent DROP COLUMN allow_domain_mode;
ALTER TABLE spider_base_assignedcontent DROP COLUMN allow_domain_mode;
this doesn't work in sqlite3 (
export data (and remove allow_domain_mode if specified)
recreate db file
import data
see: http://www.sqlitetutorial.net/sqlite-alter-table/ why you don't want to try it manually
)
Mysql works with some special settings:
Require mysql to use utf8 charset
To unbreak tests, use 'CHARSET': 'utf8':
~~~~ python
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'TEST': {
'CHARSET': 'utf8'
}
}
}
~~~~
### Possibilities how to add utf8 charset to mysql:
* use 'read_default_file' and add "default-character-set = utf8" in config
* create database with "CHARACTER SET utf8"
* see: https://docs.djangoproject.com/en/dev/ref/databases/#mysql-notes
### \_\_old crashes object creation:
downgrade sqlite3 to 3.25 or upgrade django to at least 2.1.5/2.0.10
importing data:
set:
UPDATE_DYNAMIC_AFTER_MIGRATION = False
before importing data (with loaddata), update dynamic creates data
### keep pathes if switching from cgi
~~~~
location /cgi-bin/cgihandler.fcgi {
rewrite /cgi-bin/cgihandler.fcgi/?(.*)$ https://new.spkcspider.net/$1 redirect ;
}
~~~~
### logging
In this model tokens are transferred as GET parameters. Consider disabling the
logging of GET parameters (at least the sensible ones) or better:
disable logging of succeeding requests
nginx filter tokens only (hard):
~~~~
location / {
set $filtered_request $request;
if ($filtered_request ~ (.*)token=[^&]*(.*)) {
set $filtered_request $1token=****$2;
}
}
log_format filtered_combined '$remote_addr - $remote_user [$time_local] '
'"$filtered_request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
access_log /var/logs/nginx-access.log filtered_combined;
~~~~
nginx filter GET parameters:
~~~~
log_format filtered_combined '$remote_addr - $remote_user [$time_local] '
'"$uri" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
access_log /var/logs/nginx-access.log filtered_combined;
~~~~
apache filter GET parameters:
~~~~
LogFormat "%h %l %u %t \"%m %U %H\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" combined
~~~~
### localization
Don't use path based localization! This breaks the whole model.
Pathes should be unique for validation. Localisation in curl requests
can be archieved by headers.
# External usage
There are special GET parameters for controlling spkcspider:
* page=<int>: page number
* token=xy: token as GET parameter, if invalid: retrieve token as GET parameter
* token=prefer: uses invalid mechanic, easier to see what it does
* raw=true: optimize output for machines, use turtle format
* raw=embed: embed content of components, use turtle format
* id=id&id=id: limit content ids (Content lists only)
* search=foo&search=!notfoo: search case insensitive a string
* search=\_unlisted: List "unlisted" content if owner, special user (doesn't work in public list).
* protection=false: fail if protections are required
* protection=xy&protection=yx...: protections to use
* intention=auth: try to login with UserComponent authentication (falls back to login redirect)
* referrer=<url>: activate referrer mode
* intention=domain: domain verify referrer mode
* intention=sl: server-less referrer mode
* payload=<foo>: passed on successful requests (including post), e.g. for sessionid
* intention=login: referrer uses spkcspider for login (note: referrer should be the one where the user is logging in, check referrer field for that)
* intention=persist: referrer can persist data on webserver
* embed_big=true: only for staff and superuser: Overrides maximal size of files which are embedded in graphs (only for default helper)
## special header
* Content-Type/Accept=application/json: some forms are rendered as json (currently only deletion form)
## Referrer
* normal referrer mode: send token to referrer, client verifies with hash that he sent the token.
* server-less referrer mode (sl): token is transferred as GET parameter and no POST request is made (less secure as client sees token and client is not authenticated)
* domain referrer mode (domain): referrer domain is add to token. Doesn't work with other intentions (but "live" mode is active as no filter will be created) and works only if domain_mode is for context active (e.g. feature or access context (content)). Can be automated, doesn't require user approval. Useful for tag updates (only active if feature requests domain mode).
### special intentions:
* sl: activates server less mode
* live: filter live instead using fixed ids
## search parameters
* search also searches UserComponents name and description fields
* can only be used with "list"-views
* items can be negated with !foo
* strict infofield search can be activated with \_
* !!foo escapes a !foo item
* \_\_foo escapes a \_foo item
* !\_ negates a strict infofield search
* \_unlisted is a special search: it lists with "unlisted" marked contents
verified_by urls should return last verification date for a hash
## raw mode
raw mode can follow references even in other components because it is readonly.
Otherwise security could be compromised.
## Important Features
* Persistence: Allow referrer to save data (used and activated by persistent features)
* WebConfig: Allow remote websites and servers to save config data on your server (requires Persistence)
* TmpConfig: Allow remote websites and servers to save config data on your server, attached to temporary tokens (means: they are gone after a while)
# internal API
## Structure
### spider:
For spiders and contents
* spkcspider.apps.spider: store User Components, common base, WARNING: has spider_base namespace to not break existing apps
* spkcspider.apps.spider_accounts: user implementation suitable for the spiders. You can supply your own user model instead.
* spkcspider.apps.spider_filets: File and Text Content types
* spkcspider.apps.spider_keys: Public keys and anchors
* spkcspider.apps.spider_tags: verified information tags
* spkcspider.apps.spider_webcfg: WebConfig Feature
* spkcspider: contains spkcspider url detection and wsgi handler
### verifier:
Base reference implementation of a verifier.
spkcspider.apps.verifier: verifier base utils WARNING: has spider_verifier namespace to not break existing apps
## info field syntax
The info field is a simple key value storage. The syntax is (strip the spaces):
flag syntax: \\x1e key \\x1e
key value syntax: \\x1e key=value \\x1e
Note: I use the semantic ascii seperators \\x1e. Why? Sperating with an non-printable character eases escaping and sanitizing.
Note 2: I reverted from using \\x1f instead of = because the info field is used in searchs
Why not a json field? Django has no uniform json field for every db adapter yet.
## forms
* forms.initial: will be used for rdf
* field.initial: only for initialization
## authentication/privileges
* request.is_staff: requesting user used staff rights to access view (not true in ComponentPublicIndex)
* request.is_owner: requesting user owns the components
* request.is_special_user: requesting user owns the components or is_staff
* request.protections: int: enough protections were fullfilled, maximal measured strength, list: protections which failed, False: no access; access with protections not possible
## Special Scopes
* add: create content, with AssignedContent form
* update: update content
* raw_update: update Content, without AssignedContent form, adds second raw update mode (raw_add is not existent, can be archieved by returning HttpResponse in add scope)
* export: export data (import not implemented yet)
* view: present content to untrusted parties
## strength (component)
* 0: no protection. Complete content visible
* 1-3: protection strength which can be provided by protections. Meta data (names, descriptions) visible, inclusion in sitemap, public components
* 4: login only, user password. Still with inclusion of metadata
* 5: public attribute not set. No inclusion in sitemap or public components index anymore
* 6-8: protections + public attribute not set
* 9: login only, user password + public attribute not set
* 10: index, login only, special protected. Protections are used for login. Content here can be made unique per user by using unique per component attribute
= extra["strength"] on token (if available elsewise treat as zero):
the strength of the usercomponent for which it was created at the creation point
## strength (protection)
* 0: no protection
* 1-3: weak, medium, strong
* 4: do component authentication
= extra["prot_strength"] on token (if available elsewise treat as zero):
the strength of protections which was passed for creating the token
Note: access tokens created by admin have strength 0
## get usercomponent/content from url/urlpart for features
Use UserComponent.objects.from_url_part(url) / AssignedContent.from_url_part(url, [matchers]) for that
or use a domain_mode or persistent token.
Note: the difference between a domain_mode and a persistent token is, that the domain_mode token has a variable lifetime (user specific but defaults to 7 days)
Note: AssignedContent.objects.from_url_part(url) returns tuple: (matched feature/content, content which contains content/feature or None)
# API Breaks
* >0.5: settings rename\*\_ TLD_PARAMS_MAPPING to \*\_REQUEST_KWARGS_MAP with new syntax (hosts are allowed, tlds start with .)
* Note: port arguments are stripped, localhost matches localhost:80, localhost:8000, ...
* >=0.18: change order of filter parameters, nearly all filters start with request (for compatibility with (django) decorators)
* >=0.21: huge change in python API, http API should be backward compatible
* >=0.22: switch to datacontent (except in rare special cases like in SpiderTag), 3party modules will break if they used BaseContent
# TODO
* implement UploadTextareaWidget
* maybe: status codes if forms fail should represent it
* fix RDF export and view of spider_tags
* examples
* documentation
* test admin
* cleanup travelprotection: either no trigger_passwords if no trigger action is selected, or depend for trigger on trigger_passwords
* partly done, missing in frontend
* Localisation
* harmonize punctation
* css theme instead inline style
## Later
* verify subproperties without resource:
* delay hash calculation if Bnode, then create hash from hashable hash of bnode
* this case currently doesn't happen as embed/raw is solely used and no bigger no-contents are currently in use
* delayed deletion of user (disable and strength 9 everywhere)
* maybe: make quota type overridable (maybe add extra nonsaved quota: other or use 0)
* create client side script for import (pushing to server, index token for auth?)
* use browerside javascript?
* textfilet etherpad like synchronization
* pw protection: add migration tool for changed SECRET_KEY
* log changes
* improve protections, add protections
### Implement Web Comments
* every internal page can be annotated (to keep contact to author)
* send as message?
* CommentBox?
* Comment: url, subcommentlist, commenttext, reactionlist (reaction, counter)
* view: load iframe with original content?
* js for loading subcomments (only 1 level), sanitize!
* you see only the comments of your friends
* implement with messaging? Would keep comments private
* Later/Maybe:
* way to register your comment url on webpage, so others can see all comments
* social media stuff: find content via comments and likes
* annotation of other pages
# Thanks
* Default theme uses Font Awesome by Dave Gandy - http://fontawesome.io
* Some text fields use Trumbowyg by Alexander Demode
* Django team for their excellent product
%package help
Summary: Development documents and examples for spkcspider
Provides: python3-spkcspider-doc
%description help
spkcspider provides a digital visiting card which can e.g. be used for authentication, shopping and payment. For this a multifactor authentication is provided.
It keeps your online data safe while shopping by just providing a link to a potion of your data. Doing this, the user may can provide some knocking mechanism (e.g. has to provide some code, tan) to protect the content.
Further features and advantages of spkcspider are:
* cross device configuration without saving user data on webshop/service.
This makes them easily DSGVO compatible without adjustments
* Address Data have to changed only on one place if you move. This is especially useful if you move a lot
Also if you travel and want to buy something on the way.
* Verification of data is possible.
* Privacy: private servers are easily set up (only requirement: cgi), also compatible to tor
* Travelling: some people don't respect common rules for privacy. This tool allows you to keep your digital life private.
* You don't have it on the device
* You can hide your data with the travel mode (against the worst kind of inspectors)
* Note: traces could be still existent (like "recently-used" feature, bookmarks)
* for governments: use psychology instead of breaking into systems! The only victims are law-abidding citizens.
# Installation
This project can either be used as a standalone project (clone repo) or as a set of reusable apps (setup.py installation).
## Build Requirements
* npm
* pip >=19 (and poetry)
## Poetry (within virtual environment)
~~~~ sh
poetry install
# for installing with extras specify -E extra1 -E extra2
~~~~
## Pip
~~~~ sh
pip install .
~~~~
## Setup
~~~~ sh
npm install --no-save
./manager.py migrate
./manager.py collectstatic
# or simply use
./tools/install_deps.sh
~~~~
## Caveats
allow_domain_mode NULL errors:
some migration failed and now it is neccessary to redo them manually
connect to database and execute:
ALTER TABLE spider_base_usercomponent DROP COLUMN allow_domain_mode;
ALTER TABLE spider_base_assignedcontent DROP COLUMN allow_domain_mode;
this doesn't work in sqlite3 (
export data (and remove allow_domain_mode if specified)
recreate db file
import data
see: http://www.sqlitetutorial.net/sqlite-alter-table/ why you don't want to try it manually
)
Mysql works with some special settings:
Require mysql to use utf8 charset
To unbreak tests, use 'CHARSET': 'utf8':
~~~~ python
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'TEST': {
'CHARSET': 'utf8'
}
}
}
~~~~
### Possibilities how to add utf8 charset to mysql:
* use 'read_default_file' and add "default-character-set = utf8" in config
* create database with "CHARACTER SET utf8"
* see: https://docs.djangoproject.com/en/dev/ref/databases/#mysql-notes
### \_\_old crashes object creation:
downgrade sqlite3 to 3.25 or upgrade django to at least 2.1.5/2.0.10
importing data:
set:
UPDATE_DYNAMIC_AFTER_MIGRATION = False
before importing data (with loaddata), update dynamic creates data
### keep pathes if switching from cgi
~~~~
location /cgi-bin/cgihandler.fcgi {
rewrite /cgi-bin/cgihandler.fcgi/?(.*)$ https://new.spkcspider.net/$1 redirect ;
}
~~~~
### logging
In this model tokens are transferred as GET parameters. Consider disabling the
logging of GET parameters (at least the sensible ones) or better:
disable logging of succeeding requests
nginx filter tokens only (hard):
~~~~
location / {
set $filtered_request $request;
if ($filtered_request ~ (.*)token=[^&]*(.*)) {
set $filtered_request $1token=****$2;
}
}
log_format filtered_combined '$remote_addr - $remote_user [$time_local] '
'"$filtered_request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
access_log /var/logs/nginx-access.log filtered_combined;
~~~~
nginx filter GET parameters:
~~~~
log_format filtered_combined '$remote_addr - $remote_user [$time_local] '
'"$uri" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
access_log /var/logs/nginx-access.log filtered_combined;
~~~~
apache filter GET parameters:
~~~~
LogFormat "%h %l %u %t \"%m %U %H\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" combined
~~~~
### localization
Don't use path based localization! This breaks the whole model.
Pathes should be unique for validation. Localisation in curl requests
can be archieved by headers.
# External usage
There are special GET parameters for controlling spkcspider:
* page=<int>: page number
* token=xy: token as GET parameter, if invalid: retrieve token as GET parameter
* token=prefer: uses invalid mechanic, easier to see what it does
* raw=true: optimize output for machines, use turtle format
* raw=embed: embed content of components, use turtle format
* id=id&id=id: limit content ids (Content lists only)
* search=foo&search=!notfoo: search case insensitive a string
* search=\_unlisted: List "unlisted" content if owner, special user (doesn't work in public list).
* protection=false: fail if protections are required
* protection=xy&protection=yx...: protections to use
* intention=auth: try to login with UserComponent authentication (falls back to login redirect)
* referrer=<url>: activate referrer mode
* intention=domain: domain verify referrer mode
* intention=sl: server-less referrer mode
* payload=<foo>: passed on successful requests (including post), e.g. for sessionid
* intention=login: referrer uses spkcspider for login (note: referrer should be the one where the user is logging in, check referrer field for that)
* intention=persist: referrer can persist data on webserver
* embed_big=true: only for staff and superuser: Overrides maximal size of files which are embedded in graphs (only for default helper)
## special header
* Content-Type/Accept=application/json: some forms are rendered as json (currently only deletion form)
## Referrer
* normal referrer mode: send token to referrer, client verifies with hash that he sent the token.
* server-less referrer mode (sl): token is transferred as GET parameter and no POST request is made (less secure as client sees token and client is not authenticated)
* domain referrer mode (domain): referrer domain is add to token. Doesn't work with other intentions (but "live" mode is active as no filter will be created) and works only if domain_mode is for context active (e.g. feature or access context (content)). Can be automated, doesn't require user approval. Useful for tag updates (only active if feature requests domain mode).
### special intentions:
* sl: activates server less mode
* live: filter live instead using fixed ids
## search parameters
* search also searches UserComponents name and description fields
* can only be used with "list"-views
* items can be negated with !foo
* strict infofield search can be activated with \_
* !!foo escapes a !foo item
* \_\_foo escapes a \_foo item
* !\_ negates a strict infofield search
* \_unlisted is a special search: it lists with "unlisted" marked contents
verified_by urls should return last verification date for a hash
## raw mode
raw mode can follow references even in other components because it is readonly.
Otherwise security could be compromised.
## Important Features
* Persistence: Allow referrer to save data (used and activated by persistent features)
* WebConfig: Allow remote websites and servers to save config data on your server (requires Persistence)
* TmpConfig: Allow remote websites and servers to save config data on your server, attached to temporary tokens (means: they are gone after a while)
# internal API
## Structure
### spider:
For spiders and contents
* spkcspider.apps.spider: store User Components, common base, WARNING: has spider_base namespace to not break existing apps
* spkcspider.apps.spider_accounts: user implementation suitable for the spiders. You can supply your own user model instead.
* spkcspider.apps.spider_filets: File and Text Content types
* spkcspider.apps.spider_keys: Public keys and anchors
* spkcspider.apps.spider_tags: verified information tags
* spkcspider.apps.spider_webcfg: WebConfig Feature
* spkcspider: contains spkcspider url detection and wsgi handler
### verifier:
Base reference implementation of a verifier.
spkcspider.apps.verifier: verifier base utils WARNING: has spider_verifier namespace to not break existing apps
## info field syntax
The info field is a simple key value storage. The syntax is (strip the spaces):
flag syntax: \\x1e key \\x1e
key value syntax: \\x1e key=value \\x1e
Note: I use the semantic ascii seperators \\x1e. Why? Sperating with an non-printable character eases escaping and sanitizing.
Note 2: I reverted from using \\x1f instead of = because the info field is used in searchs
Why not a json field? Django has no uniform json field for every db adapter yet.
## forms
* forms.initial: will be used for rdf
* field.initial: only for initialization
## authentication/privileges
* request.is_staff: requesting user used staff rights to access view (not true in ComponentPublicIndex)
* request.is_owner: requesting user owns the components
* request.is_special_user: requesting user owns the components or is_staff
* request.protections: int: enough protections were fullfilled, maximal measured strength, list: protections which failed, False: no access; access with protections not possible
## Special Scopes
* add: create content, with AssignedContent form
* update: update content
* raw_update: update Content, without AssignedContent form, adds second raw update mode (raw_add is not existent, can be archieved by returning HttpResponse in add scope)
* export: export data (import not implemented yet)
* view: present content to untrusted parties
## strength (component)
* 0: no protection. Complete content visible
* 1-3: protection strength which can be provided by protections. Meta data (names, descriptions) visible, inclusion in sitemap, public components
* 4: login only, user password. Still with inclusion of metadata
* 5: public attribute not set. No inclusion in sitemap or public components index anymore
* 6-8: protections + public attribute not set
* 9: login only, user password + public attribute not set
* 10: index, login only, special protected. Protections are used for login. Content here can be made unique per user by using unique per component attribute
= extra["strength"] on token (if available elsewise treat as zero):
the strength of the usercomponent for which it was created at the creation point
## strength (protection)
* 0: no protection
* 1-3: weak, medium, strong
* 4: do component authentication
= extra["prot_strength"] on token (if available elsewise treat as zero):
the strength of protections which was passed for creating the token
Note: access tokens created by admin have strength 0
## get usercomponent/content from url/urlpart for features
Use UserComponent.objects.from_url_part(url) / AssignedContent.from_url_part(url, [matchers]) for that
or use a domain_mode or persistent token.
Note: the difference between a domain_mode and a persistent token is, that the domain_mode token has a variable lifetime (user specific but defaults to 7 days)
Note: AssignedContent.objects.from_url_part(url) returns tuple: (matched feature/content, content which contains content/feature or None)
# API Breaks
* >0.5: settings rename\*\_ TLD_PARAMS_MAPPING to \*\_REQUEST_KWARGS_MAP with new syntax (hosts are allowed, tlds start with .)
* Note: port arguments are stripped, localhost matches localhost:80, localhost:8000, ...
* >=0.18: change order of filter parameters, nearly all filters start with request (for compatibility with (django) decorators)
* >=0.21: huge change in python API, http API should be backward compatible
* >=0.22: switch to datacontent (except in rare special cases like in SpiderTag), 3party modules will break if they used BaseContent
# TODO
* implement UploadTextareaWidget
* maybe: status codes if forms fail should represent it
* fix RDF export and view of spider_tags
* examples
* documentation
* test admin
* cleanup travelprotection: either no trigger_passwords if no trigger action is selected, or depend for trigger on trigger_passwords
* partly done, missing in frontend
* Localisation
* harmonize punctation
* css theme instead inline style
## Later
* verify subproperties without resource:
* delay hash calculation if Bnode, then create hash from hashable hash of bnode
* this case currently doesn't happen as embed/raw is solely used and no bigger no-contents are currently in use
* delayed deletion of user (disable and strength 9 everywhere)
* maybe: make quota type overridable (maybe add extra nonsaved quota: other or use 0)
* create client side script for import (pushing to server, index token for auth?)
* use browerside javascript?
* textfilet etherpad like synchronization
* pw protection: add migration tool for changed SECRET_KEY
* log changes
* improve protections, add protections
### Implement Web Comments
* every internal page can be annotated (to keep contact to author)
* send as message?
* CommentBox?
* Comment: url, subcommentlist, commenttext, reactionlist (reaction, counter)
* view: load iframe with original content?
* js for loading subcomments (only 1 level), sanitize!
* you see only the comments of your friends
* implement with messaging? Would keep comments private
* Later/Maybe:
* way to register your comment url on webpage, so others can see all comments
* social media stuff: find content via comments and likes
* annotation of other pages
# Thanks
* Default theme uses Font Awesome by Dave Gandy - http://fontawesome.io
* Some text fields use Trumbowyg by Alexander Demode
* Django team for their excellent product
%prep
%autosetup -n spkcspider-0.30
%build
%py3_build
%install
%py3_install
install -d -m755 %{buildroot}/%{_pkgdocdir}
if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi
if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi
if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi
if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi
pushd %{buildroot}
if [ -d usr/lib ]; then
find usr/lib -type f -printf "\"/%h/%f\"\n" >> filelist.lst
fi
if [ -d usr/lib64 ]; then
find usr/lib64 -type f -printf "\"/%h/%f\"\n" >> filelist.lst
fi
if [ -d usr/bin ]; then
find usr/bin -type f -printf "\"/%h/%f\"\n" >> filelist.lst
fi
if [ -d usr/sbin ]; then
find usr/sbin -type f -printf "\"/%h/%f\"\n" >> filelist.lst
fi
touch doclist.lst
if [ -d usr/share/man ]; then
find usr/share/man -type f -printf "\"/%h/%f.gz\"\n" >> doclist.lst
fi
popd
mv %{buildroot}/filelist.lst .
mv %{buildroot}/doclist.lst .
%files -n python3-spkcspider -f filelist.lst
%dir %{python3_sitelib}/*
%files help -f doclist.lst
%{_docdir}/*
%changelog
* Fri Jun 09 2023 Python_Bot <Python_Bot@openeuler.org> - 0.30-1
- Package Spec generated
|