@@ -118,10 +118,14 @@ def configure_site():
118
118
119
119
app .secret_key = _site .config .get ('COIL_SECRET_KEY' )
120
120
app .config ['COIL_URL' ] = _site .config .get ('COIL_URL' )
121
+ app .config ['COIL_SINGLE' ] = _site .config .get ('COIL_SINGLE' , False )
121
122
app .config ['REDIS_URL' ] = _site .config .get ('COIL_REDIS_URL' ,
122
123
'redis://localhost:6379/0' )
123
- db = redis .StrictRedis .from_url (app .config ['REDIS_URL' ])
124
- q = rq .Queue (name = 'coil' , connection = db )
124
+ if app .config ['COIL_SINGLE' ]:
125
+ app .config ['COIL_USERS' ] = _site .config .get ('COIL_USERS' , {})
126
+ else :
127
+ db = redis .StrictRedis .from_url (app .config ['REDIS_URL' ])
128
+ q = rq .Queue (name = 'coil' , connection = db )
125
129
126
130
_site .template_hooks ['menu' ].append (generate_menu )
127
131
_site .template_hooks ['menu_alt' ].append (generate_menu_alt )
@@ -177,7 +181,11 @@ def configure_site():
177
181
_site .template_system .inject_directory (tmpl_dir )
178
182
179
183
# Site proxy
180
- site = SiteProxy (db , _site , app .logger )
184
+ if app .config ['COIL_SINGLE' ]:
185
+ site = _site
186
+ else :
187
+ site = SiteProxy (db , _site , app .logger )
188
+
181
189
configure_url (app .config ['COIL_URL' ])
182
190
183
191
@@ -227,7 +235,11 @@ def generate_menu():
227
235
:return: HTML fragment
228
236
:rtype: str
229
237
"""
230
- if db .get ('site:needs_rebuild' ) not in ('0' , '-1' ):
238
+ if db is not None :
239
+ needs_rebuild = db .get ('site:needs_rebuild' )
240
+ else :
241
+ needs_rebuild = site .coil_needs_rebuild
242
+ if needs_rebuild not in ('0' , '-1' ):
231
243
return ('</li><li><a href="{0}"><i class="fa fa-fw '
232
244
'fa-warning"></i> <strong>Rebuild</strong></a></li>' .format (
233
245
url_for ('rebuild' )))
@@ -245,7 +257,7 @@ def generate_menu_alt():
245
257
if not current_user .is_authenticated ():
246
258
return ('<li><a href="{0}"><i class="fa fa-fw fa-sign-in"></i> '
247
259
'Log in</a></li>' .format (url_for ('login' )))
248
- if current_user .is_admin :
260
+ if db is not None and current_user .is_admin :
249
261
edit_entry = (
250
262
'<li><a href="{0}"><i class="fa fa-fw fa-users"></i> '
251
263
'Manage users</a></li>'
@@ -434,13 +446,20 @@ def get_user(uid):
434
446
:raises ValueError: uid is not an integer
435
447
:raises KeyError: if user does not exist
436
448
"""
437
- d = db .hgetall ('user:{0}' .format (uid ))
438
- if d :
439
- for p in PERMISSIONS :
440
- d [p ] = d .get (p ) == '1'
441
- return User (uid = uid , ** d )
449
+ if db is not None :
450
+ d = db .hgetall ('user:{0}' .format (uid ))
451
+ if d :
452
+ for p in PERMISSIONS :
453
+ d [p ] = d .get (p ) == '1'
454
+ return User (uid = uid , ** d )
455
+ else :
456
+ return None
442
457
else :
443
- return None
458
+ d = app .config ['COIL_USERS' ].get (uid )
459
+ if d :
460
+ return User (uid = uid , ** d )
461
+ else :
462
+ return None
444
463
445
464
446
465
def find_user_by_name (username ):
@@ -450,11 +469,14 @@ def find_user_by_name(username):
450
469
:return: the user
451
470
:rtype: User object or None
452
471
"""
453
- uid = db .hget ('users' , username )
454
- if uid :
455
- return get_user (uid )
472
+ if db is not None :
473
+ uid = db .hget ('users' , username )
474
+ if uid :
475
+ return get_user (uid )
456
476
else :
457
- return None
477
+ for u in app .config ['COIL_USERS' ]:
478
+ if u ['username' ] == username :
479
+ return get_user (uid )
458
480
459
481
460
482
def write_user (user ):
@@ -638,7 +660,10 @@ def edit(path):
638
660
with io .open (meta_path , 'w+' , encoding = 'utf-8' ) as fh :
639
661
fh .write (write_metadata (meta ))
640
662
scan_site ()
641
- db .set ('site:needs_rebuild' , '1' )
663
+ if db is not None :
664
+ db .set ('site:needs_rebuild' , '1' )
665
+ else :
666
+ site .coil_needs_rebuild = '1'
642
667
post = find_post (path )
643
668
context ['action' ] = 'save'
644
669
else :
@@ -651,11 +676,16 @@ def edit(path):
651
676
652
677
context ['post' ] = post
653
678
users = []
654
- uids = db .hgetall ('users' ).values ()
655
- for u in uids :
656
- realname , active = db .hmget ('user:{0}' .format (u ), 'realname' , 'active' )
657
- if active == '1' :
658
- users .append ((u , realname ))
679
+ if db is not None :
680
+ uids = db .hgetall ('users' ).values ()
681
+ for u in uids :
682
+ realname , active = db .hmget ('user:{0}' .format (u ), 'realname' , 'active' )
683
+ if active == '1' :
684
+ users .append ((u , realname ))
685
+ else :
686
+ for u , d in app .config ['COIL_USERS' ].values ():
687
+ if d ['active' ]:
688
+ users .append ((u , d ['realname' ]))
659
689
context ['users' ] = sorted (users )
660
690
context ['current_auid' ] = current_auid
661
691
context ['title' ] = 'Editing {0}' .format (post .title ())
@@ -689,14 +719,19 @@ def delete():
689
719
meta_path = os .path .splitext (path )[0 ] + '.meta'
690
720
os .unlink (meta_path )
691
721
scan_site ()
692
- db .set ('site:needs_rebuild' , '1' )
722
+ if db is not None :
723
+ db .set ('site:needs_rebuild' , '1' )
724
+ else :
725
+ site .coil_needs_rebuild = '1'
693
726
return redirect (url_for ('index' ))
694
727
695
728
696
729
@app .route ('/api/rebuild/' )
697
730
@login_required
698
731
def api_rebuild ():
699
732
"""Rebuild the site (internally)."""
733
+ if db is None :
734
+ return '{"error": "single-user mode"}'
700
735
build_job = q .fetch_job ('build' )
701
736
orphans_job = q .fetch_job ('orphans' )
702
737
@@ -737,17 +772,25 @@ def rebuild(mode=''):
737
772
return error ('You are not permitted to rebuild the site.</p>'
738
773
'<p class="lead">Contact an administartor for '
739
774
'more information.' , 401 )
740
- db .set ('site:needs_rebuild' , '-1' )
741
- if not q .fetch_job ('build' ) and not q .fetch_job ('orphans' ):
742
- b = q .enqueue_call (func = coil .tasks .build ,
743
- args = (app .config ['REDIS_URL' ],
744
- app .config ['NIKOLA_ROOT' ], mode ), job_id = 'build' )
745
- q .enqueue_call (func = coil .tasks .orphans ,
746
- args = (app .config ['REDIS_URL' ],
747
- app .config ['NIKOLA_ROOT' ]), job_id = 'orphans' ,
748
- depends_on = b )
775
+ if db is not None :
776
+ db .set ('site:needs_rebuild' , '-1' )
777
+ if not q .fetch_job ('build' ) and not q .fetch_job ('orphans' ):
778
+ b = q .enqueue_call (func = coil .tasks .build ,
779
+ args = (app .config ['REDIS_URL' ],
780
+ app .config ['NIKOLA_ROOT' ], mode ), job_id = 'build' )
781
+ q .enqueue_call (func = coil .tasks .orphans ,
782
+ args = (app .config ['REDIS_URL' ],
783
+ app .config ['NIKOLA_ROOT' ]), job_id = 'orphans' ,
784
+ depends_on = b )
785
+ return render ('coil_rebuild.tmpl' , {'title' : 'Rebuild' })
786
+ else :
787
+ status , outputb = coil .tasks .build_single (mode )
788
+ _ , outputo = coil .tasks .orphans_single ()
789
+ return render ('coil_rebuild_single.tmpl' , {'title' : 'Rebuild' ,
790
+ 'status' : '1' if status else '0' ,
791
+ 'outputb' : outputb ,
792
+ 'outputo' : outputo })
749
793
750
- return render ('coil_rebuild.tmpl' , {'title' : 'Rebuild' })
751
794
752
795
753
796
@app .route ('/new/<obj>/' , methods = ['POST' ])
@@ -791,7 +834,10 @@ def new(obj):
791
834
del _site .config ['ADDITIONAL_METADATA' ]['author.uid' ]
792
835
# reload post list and go to index
793
836
scan_site ()
794
- db .set ('site:needs_rebuild' , '1' )
837
+ if db is not None :
838
+ db .set ('site:needs_rebuild' , '1' )
839
+ else :
840
+ site .coil_needs_rebuild = '1'
795
841
return redirect (url_for ('index' ))
796
842
797
843
@@ -892,8 +938,10 @@ def acp_users():
892
938
"""List all users."""
893
939
if current_user .must_change_password :
894
940
return redirect (url_for ('acp_account' ) + '?status=pwdchange' )
895
- elif not current_user .is_admin :
941
+ if not current_user .is_admin :
896
942
return error ("Not authorized to edit users." , 401 )
943
+ if not db :
944
+ return error ('The ACP is not available in single-user mode.' , 500 )
897
945
898
946
alert = ''
899
947
alert_status = ''
@@ -923,8 +971,10 @@ def acp_users_edit():
923
971
global current_user
924
972
if current_user .must_change_password :
925
973
return redirect (url_for ('acp_account' ) + '?status=pwdchange' )
926
- elif not current_user .is_admin :
974
+ if not current_user .is_admin :
927
975
return error ("Not authorized to edit users." , 401 )
976
+ if not db :
977
+ return error ('The ACP is not available in single-user mode.' , 500 )
928
978
data = request .form
929
979
930
980
form = UserEditForm ()
@@ -997,8 +1047,10 @@ def acp_users_import():
997
1047
"""Import users from a TSV file."""
998
1048
if current_user .must_change_password :
999
1049
return redirect (url_for ('acp_account' ) + '?status=pwdchange' )
1000
- elif not current_user .is_admin :
1050
+ if not current_user .is_admin :
1001
1051
return error ("Not authorized to edit users." , 401 )
1052
+ if not db :
1053
+ return error ('The ACP is not available in single-user mode.' , 500 )
1002
1054
1003
1055
form = UserImportForm ()
1004
1056
if not form .validate ():
@@ -1015,8 +1067,10 @@ def acp_users_delete():
1015
1067
"""Delete or undelete an user account."""
1016
1068
if current_user .must_change_password :
1017
1069
return redirect (url_for ('acp_account' ) + '?status=pwdchange' )
1018
- elif not current_user .is_admin :
1070
+ if not current_user .is_admin :
1019
1071
return error ("Not authorized to edit users." , 401 )
1072
+ if not db :
1073
+ return error ('The ACP is not available in single-user mode.' , 500 )
1020
1074
1021
1075
form = UserDeleteForm ()
1022
1076
if not form .validate ():
@@ -1040,8 +1094,10 @@ def acp_users_permissions():
1040
1094
"""Change user permissions."""
1041
1095
if current_user .must_change_password :
1042
1096
return redirect (url_for ('acp_account' ) + '?status=pwdchange' )
1043
- elif not current_user .is_admin :
1097
+ if not current_user .is_admin :
1044
1098
return error ("Not authorized to edit users." , 401 )
1099
+ if not db :
1100
+ return error ('The ACP is not available in single-user mode.' , 500 )
1045
1101
1046
1102
form = PermissionsForm ()
1047
1103
users = []
0 commit comments