Fossil SCM
On the User List admin page, show the user's subscriptions and provide a like to the subscription page (if any).
Commit
8b287e8d97f03cc4018aec70e66c328b59adecd96c811021cec037facf70df91
Parent
2d1ef1e1f3c053e…
1 file changed
+26
-4
+26
-4
| --- src/setupuser.c | ||
| +++ src/setupuser.c | ||
| @@ -16,10 +16,13 @@ | ||
| 16 | 16 | ******************************************************************************* |
| 17 | 17 | ** |
| 18 | 18 | ** Setup pages associated with user management. The code in this |
| 19 | 19 | ** file was formerly part of the "setup.c" module, but has been broken |
| 20 | 20 | ** out into its own module to improve maintainability. |
| 21 | +** | |
| 22 | +** Note: Do not confuse "Users" with "Subscribers". Code to deal with | |
| 23 | +** subscribers is over in the "alerts.c" source file. | |
| 21 | 24 | */ |
| 22 | 25 | #include "config.h" |
| 23 | 26 | #include <assert.h> |
| 24 | 27 | #include "setupuser.h" |
| 25 | 28 | |
| @@ -109,13 +112,14 @@ | ||
| 109 | 112 | } |
| 110 | 113 | if( !bUnusedOnly ){ |
| 111 | 114 | style_submenu_element("Unused", "setup_ulist?unused"); |
| 112 | 115 | } |
| 113 | 116 | @ <table border=1 cellpadding=2 cellspacing=0 class='userTable sortable' \ |
| 114 | - @ data-column-types='ktxTTK' data-init-sort='2'> | |
| 117 | + @ data-column-types='ktxTTKt' data-init-sort='2'> | |
| 115 | 118 | @ <thead><tr> |
| 116 | - @ <th>Login Name<th>Caps<th>Info<th>Date<th>Expire<th>Last Login</tr></thead> | |
| 119 | + @ <th>Login Name<th>Caps<th>Info<th>Date<th>Expire<th>Last Login\ | |
| 120 | + @ <th>Alerts</tr></thead> | |
| 117 | 121 | @ <tbody> |
| 118 | 122 | db_multi_exec( |
| 119 | 123 | "CREATE TEMP TABLE lastAccess(uname TEXT PRIMARY KEY, atime REAL)" |
| 120 | 124 | "WITHOUT ROWID;" |
| 121 | 125 | ); |
| @@ -127,10 +131,16 @@ | ||
| 127 | 131 | " UNION ALL" |
| 128 | 132 | " SELECT login AS uname, rcvfrom.mtime AS mtime" |
| 129 | 133 | " FROM rcvfrom JOIN user USING(uid))" |
| 130 | 134 | " GROUP BY 1;" |
| 131 | 135 | ); |
| 136 | + } | |
| 137 | + if( !db_table_exists("repository","subscriber") ){ | |
| 138 | + db_multi_exec( | |
| 139 | + "CREATE TEMP TABLE subscriber(suname PRIMARY KEY, ssub, subscriberId)" | |
| 140 | + "WITHOUT ROWID;" | |
| 141 | + ); | |
| 132 | 142 | } |
| 133 | 143 | if( bUnusedOnly ){ |
| 134 | 144 | zWith = mprintf( |
| 135 | 145 | " AND login NOT IN (" |
| 136 | 146 | "SELECT user FROM event WHERE user NOT NULL " |
| @@ -142,17 +152,19 @@ | ||
| 142 | 152 | zWith = mprintf(" AND fullcap(cap) GLOB '*[%q]*'", zWith); |
| 143 | 153 | }else{ |
| 144 | 154 | zWith = ""; |
| 145 | 155 | } |
| 146 | 156 | db_prepare(&s, |
| 147 | - "SELECT uid, login, cap, info, date(mtime,'unixepoch')," | |
| 157 | + "SELECT uid, login, cap, info, date(user.mtime,'unixepoch')," | |
| 148 | 158 | " lower(login) AS sortkey, " |
| 149 | 159 | " CASE WHEN info LIKE '%%expires 20%%'" |
| 150 | 160 | " THEN substr(info,instr(lower(info),'expires')+8,10)" |
| 151 | 161 | " END AS exp," |
| 152 | - "atime" | |
| 162 | + "atime," | |
| 163 | + " subscriber.ssub, subscriber.subscriberId" | |
| 153 | 164 | " FROM user LEFT JOIN lastAccess ON login=uname" |
| 165 | + " LEFT JOIN subscriber ON login=suname" | |
| 154 | 166 | " WHERE login NOT IN ('anonymous','nobody','developer','reader') %s" |
| 155 | 167 | " ORDER BY sortkey", zWith/*safe-for-%s*/ |
| 156 | 168 | ); |
| 157 | 169 | rNow = db_double(0.0, "SELECT julianday('now');"); |
| 158 | 170 | while( db_step(&s)==SQLITE_ROW ){ |
| @@ -163,10 +175,12 @@ | ||
| 163 | 175 | const char *zDate = db_column_text(&s, 4); |
| 164 | 176 | const char *zSortKey = db_column_text(&s,5); |
| 165 | 177 | const char *zExp = db_column_text(&s,6); |
| 166 | 178 | double rATime = db_column_double(&s,7); |
| 167 | 179 | char *zAge = 0; |
| 180 | + const char *zSub; | |
| 181 | + int sid = db_column_int(&s,9); | |
| 168 | 182 | if( rATime>0.0 ){ |
| 169 | 183 | zAge = human_readable_age(rNow - rATime); |
| 170 | 184 | } |
| 171 | 185 | @ <tr> |
| 172 | 186 | @ <td data-sortkey='%h(zSortKey)'>\ |
| @@ -174,10 +188,18 @@ | ||
| 174 | 188 | @ <td>%h(zCap) |
| 175 | 189 | @ <td>%h(zInfo) |
| 176 | 190 | @ <td>%h(zDate?zDate:"") |
| 177 | 191 | @ <td>%h(zExp?zExp:"") |
| 178 | 192 | @ <td data-sortkey='%f(rATime)' style='white-space:nowrap'>%s(zAge?zAge:"") |
| 193 | + if( db_column_type(&s,8)==SQLITE_NULL ){ | |
| 194 | + @ <td> | |
| 195 | + }else if( (zSub = db_column_text(&s,8))==0 || zSub[0]==0 ){ | |
| 196 | + @ <td><a href="%R/alerts?sid=%d(sid)"><i>off</i></a> | |
| 197 | + }else{ | |
| 198 | + @ <td><a href="%R/alerts?sid=%d(sid)">%h(zSub)</a> | |
| 199 | + } | |
| 200 | + | |
| 179 | 201 | @ </tr> |
| 180 | 202 | fossil_free(zAge); |
| 181 | 203 | } |
| 182 | 204 | @ </tbody></table> |
| 183 | 205 | db_finalize(&s); |
| 184 | 206 |
| --- src/setupuser.c | |
| +++ src/setupuser.c | |
| @@ -16,10 +16,13 @@ | |
| 16 | ******************************************************************************* |
| 17 | ** |
| 18 | ** Setup pages associated with user management. The code in this |
| 19 | ** file was formerly part of the "setup.c" module, but has been broken |
| 20 | ** out into its own module to improve maintainability. |
| 21 | */ |
| 22 | #include "config.h" |
| 23 | #include <assert.h> |
| 24 | #include "setupuser.h" |
| 25 | |
| @@ -109,13 +112,14 @@ | |
| 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> |
| 118 | db_multi_exec( |
| 119 | "CREATE TEMP TABLE lastAccess(uname TEXT PRIMARY KEY, atime REAL)" |
| 120 | "WITHOUT ROWID;" |
| 121 | ); |
| @@ -127,10 +131,16 @@ | |
| 127 | " UNION ALL" |
| 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 " |
| @@ -142,17 +152,19 @@ | |
| 142 | zWith = mprintf(" AND fullcap(cap) GLOB '*[%q]*'", zWith); |
| 143 | }else{ |
| 144 | zWith = ""; |
| 145 | } |
| 146 | db_prepare(&s, |
| 147 | "SELECT uid, login, cap, info, date(mtime,'unixepoch')," |
| 148 | " lower(login) AS sortkey, " |
| 149 | " CASE WHEN info LIKE '%%expires 20%%'" |
| 150 | " THEN substr(info,instr(lower(info),'expires')+8,10)" |
| 151 | " END AS exp," |
| 152 | "atime" |
| 153 | " FROM user LEFT JOIN lastAccess ON login=uname" |
| 154 | " WHERE login NOT IN ('anonymous','nobody','developer','reader') %s" |
| 155 | " ORDER BY sortkey", zWith/*safe-for-%s*/ |
| 156 | ); |
| 157 | rNow = db_double(0.0, "SELECT julianday('now');"); |
| 158 | while( db_step(&s)==SQLITE_ROW ){ |
| @@ -163,10 +175,12 @@ | |
| 163 | const char *zDate = db_column_text(&s, 4); |
| 164 | const char *zSortKey = db_column_text(&s,5); |
| 165 | const char *zExp = db_column_text(&s,6); |
| 166 | double rATime = db_column_double(&s,7); |
| 167 | char *zAge = 0; |
| 168 | if( rATime>0.0 ){ |
| 169 | zAge = human_readable_age(rNow - rATime); |
| 170 | } |
| 171 | @ <tr> |
| 172 | @ <td data-sortkey='%h(zSortKey)'>\ |
| @@ -174,10 +188,18 @@ | |
| 174 | @ <td>%h(zCap) |
| 175 | @ <td>%h(zInfo) |
| 176 | @ <td>%h(zDate?zDate:"") |
| 177 | @ <td>%h(zExp?zExp:"") |
| 178 | @ <td data-sortkey='%f(rATime)' style='white-space:nowrap'>%s(zAge?zAge:"") |
| 179 | @ </tr> |
| 180 | fossil_free(zAge); |
| 181 | } |
| 182 | @ </tbody></table> |
| 183 | db_finalize(&s); |
| 184 |
| --- src/setupuser.c | |
| +++ src/setupuser.c | |
| @@ -16,10 +16,13 @@ | |
| 16 | ******************************************************************************* |
| 17 | ** |
| 18 | ** Setup pages associated with user management. The code in this |
| 19 | ** file was formerly part of the "setup.c" module, but has been broken |
| 20 | ** out into its own module to improve maintainability. |
| 21 | ** |
| 22 | ** Note: Do not confuse "Users" with "Subscribers". Code to deal with |
| 23 | ** subscribers is over in the "alerts.c" source file. |
| 24 | */ |
| 25 | #include "config.h" |
| 26 | #include <assert.h> |
| 27 | #include "setupuser.h" |
| 28 | |
| @@ -109,13 +112,14 @@ | |
| 112 | } |
| 113 | if( !bUnusedOnly ){ |
| 114 | style_submenu_element("Unused", "setup_ulist?unused"); |
| 115 | } |
| 116 | @ <table border=1 cellpadding=2 cellspacing=0 class='userTable sortable' \ |
| 117 | @ data-column-types='ktxTTKt' data-init-sort='2'> |
| 118 | @ <thead><tr> |
| 119 | @ <th>Login Name<th>Caps<th>Info<th>Date<th>Expire<th>Last Login\ |
| 120 | @ <th>Alerts</tr></thead> |
| 121 | @ <tbody> |
| 122 | db_multi_exec( |
| 123 | "CREATE TEMP TABLE lastAccess(uname TEXT PRIMARY KEY, atime REAL)" |
| 124 | "WITHOUT ROWID;" |
| 125 | ); |
| @@ -127,10 +131,16 @@ | |
| 131 | " UNION ALL" |
| 132 | " SELECT login AS uname, rcvfrom.mtime AS mtime" |
| 133 | " FROM rcvfrom JOIN user USING(uid))" |
| 134 | " GROUP BY 1;" |
| 135 | ); |
| 136 | } |
| 137 | if( !db_table_exists("repository","subscriber") ){ |
| 138 | db_multi_exec( |
| 139 | "CREATE TEMP TABLE subscriber(suname PRIMARY KEY, ssub, subscriberId)" |
| 140 | "WITHOUT ROWID;" |
| 141 | ); |
| 142 | } |
| 143 | if( bUnusedOnly ){ |
| 144 | zWith = mprintf( |
| 145 | " AND login NOT IN (" |
| 146 | "SELECT user FROM event WHERE user NOT NULL " |
| @@ -142,17 +152,19 @@ | |
| 152 | zWith = mprintf(" AND fullcap(cap) GLOB '*[%q]*'", zWith); |
| 153 | }else{ |
| 154 | zWith = ""; |
| 155 | } |
| 156 | db_prepare(&s, |
| 157 | "SELECT uid, login, cap, info, date(user.mtime,'unixepoch')," |
| 158 | " lower(login) AS sortkey, " |
| 159 | " CASE WHEN info LIKE '%%expires 20%%'" |
| 160 | " THEN substr(info,instr(lower(info),'expires')+8,10)" |
| 161 | " END AS exp," |
| 162 | "atime," |
| 163 | " subscriber.ssub, subscriber.subscriberId" |
| 164 | " FROM user LEFT JOIN lastAccess ON login=uname" |
| 165 | " LEFT JOIN subscriber ON login=suname" |
| 166 | " WHERE login NOT IN ('anonymous','nobody','developer','reader') %s" |
| 167 | " ORDER BY sortkey", zWith/*safe-for-%s*/ |
| 168 | ); |
| 169 | rNow = db_double(0.0, "SELECT julianday('now');"); |
| 170 | while( db_step(&s)==SQLITE_ROW ){ |
| @@ -163,10 +175,12 @@ | |
| 175 | const char *zDate = db_column_text(&s, 4); |
| 176 | const char *zSortKey = db_column_text(&s,5); |
| 177 | const char *zExp = db_column_text(&s,6); |
| 178 | double rATime = db_column_double(&s,7); |
| 179 | char *zAge = 0; |
| 180 | const char *zSub; |
| 181 | int sid = db_column_int(&s,9); |
| 182 | if( rATime>0.0 ){ |
| 183 | zAge = human_readable_age(rNow - rATime); |
| 184 | } |
| 185 | @ <tr> |
| 186 | @ <td data-sortkey='%h(zSortKey)'>\ |
| @@ -174,10 +188,18 @@ | |
| 188 | @ <td>%h(zCap) |
| 189 | @ <td>%h(zInfo) |
| 190 | @ <td>%h(zDate?zDate:"") |
| 191 | @ <td>%h(zExp?zExp:"") |
| 192 | @ <td data-sortkey='%f(rATime)' style='white-space:nowrap'>%s(zAge?zAge:"") |
| 193 | if( db_column_type(&s,8)==SQLITE_NULL ){ |
| 194 | @ <td> |
| 195 | }else if( (zSub = db_column_text(&s,8))==0 || zSub[0]==0 ){ |
| 196 | @ <td><a href="%R/alerts?sid=%d(sid)"><i>off</i></a> |
| 197 | }else{ |
| 198 | @ <td><a href="%R/alerts?sid=%d(sid)">%h(zSub)</a> |
| 199 | } |
| 200 | |
| 201 | @ </tr> |
| 202 | fossil_free(zAge); |
| 203 | } |
| 204 | @ </tbody></table> |
| 205 | db_finalize(&s); |
| 206 |