Fossil SCM
Improved display of the user list on the setup menu.
Commit
d3fbf717386970ebb8c29630698f697745b0fa48
Parent
18df719ed566399…
1 file changed
+92
-50
+92
-50
| --- src/setup.c | ||
| +++ src/setup.c | ||
| @@ -145,77 +145,119 @@ | ||
| 145 | 145 | ** screen for that user. Requires Admin privileges. |
| 146 | 146 | */ |
| 147 | 147 | void setup_ulist(void){ |
| 148 | 148 | Stmt s; |
| 149 | 149 | int prevLevel = 0; |
| 150 | + int nRow = 0; | |
| 151 | + int iSort; | |
| 152 | + static const char *azSortOptions[] = { | |
| 153 | + "0", "Name", | |
| 154 | + "1", "Uid", | |
| 155 | + "2", "Capabilities", | |
| 156 | + "3", "Last Change", | |
| 157 | + "4", "Expiration" | |
| 158 | + }; | |
| 159 | + const char *zOrderBy[] = { | |
| 160 | + "login COLLATE nocase", | |
| 161 | + "uid", | |
| 162 | + "cap, login COLLATE nocase", | |
| 163 | + "mtime DESC", | |
| 164 | + "exp DESC, login COLLATE nocase" | |
| 165 | + }; | |
| 150 | 166 | |
| 151 | 167 | login_check_credentials(); |
| 152 | 168 | if( !g.perm.Admin ){ |
| 153 | 169 | login_needed(0); |
| 154 | 170 | return; |
| 155 | 171 | } |
| 172 | + iSort = atoi(PD("sx", "0")); | |
| 173 | + if( iSort<0 || iSort>ArraySize(zOrderBy) ) iSort = 0; | |
| 174 | + | |
| 156 | 175 | |
| 157 | 176 | style_submenu_element("Add", "Add User", "setup_uedit"); |
| 158 | 177 | style_submenu_element("Help", "Help", "setup_ulist_notes"); |
| 178 | + style_submenu_multichoice("sx", ArraySize(azSortOptions)/2, azSortOptions, 0); | |
| 159 | 179 | style_header("User List"); |
| 160 | - @ <table class="usetupUserList"> | |
| 161 | - prevLevel = 0; | |
| 180 | + @ <table border=0 cellpadding=0 cellspacing=0> | |
| 181 | + db_prepare(&s, | |
| 182 | + "SELECT uid, login, cap, info, datetime(mtime,'unixepoch'), NULL AS exp " | |
| 183 | + " FROM user" | |
| 184 | + " WHERE login IN ('anonymous','nobody','developer','reader')" | |
| 185 | + " ORDER BY %s", | |
| 186 | + zOrderBy[iSort]/*safe-for-%s*/ | |
| 187 | + ); | |
| 188 | + while( db_step(&s)==SQLITE_ROW ){ | |
| 189 | + int uid = db_column_int(&s, 0); | |
| 190 | + const char *zLogin = db_column_text(&s, 1); | |
| 191 | + const char *zCap = db_column_text(&s, 2); | |
| 192 | + const char *zDate = db_column_text(&s, 4); | |
| 193 | + if( nRow++ ){ | |
| 194 | + @ <tr><td colspan=3><hr></td></tr> | |
| 195 | + } | |
| 196 | + @ <tr><td valign='top'>Category:</td> | |
| 197 | + @ <td> </td> | |
| 198 | + @ <td><a href='setup_uedit?id=%d(uid)'>%h(zLogin)</a> | |
| 199 | + if( fossil_strcmp(zLogin,"anonymous")==0 ){ | |
| 200 | + @ (All logged-in users) | |
| 201 | + }else if( fossil_strcmp(zLogin,"developer")==0 ){ | |
| 202 | + @ (Users with '<b>v</b>' capability) | |
| 203 | + }else if( fossil_strcmp(zLogin,"nobody")==0 ){ | |
| 204 | + @ (All users without login) | |
| 205 | + }else if( fossil_strcmp(zLogin,"reader")==0 ){ | |
| 206 | + @ (Users with '<b>u</b>' capability) | |
| 207 | + } | |
| 208 | + @ </td></tr> | |
| 209 | + @ <tr><td valign='top'>Capabilities:</td><td></td> | |
| 210 | + @ <td>%h(zCap)</a></td></tr> | |
| 211 | + if( zDate && zDate[0] ){ | |
| 212 | + @ <tr><td valign='top'>Last change:</td><td></td> | |
| 213 | + @ <td>%h(zDate)</a></td></tr> | |
| 214 | + } | |
| 215 | + } | |
| 216 | + db_finalize(&s); | |
| 217 | + | |
| 218 | + nRow = 0; | |
| 162 | 219 | db_prepare(&s, |
| 163 | - "SELECT uid, login, cap, info, 1 FROM user" | |
| 164 | - " WHERE login IN ('anonymous','nobody','developer','reader') " | |
| 165 | - " UNION ALL " | |
| 166 | - "SELECT uid, login, cap, info, 2 FROM user" | |
| 167 | - " WHERE login NOT IN ('anonymous','nobody','developer','reader') " | |
| 168 | - "ORDER BY 5, 2 COLLATE nocase" | |
| 220 | + "SELECT uid, login, cap, info, datetime(mtime,'unixepoch'), " | |
| 221 | + " CASE WHEN info LIKE '%%expires 20%%'" | |
| 222 | + " THEN substr(info,instr(lower(info),'expires')+8,10)" | |
| 223 | + " END AS exp" | |
| 224 | + " FROM user" | |
| 225 | + " WHERE login NOT IN ('anonymous','nobody','developer','reader')" | |
| 226 | + " ORDER BY %s", | |
| 227 | + zOrderBy[iSort]/*safe-for-%s*/ | |
| 169 | 228 | ); |
| 170 | 229 | while( db_step(&s)==SQLITE_ROW ){ |
| 171 | - int iLevel = db_column_int(&s, 4); | |
| 172 | - const char *zCap = db_column_text(&s, 2); | |
| 230 | + int uid = db_column_int(&s, 0); | |
| 173 | 231 | const char *zLogin = db_column_text(&s, 1); |
| 174 | - if( iLevel>prevLevel ){ | |
| 175 | - if( prevLevel>0 ){ | |
| 176 | - @ <tr><td colspan="3"><hr></td></tr> | |
| 177 | - } | |
| 178 | - if( iLevel==1 ){ | |
| 179 | - @ <tr> | |
| 180 | - @ <th class="usetupListUser" | |
| 181 | - @ style="text-align: right;padding-right: 20px;">Category</th> | |
| 182 | - @ <th class="usetupListCap" | |
| 183 | - @ style="text-align: center;padding-right: 15px;">Capabilities</th> | |
| 184 | - @ <th class="usetupListCon" | |
| 185 | - @ style="text-align: left;">Notes</th> | |
| 186 | - @ </tr> | |
| 187 | - }else{ | |
| 188 | - @ <tr> | |
| 189 | - @ <th class="usetupListUser" | |
| 190 | - @ style="text-align: right;padding-right: 20px;">User ID</th> | |
| 191 | - @ <th class="usetupListCap" | |
| 192 | - @ style="text-align: center;padding-right: 15px;">Capabilities</th> | |
| 193 | - @ <th class="usetupListCon" | |
| 194 | - @ style="text-align: left;">Contact Info</th> | |
| 195 | - @ </tr> | |
| 196 | - } | |
| 197 | - prevLevel = iLevel; | |
| 198 | - } | |
| 199 | - @ <tr> | |
| 200 | - @ <td class="usetupListUser" | |
| 201 | - @ style="text-align: right;padding-right: 20px;white-space:nowrap;"> | |
| 202 | - if( g.perm.Admin && (zCap[0]!='s' || g.perm.Setup) ){ | |
| 203 | - @ <a href="setup_uedit?id=%d(db_column_int(&s,0))"> | |
| 204 | - } | |
| 205 | - @ %h(zLogin) | |
| 206 | - if( g.perm.Admin ){ | |
| 207 | - @ </a> | |
| 208 | - } | |
| 209 | - @ </td> | |
| 210 | - @ <td class="usetupListCap" style="text-align: center;padding-right: 15px;">%s(zCap)</td> | |
| 211 | - @ <td class="usetupListCon" style="text-align: left;">%h(db_column_text(&s,3))</td> | |
| 212 | - @ </tr> | |
| 232 | + const char *zCap = db_column_text(&s, 2); | |
| 233 | + const char *zInfo = db_column_text(&s, 3); | |
| 234 | + const char *zDate = db_column_text(&s, 4); | |
| 235 | + const char *zExp = db_column_text(&s,5); | |
| 236 | + if( (nRow++)==0 ){ | |
| 237 | + @ <tr><td colspan=3><div class='section'>Users</div></tr> | |
| 238 | + }else{ | |
| 239 | + @ <tr><td colspan=3><hr></td></tr> | |
| 240 | + } | |
| 241 | + @ <tr><td valign='top'>Username:</td><td></td> | |
| 242 | + @ <td><a href='setup_uedit?id=%d(uid)'>%h(zLogin) (uid: %d(uid))</a></td><tr> | |
| 243 | + @ <tr><td valign='top'>Capabilities:</td><td></td> | |
| 244 | + @ <td>%h(zCap)</a></td></tr> | |
| 245 | + if( zExp && zExp[0] ){ | |
| 246 | + @ <tr><td valign='top'>Login expires:</td><td></td> | |
| 247 | + @ <td>%h(zExp)</a></td></tr> | |
| 248 | + } | |
| 249 | + @ <tr><td valign='top'>Notes:</td><td></td> | |
| 250 | + @ <td>%h(zInfo)</a></td></tr> | |
| 251 | + if( zDate && zDate[0] ){ | |
| 252 | + @ <tr><td valign='top'>Last change:</td><td></td> | |
| 253 | + @ <td>%h(zDate)</a></td></tr> | |
| 254 | + } | |
| 213 | 255 | } |
| 214 | 256 | @ </table> |
| 215 | - style_footer(); | |
| 216 | 257 | db_finalize(&s); |
| 258 | + style_footer(); | |
| 217 | 259 | } |
| 218 | 260 | |
| 219 | 261 | /* |
| 220 | 262 | ** WEBPAGE: setup_ulist_notes |
| 221 | 263 | ** |
| 222 | 264 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -145,77 +145,119 @@ | |
| 145 | ** screen for that user. Requires Admin privileges. |
| 146 | */ |
| 147 | void setup_ulist(void){ |
| 148 | Stmt s; |
| 149 | int prevLevel = 0; |
| 150 | |
| 151 | login_check_credentials(); |
| 152 | if( !g.perm.Admin ){ |
| 153 | login_needed(0); |
| 154 | return; |
| 155 | } |
| 156 | |
| 157 | style_submenu_element("Add", "Add User", "setup_uedit"); |
| 158 | style_submenu_element("Help", "Help", "setup_ulist_notes"); |
| 159 | style_header("User List"); |
| 160 | @ <table class="usetupUserList"> |
| 161 | prevLevel = 0; |
| 162 | db_prepare(&s, |
| 163 | "SELECT uid, login, cap, info, 1 FROM user" |
| 164 | " WHERE login IN ('anonymous','nobody','developer','reader') " |
| 165 | " UNION ALL " |
| 166 | "SELECT uid, login, cap, info, 2 FROM user" |
| 167 | " WHERE login NOT IN ('anonymous','nobody','developer','reader') " |
| 168 | "ORDER BY 5, 2 COLLATE nocase" |
| 169 | ); |
| 170 | while( db_step(&s)==SQLITE_ROW ){ |
| 171 | int iLevel = db_column_int(&s, 4); |
| 172 | const char *zCap = db_column_text(&s, 2); |
| 173 | const char *zLogin = db_column_text(&s, 1); |
| 174 | if( iLevel>prevLevel ){ |
| 175 | if( prevLevel>0 ){ |
| 176 | @ <tr><td colspan="3"><hr></td></tr> |
| 177 | } |
| 178 | if( iLevel==1 ){ |
| 179 | @ <tr> |
| 180 | @ <th class="usetupListUser" |
| 181 | @ style="text-align: right;padding-right: 20px;">Category</th> |
| 182 | @ <th class="usetupListCap" |
| 183 | @ style="text-align: center;padding-right: 15px;">Capabilities</th> |
| 184 | @ <th class="usetupListCon" |
| 185 | @ style="text-align: left;">Notes</th> |
| 186 | @ </tr> |
| 187 | }else{ |
| 188 | @ <tr> |
| 189 | @ <th class="usetupListUser" |
| 190 | @ style="text-align: right;padding-right: 20px;">User ID</th> |
| 191 | @ <th class="usetupListCap" |
| 192 | @ style="text-align: center;padding-right: 15px;">Capabilities</th> |
| 193 | @ <th class="usetupListCon" |
| 194 | @ style="text-align: left;">Contact Info</th> |
| 195 | @ </tr> |
| 196 | } |
| 197 | prevLevel = iLevel; |
| 198 | } |
| 199 | @ <tr> |
| 200 | @ <td class="usetupListUser" |
| 201 | @ style="text-align: right;padding-right: 20px;white-space:nowrap;"> |
| 202 | if( g.perm.Admin && (zCap[0]!='s' || g.perm.Setup) ){ |
| 203 | @ <a href="setup_uedit?id=%d(db_column_int(&s,0))"> |
| 204 | } |
| 205 | @ %h(zLogin) |
| 206 | if( g.perm.Admin ){ |
| 207 | @ </a> |
| 208 | } |
| 209 | @ </td> |
| 210 | @ <td class="usetupListCap" style="text-align: center;padding-right: 15px;">%s(zCap)</td> |
| 211 | @ <td class="usetupListCon" style="text-align: left;">%h(db_column_text(&s,3))</td> |
| 212 | @ </tr> |
| 213 | } |
| 214 | @ </table> |
| 215 | style_footer(); |
| 216 | db_finalize(&s); |
| 217 | } |
| 218 | |
| 219 | /* |
| 220 | ** WEBPAGE: setup_ulist_notes |
| 221 | ** |
| 222 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -145,77 +145,119 @@ | |
| 145 | ** screen for that user. Requires Admin privileges. |
| 146 | */ |
| 147 | void setup_ulist(void){ |
| 148 | Stmt s; |
| 149 | int prevLevel = 0; |
| 150 | int nRow = 0; |
| 151 | int iSort; |
| 152 | static const char *azSortOptions[] = { |
| 153 | "0", "Name", |
| 154 | "1", "Uid", |
| 155 | "2", "Capabilities", |
| 156 | "3", "Last Change", |
| 157 | "4", "Expiration" |
| 158 | }; |
| 159 | const char *zOrderBy[] = { |
| 160 | "login COLLATE nocase", |
| 161 | "uid", |
| 162 | "cap, login COLLATE nocase", |
| 163 | "mtime DESC", |
| 164 | "exp DESC, login COLLATE nocase" |
| 165 | }; |
| 166 | |
| 167 | login_check_credentials(); |
| 168 | if( !g.perm.Admin ){ |
| 169 | login_needed(0); |
| 170 | return; |
| 171 | } |
| 172 | iSort = atoi(PD("sx", "0")); |
| 173 | if( iSort<0 || iSort>ArraySize(zOrderBy) ) iSort = 0; |
| 174 | |
| 175 | |
| 176 | style_submenu_element("Add", "Add User", "setup_uedit"); |
| 177 | style_submenu_element("Help", "Help", "setup_ulist_notes"); |
| 178 | style_submenu_multichoice("sx", ArraySize(azSortOptions)/2, azSortOptions, 0); |
| 179 | style_header("User List"); |
| 180 | @ <table border=0 cellpadding=0 cellspacing=0> |
| 181 | db_prepare(&s, |
| 182 | "SELECT uid, login, cap, info, datetime(mtime,'unixepoch'), NULL AS exp " |
| 183 | " FROM user" |
| 184 | " WHERE login IN ('anonymous','nobody','developer','reader')" |
| 185 | " ORDER BY %s", |
| 186 | zOrderBy[iSort]/*safe-for-%s*/ |
| 187 | ); |
| 188 | while( db_step(&s)==SQLITE_ROW ){ |
| 189 | int uid = db_column_int(&s, 0); |
| 190 | const char *zLogin = db_column_text(&s, 1); |
| 191 | const char *zCap = db_column_text(&s, 2); |
| 192 | const char *zDate = db_column_text(&s, 4); |
| 193 | if( nRow++ ){ |
| 194 | @ <tr><td colspan=3><hr></td></tr> |
| 195 | } |
| 196 | @ <tr><td valign='top'>Category:</td> |
| 197 | @ <td> </td> |
| 198 | @ <td><a href='setup_uedit?id=%d(uid)'>%h(zLogin)</a> |
| 199 | if( fossil_strcmp(zLogin,"anonymous")==0 ){ |
| 200 | @ (All logged-in users) |
| 201 | }else if( fossil_strcmp(zLogin,"developer")==0 ){ |
| 202 | @ (Users with '<b>v</b>' capability) |
| 203 | }else if( fossil_strcmp(zLogin,"nobody")==0 ){ |
| 204 | @ (All users without login) |
| 205 | }else if( fossil_strcmp(zLogin,"reader")==0 ){ |
| 206 | @ (Users with '<b>u</b>' capability) |
| 207 | } |
| 208 | @ </td></tr> |
| 209 | @ <tr><td valign='top'>Capabilities:</td><td></td> |
| 210 | @ <td>%h(zCap)</a></td></tr> |
| 211 | if( zDate && zDate[0] ){ |
| 212 | @ <tr><td valign='top'>Last change:</td><td></td> |
| 213 | @ <td>%h(zDate)</a></td></tr> |
| 214 | } |
| 215 | } |
| 216 | db_finalize(&s); |
| 217 | |
| 218 | nRow = 0; |
| 219 | db_prepare(&s, |
| 220 | "SELECT uid, login, cap, info, datetime(mtime,'unixepoch'), " |
| 221 | " CASE WHEN info LIKE '%%expires 20%%'" |
| 222 | " THEN substr(info,instr(lower(info),'expires')+8,10)" |
| 223 | " END AS exp" |
| 224 | " FROM user" |
| 225 | " WHERE login NOT IN ('anonymous','nobody','developer','reader')" |
| 226 | " ORDER BY %s", |
| 227 | zOrderBy[iSort]/*safe-for-%s*/ |
| 228 | ); |
| 229 | while( db_step(&s)==SQLITE_ROW ){ |
| 230 | int uid = db_column_int(&s, 0); |
| 231 | const char *zLogin = db_column_text(&s, 1); |
| 232 | const char *zCap = db_column_text(&s, 2); |
| 233 | const char *zInfo = db_column_text(&s, 3); |
| 234 | const char *zDate = db_column_text(&s, 4); |
| 235 | const char *zExp = db_column_text(&s,5); |
| 236 | if( (nRow++)==0 ){ |
| 237 | @ <tr><td colspan=3><div class='section'>Users</div></tr> |
| 238 | }else{ |
| 239 | @ <tr><td colspan=3><hr></td></tr> |
| 240 | } |
| 241 | @ <tr><td valign='top'>Username:</td><td></td> |
| 242 | @ <td><a href='setup_uedit?id=%d(uid)'>%h(zLogin) (uid: %d(uid))</a></td><tr> |
| 243 | @ <tr><td valign='top'>Capabilities:</td><td></td> |
| 244 | @ <td>%h(zCap)</a></td></tr> |
| 245 | if( zExp && zExp[0] ){ |
| 246 | @ <tr><td valign='top'>Login expires:</td><td></td> |
| 247 | @ <td>%h(zExp)</a></td></tr> |
| 248 | } |
| 249 | @ <tr><td valign='top'>Notes:</td><td></td> |
| 250 | @ <td>%h(zInfo)</a></td></tr> |
| 251 | if( zDate && zDate[0] ){ |
| 252 | @ <tr><td valign='top'>Last change:</td><td></td> |
| 253 | @ <td>%h(zDate)</a></td></tr> |
| 254 | } |
| 255 | } |
| 256 | @ </table> |
| 257 | db_finalize(&s); |
| 258 | style_footer(); |
| 259 | } |
| 260 | |
| 261 | /* |
| 262 | ** WEBPAGE: setup_ulist_notes |
| 263 | ** |
| 264 |