/
admin.py
411 lines (349 loc) · 16.3 KB
/
admin.py
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
# admin.py
# Admin pages for CedarRapidsOnline web service
# Copyright (C) 2009 Clear Perception Solutions, LLC.
# Written by Trevis J. Rothwell <tjr@gnu.org>
#
# This file is part of the CedarRapidsOnline web service.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import cherrypy
import pgdb
import pageutils
import sqlutils
import string
database_connect_fields = sqlutils.database_connect_fields
class AdminUsersPage:
def index (self):
# Verify user is logged-in admin.
if (not pageutils.is_admin_p()):
raise cherrypy.HTTPRedirect ("/")
# Present listing of all users.
return "ADMIN: Present listing of all users."
index.exposed = True
def edit (self, user_id=None):
# Verify user is logged-in admin.
if (not pageutils.is_admin_p()):
raise cherrypy.HTTPRedirect ("/")
# Edit form for given user.
return "ADMIN: Edit form for given user."
edit.exposed = True
class AdminArticlesPage:
def index (self):
# Verify user is logged-in admin.
if (not pageutils.is_admin_p()):
raise cherrypy.HTTPRedirect ("/")
description = None
results = None
# Try to connect to the database.
try:
dbconnection = pgdb.connect (database_connect_fields)
dbcursor = dbconnection.cursor()
dbcursor.execute ("SELECT * FROM articles")
# Get the cursor description and results from the query.
description = dbcursor.description
results = dbcursor.fetchall()
# Close the database cursor and connection.
dbcursor.close()
dbconnection.close()
except:
pass
pagecontents = "<p><a href=\"/admin/articles/new\">Create New Article</a></p>\n"
pagecontents += "<h3>Article Listing</h3>\n"
pagecontents += "<ul>\n"
if (results == []):
pagecontents += "<li>No articles found in database.</li>\n"
for result in results:
try:
title = result[sqlutils.getfieldindex ("title", description)]
slug = result[sqlutils.getfieldindex ("slug", description)]
article_id = result[sqlutils.getfieldindex ("article_id", description)]
pagecontents += "<li><a href=\"/admin/articles/edit/" + slug + "\">" + title + "</a>\n"
pagecontents += "[<a href=\"/admin/articles/delete/" + article_id + "\">Delete</a>]</li>\n"
except:
pass
pagecontents += "</ul>\n"
# Present listing of all articles.
return pageutils.generate_page ("Articles Administration", pagecontents)
index.exposed = True
def new (self, edit=False, title=None, slug=None, display=None, body=None, article_id=None):
# Verify user is logged-in admin.
if (not pageutils.is_admin_p()):
raise cherrypy.HTTPRedirect ("/")
# Form to create new article.
pagecontents = ""
if (edit):
pagecontents += "<form action=\"/admin/articles/processedit\" method=\"post\">"
else:
pagecontents += "<form action=\"/admin/articles/processnew\" method=\"post\">"
pagecontents += "<b>Title</b>:"
pagecontents += "<br>"
if (edit):
pagecontents += "<input type=\"text\" name=\"title\" value=\"" + str(title) + "\">"
else:
pagecontents += "<input type=\"text\" name=\"title\">"
pagecontents += "<br><br>\n"
pagecontents += "<b>Slug</b>:"
pagecontents += "<br>"
if (edit):
pagecontents += "<input type=\"text\" name=\"slug\" value=\"" + str(slug) + "\">"
else:
pagecontents += "<input type=\"text\" name=\"slug\">"
pagecontents += "<br><br>"
pagecontents += "<b>Display Mode</b>:"
pagecontents += "<br>"
pagecontents += "<select name=\"display\">\n"
pagecontents += "<option value=\"0\">Do not display</option>\n"
pagecontents += "<option value=\"1\">Display with no comments</option>\n"
pagecontents += "<option value=\"2\" selected=\"selected\">Display with comments (default)</option>\n"
pagecontents += "</select>\n"
pagecontents += "<br><br>"
pagecontents += "<b>Body</b>:"
pagecontents += "<br>"
if (edit):
pagecontents += "<textarea cols=80 rows=10 name=\"body\">" + str(body) +"</textarea>\n"
else:
pagecontents += "<textarea cols=80 rows=10 name=\"body\"></textarea>\n"
pagecontents += "<br><br>"
if (edit):
pagecontents += "<input type=\"hidden\" name=\"article_id\" value=\"" + str(article_id) + "\">"
if (edit):
pagecontents += "<input type=\"submit\" value=\"Submit Changes\">"
else:
pagecontents += "<input type=\"submit\" value=\"Create New Article\">"
pagecontents += "</form>"
if (edit):
return pageutils.generate_page ("Edit Article", pagecontents)
else:
return pageutils.generate_page ("Create New Article", pagecontents)
new.exposed = True
def processedit (self, title=None, slug=None, display=None, body=None, article_id=None):
return self.processnew (title=title, slug=slug, display=display,
body=body, article_id=article_id, edit=True)
processedit.exposed = True
def processnew (self, title=None, slug=None, display=None, body=None, article_id=None,
edit=False):
# Verify user is logged-in admin.
if (not pageutils.is_admin_p()):
raise cherrypy.HTTPRedirect ("/")
# If we got to this page through the /admin/articles/new form, all fields
# should be filled in. If they aren't, something unexpected happened, and
# we shouldn't continue processing the form.
if (title == None or slug == None or display == None or body == None):
return pageutils.generate_page ("Invalid Input for New Article",
"Invalid Input for New Article!")
else:
# Remove any leading or trailing spaces.
title = string.strip (title)
slug = string.strip (slug)
body = string.strip (body)
display = string.strip (display)
author_id = pageutils.get_user_id()
try:
# Connect to the database and insert the values.
dbconnection = pgdb.connect (database_connect_fields)
dbcursor = dbconnection.cursor()
if (edit):
if (article_id == None):
return pageutils.generate_page ("No Article Id Specified",
"No Article Id Specified")
dbcursor.execute ("UPDATE articles SET title=%s, slug=%s, body=%s, display=%d WHERE article_id=%d",
[title, slug, body, int(display), int(article_id)])
else:
dbcursor.execute ("INSERT INTO articles (title, author_id, slug, body, display, creation_date) " +
"VALUES (%s, %s, %s, %s, %s, current_timestamp)",
[title, author_id, slug, body, display])
dbconnection.commit()
# Close the database cursor and connection.
dbcursor.close()
dbconnection.close()
except:
return pageutils.generate_page ("Invalid SQL Query", "Invalid SQL Query!")
raise cherrypy.HTTPRedirect ("/admin/articles/")
processnew.exposed = True
def delete (self, article_id=None):
# Verify user is logged-in admin
if (not pageutils.is_admin_p()):
raise cherrypy.HTTPRedirect ("/")
pagetext = "<p><a href=\"/admin/articles/processdelete/" + str(article_id) + "\">Confirm article/comment deletion</a></p>\n"
return pageutils.generate_page ("Confirm Deletion", pagetext)
delete.exposed = True
def processdelete (self, article_id=None):
# Verify user is logged-in admin.
if (not pageutils.is_admin_p()):
raise cherrypy.HTTPRedirect ("/")
# Verify we have an article_id
if (article_id == None):
return pageutils.generate_page ("No Article Id Specified", "Nothing to delete!")
try:
# Connect to the database and delete the given article.
dbconnection = pgdb.connect (database_connect_fields)
dbcursor = dbconnection.cursor()
dbcursor.execute ("DELETE FROM articles WHERE article_id=%s", [str(article_id)])
dbconnection.commit()
# Close the database cursor and connection.
dbcursor.close()
dbconnection.close()
except:
return pageutils.generate_page ("Database Error", "Deletion failed!")
return pageutils.generate_page ("Successful Deletion", "The specified article/comment has been deleted.")
processdelete.exposed = True
def edit (self, article_slug = None):
# Verify user is logged-in admin.
if (not pageutils.is_admin_p()):
raise cherrypy.HTTPRedirect ("/")
# Verify we have an article to work with.
if (article_slug == None):
raise cherrypy.HTTPRedirect ("/articles/")
description = None
results = None
# Try to connect to the database.
try:
dbconnection = pgdb.connect (database_connect_fields)
dbcursor = dbconnection.cursor()
dbcursor.execute ("SELECT * FROM articles WHERE slug=%s", [article_slug])
# Get the cursor description and results from the query.
description = dbcursor.description
results = dbcursor.fetchone()
# Close the database cursor and connection.
dbcursor.close()
dbconnection.close()
except:
pass
if (results == None):
return pageutils.generate_page ("Invalid Article Specified", "Invalid Article Specified")
# Obtain the article title from the database results.
title = ""
try:
title = results[sqlutils.getfieldindex ("title", description)]
except:
pass
# Obtain the article body from the database results.
body = ""
try:
body = results[sqlutils.getfieldindex ("body", description)]
except:
pass
# Obtain the article display value.
display = ""
try:
display = str(results[sqlutils.getfieldindex ("display", description)])
except:
pass
# Obtain the article_id.
article_id = ""
try:
article_id = str(results[sqlutils.getfieldindex ("article_id", description)])
except:
pass
slug = article_slug
return self.new (edit=True, title=title, body=body, display=display, slug=slug, article_id=article_id)
edit.exposed = True
class AdminDiscussionsPage:
def index (self):
# No reason to present listing of discussions, as this is
# available from the main public view.
return "ADMIN: Select admin options from a particular discussion."
index.exposed = True
def delete (self, discussion_id=None):
# Verify user is logged-in admin
if (not pageutils.is_admin_p()):
raise cherrypy.HTTPRedirect ("/")
pagetext = "<p><a href=\"/admin/discussions/processdelete/" + str(discussion_id) + "\">Confirm discussion/reply deletion</a></p>\n"
return pageutils.generate_page ("Confirm Deletion", pagetext)
delete.exposed = True
def processdelete (self, discussion_id=None):
# Verify user is logged-in admin.
if (not pageutils.is_admin_p()):
raise cherrypy.HTTPRedirect ("/")
# Verify we have an discussion_id
if (discussion_id == None):
return pageutils.generate_page ("No Discussion Id Specified", "Nothing to delete!")
try:
# Connect to the database and delete the given discussion.
dbconnection = pgdb.connect (database_connect_fields)
dbcursor = dbconnection.cursor()
dbcursor.execute ("DELETE FROM discussions WHERE discussion_id=%s",
[str(discussion_id)])
dbconnection.commit()
# Also delete replies, if any.
dbcursor.execute ("DELETE FROM discussions WHERE refers_to=%s",
[str(discussion_id)])
dbconnection.commit()
# Close the database cursor and connection.
dbcursor.close()
dbconnection.close()
except:
return pageutils.generate_page ("Database Error", "Deletion failed!")
return pageutils.generate_page ("Successful Deletion",
"The specified discussion/reply has been deleted.")
processdelete.exposed = True
class AdminEventsPage:
def index (self):
# Verify user is logged-in admin.
if (not pageutils.is_admin_p()):
raise cherrypy.HTTPRedirect ("/")
# No reason to present listing of events, as this is available
# from the main public view.
return "ADMIN: Select admin options from a particular event."
index.exposed = True
def delete (self, event_id=None):
# Verify user is logged-in admin
if (not pageutils.is_admin_p()):
raise cherrypy.HTTPRedirect ("/")
pagetext = "<p><a href=\"/admin/events/processdelete/" + str(event_id) + "\">Confirm event deletion</a></p>\n"
return pageutils.generate_page ("Confirm Deletion", pagetext)
delete.exposed = True
def processdelete (self, event_id=None):
# Verify user is logged-in admin.
if (not pageutils.is_admin_p()):
raise cherrypy.HTTPRedirect ("/")
# Verify we have an event_id
if (event_id == None):
return pageutils.generate_page ("No Event Id Specified", "Nothing to delete!")
try:
# Connect to the database and delete the given discussion.
dbconnection = pgdb.connect (database_connect_fields)
dbcursor = dbconnection.cursor()
dbcursor.execute ("DELETE FROM events WHERE event_id=%s",
[str(event_id)])
dbconnection.commit()
# Close the database cursor and connection.
dbcursor.close()
dbconnection.close()
except:
return pageutils.generate_page ("Database Error", "Deletion failed!")
return pageutils.generate_page ("Successful Deletion",
"The specified event has been deleted.")
processdelete.exposed = True
class AdminPage:
def __init__(self):
# Set up the nested admin page classes. No reason
# to maintain these from the top-level index.py file.
self.users = AdminUsersPage()
self.articles = AdminArticlesPage()
self.discussions = AdminDiscussionsPage()
self.events = AdminEventsPage()
def index (self):
# Verify user is logged-in admin.
if (not pageutils.is_admin_p()):
raise cherrypy.HTTPRedirect ("/")
# Present menu of administrative activities
return """
<ul>
<li><a href=\"/admin/users/\">Users Admin</a></li>
<li><a href=\"/admin/articles/\">Articles Admin</a></li>
<li><a href=\"/admin/discussions/\">Discussions Admin</a></li>
<li><a href=\"/admin/events/\">Events Admin</a></li>
</ul>"""
index.exposed = True