Fossil SCM
Add the "unused" query parameter to the /setup_ulist page.
Commit
7711a4fbc2e214b3406ab72d459a563985b57040b2c2e69a22d40881ee07a5d9
Parent
2cdd7573ed8acd8…
1 file changed
+22
-6
+22
-6
| --- src/setupuser.c | ||
| +++ src/setupuser.c | ||
| @@ -35,10 +35,11 @@ | ||
| 35 | 35 | */ |
| 36 | 36 | void setup_ulist(void){ |
| 37 | 37 | Stmt s; |
| 38 | 38 | double rNow; |
| 39 | 39 | const char *zWith = P("with"); |
| 40 | + int bUnusedOnly = P("unused")!=0; | |
| 40 | 41 | |
| 41 | 42 | login_check_credentials(); |
| 42 | 43 | if( !g.perm.Admin ){ |
| 43 | 44 | login_needed(0); |
| 44 | 45 | return; |
| @@ -49,11 +50,11 @@ | ||
| 49 | 50 | style_submenu_element("Help", "setup_ulist_notes"); |
| 50 | 51 | if( alert_tables_exist() ){ |
| 51 | 52 | style_submenu_element("Subscribers", "subscribers"); |
| 52 | 53 | } |
| 53 | 54 | style_header("User List"); |
| 54 | - if( zWith==0 || zWith[0]==0 ){ | |
| 55 | + if( (zWith==0 || zWith[0]==0) && !bUnusedOnly ){ | |
| 55 | 56 | @ <table border=1 cellpadding=2 cellspacing=0 class='userTable'> |
| 56 | 57 | @ <thead><tr> |
| 57 | 58 | @ <th>Category |
| 58 | 59 | @ <th>Capabilities (<a href='%R/setup_ucap_list'>key</a>) |
| 59 | 60 | @ <th>Info <th>Last Change</tr></thead> |
| @@ -94,16 +95,23 @@ | ||
| 94 | 95 | db_finalize(&s); |
| 95 | 96 | @ </tbody></table> |
| 96 | 97 | @ <div class='section'>Users</div> |
| 97 | 98 | }else{ |
| 98 | 99 | style_submenu_element("All Users", "setup_ulist"); |
| 99 | - if( zWith[1]==0 ){ | |
| 100 | - @ <div class='section'>Users with capability "%h(zWith)"</div> | |
| 101 | - }else{ | |
| 102 | - @ <div class='section'>Users with any capability in "%h(zWith)"</div> | |
| 100 | + if( bUnusedOnly ){ | |
| 101 | + @ <div class='section'>Unused logins</div> | |
| 102 | + }else if( zWith ){ | |
| 103 | + if( zWith[1]==0 ){ | |
| 104 | + @ <div class='section'>Users with capability "%h(zWith)"</div> | |
| 105 | + }else{ | |
| 106 | + @ <div class='section'>Users with any capability in "%h(zWith)"</div> | |
| 107 | + } | |
| 103 | 108 | } |
| 104 | 109 | } |
| 110 | + if( !bUnusedOnly ){ | |
| 111 | + style_submenu_element("Unused", "setup_ulist?unused"); | |
| 112 | + } | |
| 105 | 113 | @ <table border=1 cellpadding=2 cellspacing=0 class='userTable sortable' \ |
| 106 | 114 | @ data-column-types='ktxTTK' data-init-sort='2'> |
| 107 | 115 | @ <thead><tr> |
| 108 | 116 | @ <th>Login Name<th>Caps<th>Info<th>Date<th>Expire<th>Last Login</tr></thead> |
| 109 | 117 | @ <tbody> |
| @@ -120,11 +128,19 @@ | ||
| 120 | 128 | " SELECT login AS uname, rcvfrom.mtime AS mtime" |
| 121 | 129 | " FROM rcvfrom JOIN user USING(uid))" |
| 122 | 130 | " GROUP BY 1;" |
| 123 | 131 | ); |
| 124 | 132 | } |
| 125 | - if( zWith && zWith[0] ){ | |
| 133 | + if( bUnusedOnly ){ | |
| 134 | + zWith = mprintf( | |
| 135 | + " AND login NOT IN (" | |
| 136 | + "SELECT user FROM event WHERE user NOT NULL " | |
| 137 | + "UNION ALL SELECT euser FROM event WHERE euser NOT NULL%s)" | |
| 138 | + " AND uid NOT IN (SELECT uid FROM rcvfrom)", | |
| 139 | + alert_tables_exist() ? | |
| 140 | + " UNION ALL SELECT suname FROM subscriber WHERE suname NOT NULL":""); | |
| 141 | + }else if( zWith && zWith[0] ){ | |
| 126 | 142 | zWith = mprintf(" AND fullcap(cap) GLOB '*[%q]*'", zWith); |
| 127 | 143 | }else{ |
| 128 | 144 | zWith = ""; |
| 129 | 145 | } |
| 130 | 146 | db_prepare(&s, |
| 131 | 147 |
| --- src/setupuser.c | |
| +++ src/setupuser.c | |
| @@ -35,10 +35,11 @@ | |
| 35 | */ |
| 36 | void setup_ulist(void){ |
| 37 | Stmt s; |
| 38 | double rNow; |
| 39 | const char *zWith = P("with"); |
| 40 | |
| 41 | login_check_credentials(); |
| 42 | if( !g.perm.Admin ){ |
| 43 | login_needed(0); |
| 44 | return; |
| @@ -49,11 +50,11 @@ | |
| 49 | style_submenu_element("Help", "setup_ulist_notes"); |
| 50 | if( alert_tables_exist() ){ |
| 51 | style_submenu_element("Subscribers", "subscribers"); |
| 52 | } |
| 53 | style_header("User List"); |
| 54 | if( zWith==0 || zWith[0]==0 ){ |
| 55 | @ <table border=1 cellpadding=2 cellspacing=0 class='userTable'> |
| 56 | @ <thead><tr> |
| 57 | @ <th>Category |
| 58 | @ <th>Capabilities (<a href='%R/setup_ucap_list'>key</a>) |
| 59 | @ <th>Info <th>Last Change</tr></thead> |
| @@ -94,16 +95,23 @@ | |
| 94 | db_finalize(&s); |
| 95 | @ </tbody></table> |
| 96 | @ <div class='section'>Users</div> |
| 97 | }else{ |
| 98 | style_submenu_element("All Users", "setup_ulist"); |
| 99 | if( zWith[1]==0 ){ |
| 100 | @ <div class='section'>Users with capability "%h(zWith)"</div> |
| 101 | }else{ |
| 102 | @ <div class='section'>Users with any capability in "%h(zWith)"</div> |
| 103 | } |
| 104 | } |
| 105 | @ <table border=1 cellpadding=2 cellspacing=0 class='userTable sortable' \ |
| 106 | @ data-column-types='ktxTTK' data-init-sort='2'> |
| 107 | @ <thead><tr> |
| 108 | @ <th>Login Name<th>Caps<th>Info<th>Date<th>Expire<th>Last Login</tr></thead> |
| 109 | @ <tbody> |
| @@ -120,11 +128,19 @@ | |
| 120 | " SELECT login AS uname, rcvfrom.mtime AS mtime" |
| 121 | " FROM rcvfrom JOIN user USING(uid))" |
| 122 | " GROUP BY 1;" |
| 123 | ); |
| 124 | } |
| 125 | if( zWith && zWith[0] ){ |
| 126 | zWith = mprintf(" AND fullcap(cap) GLOB '*[%q]*'", zWith); |
| 127 | }else{ |
| 128 | zWith = ""; |
| 129 | } |
| 130 | db_prepare(&s, |
| 131 |
| --- src/setupuser.c | |
| +++ src/setupuser.c | |
| @@ -35,10 +35,11 @@ | |
| 35 | */ |
| 36 | void setup_ulist(void){ |
| 37 | Stmt s; |
| 38 | double rNow; |
| 39 | const char *zWith = P("with"); |
| 40 | int bUnusedOnly = P("unused")!=0; |
| 41 | |
| 42 | login_check_credentials(); |
| 43 | if( !g.perm.Admin ){ |
| 44 | login_needed(0); |
| 45 | return; |
| @@ -49,11 +50,11 @@ | |
| 50 | style_submenu_element("Help", "setup_ulist_notes"); |
| 51 | if( alert_tables_exist() ){ |
| 52 | style_submenu_element("Subscribers", "subscribers"); |
| 53 | } |
| 54 | style_header("User List"); |
| 55 | if( (zWith==0 || zWith[0]==0) && !bUnusedOnly ){ |
| 56 | @ <table border=1 cellpadding=2 cellspacing=0 class='userTable'> |
| 57 | @ <thead><tr> |
| 58 | @ <th>Category |
| 59 | @ <th>Capabilities (<a href='%R/setup_ucap_list'>key</a>) |
| 60 | @ <th>Info <th>Last Change</tr></thead> |
| @@ -94,16 +95,23 @@ | |
| 95 | db_finalize(&s); |
| 96 | @ </tbody></table> |
| 97 | @ <div class='section'>Users</div> |
| 98 | }else{ |
| 99 | style_submenu_element("All Users", "setup_ulist"); |
| 100 | if( bUnusedOnly ){ |
| 101 | @ <div class='section'>Unused logins</div> |
| 102 | }else if( zWith ){ |
| 103 | if( zWith[1]==0 ){ |
| 104 | @ <div class='section'>Users with capability "%h(zWith)"</div> |
| 105 | }else{ |
| 106 | @ <div class='section'>Users with any capability in "%h(zWith)"</div> |
| 107 | } |
| 108 | } |
| 109 | } |
| 110 | if( !bUnusedOnly ){ |
| 111 | style_submenu_element("Unused", "setup_ulist?unused"); |
| 112 | } |
| 113 | @ <table border=1 cellpadding=2 cellspacing=0 class='userTable sortable' \ |
| 114 | @ data-column-types='ktxTTK' data-init-sort='2'> |
| 115 | @ <thead><tr> |
| 116 | @ <th>Login Name<th>Caps<th>Info<th>Date<th>Expire<th>Last Login</tr></thead> |
| 117 | @ <tbody> |
| @@ -120,11 +128,19 @@ | |
| 128 | " SELECT login AS uname, rcvfrom.mtime AS mtime" |
| 129 | " FROM rcvfrom JOIN user USING(uid))" |
| 130 | " GROUP BY 1;" |
| 131 | ); |
| 132 | } |
| 133 | if( bUnusedOnly ){ |
| 134 | zWith = mprintf( |
| 135 | " AND login NOT IN (" |
| 136 | "SELECT user FROM event WHERE user NOT NULL " |
| 137 | "UNION ALL SELECT euser FROM event WHERE euser NOT NULL%s)" |
| 138 | " AND uid NOT IN (SELECT uid FROM rcvfrom)", |
| 139 | alert_tables_exist() ? |
| 140 | " UNION ALL SELECT suname FROM subscriber WHERE suname NOT NULL":""); |
| 141 | }else if( zWith && zWith[0] ){ |
| 142 | zWith = mprintf(" AND fullcap(cap) GLOB '*[%q]*'", zWith); |
| 143 | }else{ |
| 144 | zWith = ""; |
| 145 | } |
| 146 | db_prepare(&s, |
| 147 |