| | @@ -272,5 +272,88 @@ |
| 272 | 272 | @ <td><i>Announce:</i> Send announcements</td></tr> |
| 273 | 273 | @ <tr><th valign="top">D</th> |
| 274 | 274 | @ <td><i>Debug:</i> Enable debugging features</td></tr> |
| 275 | 275 | @ </table> |
| 276 | 276 | } |
| 277 | + |
| 278 | +/* |
| 279 | +** Generate a "capability summary table" that shows the major capabilities |
| 280 | +** against the various user categories. |
| 281 | +*/ |
| 282 | +void capability_summary(void){ |
| 283 | + Stmt q; |
| 284 | + db_prepare(&q, |
| 285 | + "WITH t(id,seq) AS (VALUES('nobody',1),('anonymous',2),('reader',3)," |
| 286 | + "('developer',4))" |
| 287 | + " SELECT id, fullcap(user.cap),seq FROM t LEFT JOIN user ON t.id=user.login" |
| 288 | + " UNION ALL" |
| 289 | + " SELECT 'Regular Users', fullcap(capunion(cap)), 5 FROM user" |
| 290 | + " WHERE cap NOT GLOB '*[as]*'" |
| 291 | + " UNION ALL" |
| 292 | + " SELECT 'Admins', fullcap(capunion(cap)), 6 FROM user" |
| 293 | + " WHERE cap GLOB '*[as]*'" |
| 294 | + " ORDER BY 3 ASC" |
| 295 | + ); |
| 296 | + @ <table id='capabilitySummary' cellpadding="0" cellspacing="0" border="1"> |
| 297 | + @ <tr><th> <th>Code<th>Forum<th>Tickets<th>Wiki\ |
| 298 | + @ <th>Unversioned Content</th></tr> |
| 299 | + while( db_step(&q)==SQLITE_ROW ){ |
| 300 | + const char *zId = db_column_text(&q, 0); |
| 301 | + const char *zCap = db_column_text(&q, 1); |
| 302 | + int eType; |
| 303 | + static const char *azType[] = { "off", "read", "write" }; |
| 304 | + |
| 305 | + /* Code */ |
| 306 | + @ <tr><th align="right">%h(zId)</th> |
| 307 | + if( sqlite3_strglob("*[asi]*",zCap)==0 ){ |
| 308 | + eType = 2; |
| 309 | + }else if( sqlite3_strglob("*[oz]*",zCap)==0 ){ |
| 310 | + eType = 1; |
| 311 | + }else{ |
| 312 | + eType = 0; |
| 313 | + } |
| 314 | + @ <td>%s(azType[eType])</td> |
| 315 | + |
| 316 | + /* Forum */ |
| 317 | + if( sqlite3_strglob("*[as3456]*",zCap)==0 ){ |
| 318 | + eType = 2; |
| 319 | + }else if( sqlite3_strglob("*2*",zCap)==0 ){ |
| 320 | + eType = 1; |
| 321 | + }else{ |
| 322 | + eType = 0; |
| 323 | + } |
| 324 | + @ <td>%s(azType[eType])</td> |
| 325 | + |
| 326 | + /* Ticket */ |
| 327 | + if( sqlite3_strglob("*[ascdnqtw]*",zCap)==0 ){ |
| 328 | + eType = 2; |
| 329 | + }else if( sqlite3_strglob("*r*",zCap)==0 ){ |
| 330 | + eType = 1; |
| 331 | + }else{ |
| 332 | + eType = 0; |
| 333 | + } |
| 334 | + @ <td>%s(azType[eType])</td> |
| 335 | + |
| 336 | + /* Wiki */ |
| 337 | + if( sqlite3_strglob("*[asdfjlm]*",zCap)==0 ){ |
| 338 | + eType = 2; |
| 339 | + }else if( sqlite3_strglob("*j*",zCap)==0 ){ |
| 340 | + eType = 1; |
| 341 | + }else{ |
| 342 | + eType = 0; |
| 343 | + } |
| 344 | + @ <td>%s(azType[eType])</td> |
| 345 | + |
| 346 | + /* Unversioned */ |
| 347 | + if( sqlite3_strglob("*y*",zCap)==0 ){ |
| 348 | + eType = 2; |
| 349 | + }else if( sqlite3_strglob("*o*",zCap)==0 ){ |
| 350 | + eType = 1; |
| 351 | + }else{ |
| 352 | + eType = 0; |
| 353 | + } |
| 354 | + @ <td>%s(azType[eType])</td> |
| 355 | + |
| 356 | + } |
| 357 | + db_finalize(&q); |
| 358 | + @ </table> |
| 359 | +} |
| 277 | 360 | |