Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | More infrastructure for wiki and ticket moderation. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | moderation |
| Files: | files | file ages | folders |
| SHA1: |
f7938ebd00ee6d47fa7684c44de4be68 |
| User & Date: | drh 2012-11-01 13:11:52.739 |
Context
|
2012-11-01
| ||
| 14:34 | Wiki moderation now appears to be working. ... (check-in: b7ccf110f3 user: drh tags: moderation) | |
| 13:11 | More infrastructure for wiki and ticket moderation. ... (check-in: f7938ebd00 user: drh tags: moderation) | |
|
2012-10-31
| ||
| 23:07 | Improvements to the display of Wiki and Ticket changes. ... (check-in: ba0ae3b24a user: drh tags: moderation) | |
Changes
Changes to src/info.c.
| ︙ | ︙ | |||
1628 1629 1630 1631 1632 1633 1634 |
**
** Show the details of a ticket change control artifact.
*/
void tinfo_page(void){
int rid;
char *zDate;
const char *zUuid;
| | | 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 |
**
** Show the details of a ticket change control artifact.
*/
void tinfo_page(void){
int rid;
char *zDate;
const char *zUuid;
char zTktName[UUID_SIZE+1];
Manifest *pTktChng;
login_check_credentials();
if( !g.perm.RdTkt ){ login_needed(); return; }
rid = name_to_rid_www("name");
if( rid==0 ){ fossil_redirect_home(); }
zUuid = db_text("", "SELECT uuid FROM blob WHERE rid=%d", rid);
|
| ︙ | ︙ | |||
1651 1652 1653 1654 1655 1656 1657 |
}
pTktChng = manifest_get(rid, CFTYPE_TICKET);
if( pTktChng==0 ){
fossil_redirect_home();
}
style_header("Ticket Change Details");
zDate = db_text(0, "SELECT datetime(%.12f)", pTktChng->rDate);
| | | | < < > > > > > | 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 |
}
pTktChng = manifest_get(rid, CFTYPE_TICKET);
if( pTktChng==0 ){
fossil_redirect_home();
}
style_header("Ticket Change Details");
zDate = db_text(0, "SELECT datetime(%.12f)", pTktChng->rDate);
memcpy(zTktName, pTktChng->zTicketUuid, UUID_SIZE);
zTktName[UUID_SIZE] = 0;
if( g.perm.Hyperlink ){
@ <h2>Changes to ticket
@ %z(href("%R/tktview/%s",zTktName))%s(zTktName)</a></h2>
@
@ <p>By %h(pTktChng->zUser) on %s(zDate).
style_submenu_element("Raw", "Raw", "%R/artifact/%T", zUuid);
style_submenu_element("History", "History",
"%R/tkthistory/%s", pTktChng->zTicketUuid);
}else{
@ <h2>Changes to ticket %s(zTktName)</h2>
@
@ <p>By %h(pTktChng->zUser) on %s(zDate).
@ </p>
}
free(zDate);
ticket_output_change_artifact(pTktChng);
manifest_destroy(pTktChng);
if( g.perm.Setup ){
@
@ <p>These changes are implemented by artifact
@ %z(href("%R/artifact/%s",zUuid))%s(zUuid)</a> (%d(rid)).</p>
}
style_footer();
}
/*
** WEBPAGE: info
** URL: info/ARTIFACTID
|
| ︙ | ︙ |
Changes to src/moderate.c.
| ︙ | ︙ | |||
18 19 20 21 22 23 24 | ** This file contains code used to deal with moderator actions for ** Wiki and Tickets. */ #include "config.h" #include "moderate.h" #include <assert.h> | < | < | > | > > > | > > > > > > > > > > > | > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > | > > > > > > > > | > > > > > > > > > > > | 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 |
** This file contains code used to deal with moderator actions for
** Wiki and Tickets.
*/
#include "config.h"
#include "moderate.h"
#include <assert.h>
/*
** Create a table to represent pending moderation requests, if the
** table does not already exist.
*/
void moderation_table_create(void){
db_multi_exec(
"CREATE TABLE IF NOT EXISTS modreq(\n"
" objid INTEGER PRIMARY KEY,\n" /* Record pending approval */
" parent INTEGER REFERENCES modreq,\n" /* Parent record */
" tktid TEXT\n" /* Associated ticket id */
");\n"
);
}
/*
** Return TRUE if the modreq table exists
*/
int moderation_table_exists(void){
static int modreqExists = -1;
if( modreqExists<0 ){
modreqExists = db_exists("SELECT 1 FROM %s.sqlite_master"
" WHERE name='modreq'", db_name("repository"));
}
return modreqExists;
}
/*
** Return TRUE if the object specified is being held for moderation.
*/
int moderation_pending(int rid){
static Stmt q;
int rc;
if( rid==0 || !moderation_table_exists() ) return 0;
db_static_prepare(&q, "SELECT 1 FROM modreq WHERE objid=:objid");
db_bind_int(&q, ":objid", rid);
rc = db_step(&q)==SQLITE_ROW;
db_reset(&q);
return rc;
}
/*
** Delete a moderation item given by rid
*/
void moderation_disapprove(int rid){
Stmt q;
char *zTktid;
if( !moderation_pending(rid) ) return;
if( content_is_private(rid) ){
db_prepare(&q, "SELECT rid FROM delta WHERE srcid=%d", rid);
while( db_step(&q)==SQLITE_ROW ){
int ridUser = db_column_int(&q, 0);
content_undelta(ridUser);
}
db_finalize(&q);
db_multi_exec(
"DELETE FROM blob WHERE rid=%d;"
"DELETE FROM delta WHERE rid=%d;"
"DELETE FROM event WHERE objid=%d;"
"DELETE FROM tagxref WHERE rid=%d;"
"DELETE FROM private WHERE rid=%d;",
rid, rid, rid, rid, rid
);
zTktid = db_text(0, "SELECT tktid FROm modreq WHERE objid=%d", rid);
if( zTktid ){
ticket_rebuild_entry(zTktid);
fossil_free(zTktid);
}
}
db_prepare(&q, "SELECT objid FROM modreq WHERE parent=%d AND "
"UNION SELECT parent FROM modreq WHERE objid=%d",
rid, rid);
while( db_step(&q)==SQLITE_ROW ){
int other = db_column_int(&q, 0);
if( other==rid ) continue;
moderation_approve(other);
}
db_finalize(&q);
db_multi_exec("DELETE FROM modreq WHERE objid=%d", rid);
}
/*
** Approve an object held for moderation.
*/
void moderation_approve(int rid){
Stmt q;
if( !moderation_pending(rid) ) return;
db_multi_exec("DELETE FROM private WHERE rid=%d;", rid);
db_prepare(&q, "SELECT objid FROM modreq WHERE parent=%d AND "
"UNION SELECT parent FROM modreq WHERE objid=%d",
rid, rid);
while( db_step(&q)==SQLITE_ROW ){
int other = db_column_int(&q, 0);
if( other==rid ) continue;
moderation_approve(other);
}
db_finalize(&q);
db_multi_exec("DELETE FROM modreq WHERE objid=%d", rid);
}
/*
** WEBPAGE: modreq
**
** Show all pending moderation request
*/
void modreq_page(void){
Blob sql;
Stmt q;
login_check_credentials();
if( !g.perm.RdWiki && !g.perm.RdTkt ){ login_needed(); return; }
style_header("Pending Moderation Requests");
blob_init(&sql, timeline_query_for_www(), -1);
blob_appendf(&sql,
" AND event.objid IN (SELECT objid FROM modreq)"
" ORDER BY event.mtime DESC"
);
db_prepare(&q, blob_str(&sql));
www_print_timeline(&q, 0, 0, 0, 0);
db_finalize(&q);
style_footer();
}
|
Changes to src/style.c.
| ︙ | ︙ | |||
928 929 930 931 932 933 934 |
@ background-color: #ffc8c8;
},
{ "span.diffhr",
"suppressed lines in a diff",
@ color: #0000ff;
},
{ "span.diffln",
| | > > > > > | 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 |
@ background-color: #ffc8c8;
},
{ "span.diffhr",
"suppressed lines in a diff",
@ color: #0000ff;
},
{ "span.diffln",
"line numbers in a diff",
@ color: #a0a0a0;
},
{ "span.modpending",
"Moderation Pending message on timelin",
@ color: #b03800;
@ font-style: italic;
},
{ 0,
0,
0
}
};
/*
|
| ︙ | ︙ |
Changes to src/timeline.c.
| ︙ | ︙ | |||
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 |
const char *zDate = db_column_text(pQuery, 2);
const char *zType = db_column_text(pQuery, 7);
const char *zUser = db_column_text(pQuery, 4);
const char *zTagList = db_column_text(pQuery, 8);
int tagid = db_column_int(pQuery, 9);
const char *zBr = 0; /* Branch */
int commentColumn = 3; /* Column containing comment text */
char zTime[8];
if( tagid ){
if( tagid==prevTagid ){
if( tmFlags & TIMELINE_BRIEF ){
suppressCnt++;
continue;
}else{
commentColumn = 10;
}
| > > > > | 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 |
const char *zDate = db_column_text(pQuery, 2);
const char *zType = db_column_text(pQuery, 7);
const char *zUser = db_column_text(pQuery, 4);
const char *zTagList = db_column_text(pQuery, 8);
int tagid = db_column_int(pQuery, 9);
const char *zBr = 0; /* Branch */
int commentColumn = 3; /* Column containing comment text */
int modPending; /* Pending moderation */
char zTime[8];
modPending = moderation_pending(rid);
if( tagid ){
if( modPending ) tagid = -tagid;
if( tagid==prevTagid ){
if( tmFlags & TIMELINE_BRIEF ){
suppressCnt++;
continue;
}else{
commentColumn = 10;
}
|
| ︙ | ︙ | |||
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 |
@ <td class="timelineTableCell" style="background-color: %h(zBgClr);">
}else{
@ <td class="timelineTableCell">
}
if( pGraph && zType[0]!='c' ){
@ •
}
if( zType[0]=='c' ){
hyperlink_to_uuid(zUuid);
if( isLeaf ){
if( db_exists("SELECT 1 FROM tagxref"
" WHERE rid=%d AND tagid=%d AND tagtype>0",
rid, TAG_CLOSED) ){
@ <span class="timelineLeaf">Closed-Leaf:</span>
}else{
@ <span class="timelineLeaf">Leaf:</span>
}
}
}else if( zType[0]=='e' && tagid ){
| > > > | | 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 |
@ <td class="timelineTableCell" style="background-color: %h(zBgClr);">
}else{
@ <td class="timelineTableCell">
}
if( pGraph && zType[0]!='c' ){
@ •
}
if( modPending ){
@ <span class="modpending">(Pending Moderation)</span>
}
if( zType[0]=='c' ){
hyperlink_to_uuid(zUuid);
if( isLeaf ){
if( db_exists("SELECT 1 FROM tagxref"
" WHERE rid=%d AND tagid=%d AND tagtype>0",
rid, TAG_CLOSED) ){
@ <span class="timelineLeaf">Closed-Leaf:</span>
}else{
@ <span class="timelineLeaf">Leaf:</span>
}
}
}else if( zType[0]=='e' && tagid ){
hyperlink_to_event_tagid(tagid<0?-tagid:tagid);
}else if( (tmFlags & TIMELINE_ARTID)!=0 ){
hyperlink_to_uuid(zUuid);
}
db_column_blob(pQuery, commentColumn, &comment);
if( mxWikiLen>0 && blob_size(&comment)>mxWikiLen ){
Blob truncated;
blob_zero(&truncated);
|
| ︙ | ︙ | |||
359 360 361 362 363 364 365 |
char *zLink = mprintf("%R/timeline?u=%h&c=%t&nd", zUser, zDate);
@ (user: %z(href("%z",zLink))%h(zUser)</a>%s(zTagList?",":"\051")
}else{
@ (user: %h(zUser)%s(zTagList?",":"\051")
}
/* Generate a "detail" link for tags. */
| | | 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 |
char *zLink = mprintf("%R/timeline?u=%h&c=%t&nd", zUser, zDate);
@ (user: %z(href("%z",zLink))%h(zUser)</a>%s(zTagList?",":"\051")
}else{
@ (user: %h(zUser)%s(zTagList?",":"\051")
}
/* Generate a "detail" link for tags. */
if( (zType[0]=='g' || zType[0]=='w' || zType[0]=='t') && g.perm.Hyperlink ){
@ [%z(href("%R/info/%S",zUuid))details</a>]
}
/* Generate the "tags: TAGLIST" at the end of the comment, together
** with hyperlinks to the tag list.
*/
if( zTagList ){
|
| ︙ | ︙ |