Fossil SCM

Allow login using either the username or the first email address found in the USER.INFO column. Note that it might be useful to create an index on user(find_emailaddr(info)) to make this efficient in the case where there are many rows in the user table.

drh 2018-08-10 16:44 trunk
Commit 8c91be8bf085e85f7755d3029ef03c8053d24239b86aac772c64ceccbb57c8f5
1 file changed +29 -11
+29 -11
--- src/login.c
+++ src/login.c
@@ -211,21 +211,39 @@
211211
** zPassword may be either the plain-text form or the encrypted
212212
** form of the user's password.
213213
*/
214214
int login_search_uid(const char *zUsername, const char *zPasswd){
215215
char *zSha1Pw = sha1_shared_secret(zPasswd, zUsername, 0);
216
- int const uid =
217
- db_int(0,
218
- "SELECT uid FROM user"
219
- " WHERE login=%Q"
220
- " AND length(cap)>0 AND length(pw)>0"
221
- " AND login NOT IN ('anonymous','nobody','developer','reader')"
222
- " AND (pw=%Q OR (length(pw)<>40 AND pw=%Q))"
223
- " AND (info NOT LIKE '%%expires 20%%'"
224
- " OR substr(info,instr(lower(info),'expires')+8,10)>datetime('now'))",
225
- zUsername, zSha1Pw, zPasswd
226
- );
216
+ int uid = db_int(0,
217
+ "SELECT uid FROM user"
218
+ " WHERE login=%Q"
219
+ " AND length(cap)>0 AND length(pw)>0"
220
+ " AND login NOT IN ('anonymous','nobody','developer','reader')"
221
+ " AND (pw=%Q OR (length(pw)<>40 AND pw=%Q))"
222
+ " AND (info NOT LIKE '%%expires 20%%'"
223
+ " OR substr(info,instr(lower(info),'expires')+8,10)>datetime('now'))",
224
+ zUsername, zSha1Pw, zPasswd
225
+ );
226
+
227
+ /* If we did not find a login on the first attempt, and the username
228
+ ** looks like an email address, the perhaps the user entired their
229
+ ** email address instead of their login. Try again to match the user
230
+ ** against email addresses contained in the "info" field.
231
+ */
232
+ if( uid==0 && strchr(zUsername,'@')!=0 ){
233
+ Stmt q;
234
+ db_prepare(&q,
235
+ "SELECT login FROM user"
236
+ " WHERE find_emailaddr(info)=%Q"
237
+ " AND instr(login,'@')==0",
238
+ zUsername
239
+ );
240
+ while( uid==0 && db_step(&q)==SQLITE_ROW ){
241
+ uid = login_search_uid(db_column_text(&q,0),zPasswd);
242
+ }
243
+ db_finalize(&q);
244
+ }
227245
free(zSha1Pw);
228246
return uid;
229247
}
230248
231249
/*
232250
--- src/login.c
+++ src/login.c
@@ -211,21 +211,39 @@
211 ** zPassword may be either the plain-text form or the encrypted
212 ** form of the user's password.
213 */
214 int login_search_uid(const char *zUsername, const char *zPasswd){
215 char *zSha1Pw = sha1_shared_secret(zPasswd, zUsername, 0);
216 int const uid =
217 db_int(0,
218 "SELECT uid FROM user"
219 " WHERE login=%Q"
220 " AND length(cap)>0 AND length(pw)>0"
221 " AND login NOT IN ('anonymous','nobody','developer','reader')"
222 " AND (pw=%Q OR (length(pw)<>40 AND pw=%Q))"
223 " AND (info NOT LIKE '%%expires 20%%'"
224 " OR substr(info,instr(lower(info),'expires')+8,10)>datetime('now'))",
225 zUsername, zSha1Pw, zPasswd
226 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
227 free(zSha1Pw);
228 return uid;
229 }
230
231 /*
232
--- src/login.c
+++ src/login.c
@@ -211,21 +211,39 @@
211 ** zPassword may be either the plain-text form or the encrypted
212 ** form of the user's password.
213 */
214 int login_search_uid(const char *zUsername, const char *zPasswd){
215 char *zSha1Pw = sha1_shared_secret(zPasswd, zUsername, 0);
216 int uid = db_int(0,
217 "SELECT uid FROM user"
218 " WHERE login=%Q"
219 " AND length(cap)>0 AND length(pw)>0"
220 " AND login NOT IN ('anonymous','nobody','developer','reader')"
221 " AND (pw=%Q OR (length(pw)<>40 AND pw=%Q))"
222 " AND (info NOT LIKE '%%expires 20%%'"
223 " OR substr(info,instr(lower(info),'expires')+8,10)>datetime('now'))",
224 zUsername, zSha1Pw, zPasswd
225 );
226
227 /* If we did not find a login on the first attempt, and the username
228 ** looks like an email address, the perhaps the user entired their
229 ** email address instead of their login. Try again to match the user
230 ** against email addresses contained in the "info" field.
231 */
232 if( uid==0 && strchr(zUsername,'@')!=0 ){
233 Stmt q;
234 db_prepare(&q,
235 "SELECT login FROM user"
236 " WHERE find_emailaddr(info)=%Q"
237 " AND instr(login,'@')==0",
238 zUsername
239 );
240 while( uid==0 && db_step(&q)==SQLITE_ROW ){
241 uid = login_search_uid(db_column_text(&q,0),zPasswd);
242 }
243 db_finalize(&q);
244 }
245 free(zSha1Pw);
246 return uid;
247 }
248
249 /*
250

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button