1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3 #include "common.h"
4
5 #include <sys/stat.h>
6 #include <dirent.h>
7
8 #include "utils.h"
9
10 #include "seafile-session.h"
11 #include "seafile-error.h"
12 #include "user-mgr.h"
13 #include "seaf-db.h"
14 #include "seaf-utils.h"
15
16 #include <openssl/sha.h>
17 #include <openssl/rand.h>
18 #include <openssl/evp.h>
19
20 #ifdef HAVE_LDAP
21 #ifndef WIN32
22 #define LDAP_DEPRECATED 1
23 #include <ldap.h>
24 #else
25 #include <winldap.h>
26 #include <winber.h>
27 #ifndef LDAP_OPT_SUCCESS
28 #define LDAP_OPT_SUCCESS LDAP_SUCCESS
29 #endif
30 #endif
31 #endif
32
33 #define DEBUG_FLAG CCNET_DEBUG_PEER
34 #include "log.h"
35
36 #define DEFAULT_SAVING_INTERVAL_MSEC 30000
37
38 #define DEFAULT_MAX_CONNECTIONS 100
39
40 G_DEFINE_TYPE (CcnetUserManager, ccnet_user_manager, G_TYPE_OBJECT);
41
42
43 #define GET_PRIV(o) \
44 (G_TYPE_INSTANCE_GET_PRIVATE ((o), CCNET_TYPE_USER_MANAGER, CcnetUserManagerPriv))
45
46
47 static int open_db (CcnetUserManager *manager);
48
49 #ifdef HAVE_LDAP
50 static int try_load_ldap_settings (CcnetUserManager *manager);
51 #endif
52
53 struct CcnetUserManagerPriv {
54 CcnetDB *db;
55 int max_users;
56 };
57
58 static void
ccnet_user_manager_class_init(CcnetUserManagerClass * klass)59 ccnet_user_manager_class_init (CcnetUserManagerClass *klass)
60 {
61
62 g_type_class_add_private (klass, sizeof (CcnetUserManagerPriv));
63 }
64
65 static void
ccnet_user_manager_init(CcnetUserManager * manager)66 ccnet_user_manager_init (CcnetUserManager *manager)
67 {
68 manager->priv = GET_PRIV(manager);
69 }
70
71 CcnetUserManager*
ccnet_user_manager_new(SeafileSession * session)72 ccnet_user_manager_new (SeafileSession *session)
73 {
74 CcnetUserManager* manager;
75
76 manager = g_object_new (CCNET_TYPE_USER_MANAGER, NULL);
77 manager->session = session;
78 manager->user_hash = g_hash_table_new (g_str_hash, g_str_equal);
79
80 return manager;
81 }
82
83 #define DEFAULT_PASSWD_HASH_ITER 10000
84
85 // return current active user number
86 static int
get_current_user_number(CcnetUserManager * manager)87 get_current_user_number (CcnetUserManager *manager)
88 {
89 int total = 0, count;
90
91 count = ccnet_user_manager_count_emailusers (manager, "DB");
92 if (count < 0) {
93 ccnet_warning ("Failed to get user number from DB.\n");
94 return -1;
95 }
96 total += count;
97
98 #ifdef HAVE_LDAP
99 if (manager->use_ldap) {
100 count = ccnet_user_manager_count_emailusers (manager, "LDAP");
101 if (count < 0) {
102 ccnet_warning ("Failed to get user number from LDAP.\n");
103 return -1;
104 }
105 total += count;
106 }
107 #endif
108
109 return total;
110 }
111
112 static gboolean
check_user_number(CcnetUserManager * manager,gboolean allow_equal)113 check_user_number (CcnetUserManager *manager, gboolean allow_equal)
114 {
115 if (manager->priv->max_users == 0) {
116 return TRUE;
117 }
118
119 int cur_num = get_current_user_number (manager);
120 if (cur_num < 0) {
121 return FALSE;
122 }
123
124 if ((allow_equal && cur_num > manager->priv->max_users) ||
125 (!allow_equal && cur_num >= manager->priv->max_users)) {
126 ccnet_warning ("The number of users exceeds limit, max %d, current %d\n",
127 manager->priv->max_users, cur_num);
128 return FALSE;
129 }
130
131 return TRUE;
132 }
133
134 int
ccnet_user_manager_prepare(CcnetUserManager * manager)135 ccnet_user_manager_prepare (CcnetUserManager *manager)
136 {
137 int ret;
138
139 #ifdef HAVE_LDAP
140 if (try_load_ldap_settings (manager) < 0)
141 return -1;
142 #endif
143
144 int iter = g_key_file_get_integer (manager->session->ccnet_config,
145 "USER", "PASSWORD_HASH_ITERATIONS",
146 NULL);
147 if (iter <= 0)
148 iter = DEFAULT_PASSWD_HASH_ITER;
149 manager->passwd_hash_iter = iter;
150
151 manager->userdb_path = g_build_filename (manager->session->ccnet_dir,
152 "user-db", NULL);
153 ret = open_db(manager);
154 if (ret < 0)
155 return ret;
156
157 if (!check_user_number (manager, TRUE)) {
158 return -1;
159 }
160
161 return 0;
162 }
163
164 void
ccnet_user_manager_free(CcnetUserManager * manager)165 ccnet_user_manager_free (CcnetUserManager *manager)
166 {
167 g_object_unref (manager);
168 }
169
170 void
ccnet_user_manager_start(CcnetUserManager * manager)171 ccnet_user_manager_start (CcnetUserManager *manager)
172 {
173
174 }
175
ccnet_user_manager_on_exit(CcnetUserManager * manager)176 void ccnet_user_manager_on_exit (CcnetUserManager *manager)
177 {
178 }
179
180 void
ccnet_user_manager_set_max_users(CcnetUserManager * manager,gint64 max_users)181 ccnet_user_manager_set_max_users (CcnetUserManager *manager, gint64 max_users)
182 {
183 manager->priv->max_users = max_users;
184 }
185
186 /* -------- LDAP related --------- */
187
188 #ifdef HAVE_LDAP
189
190
try_load_ldap_settings(CcnetUserManager * manager)191 static int try_load_ldap_settings (CcnetUserManager *manager)
192 {
193 GKeyFile *config = manager->session->ccnet_config;
194
195 manager->ldap_host = ccnet_key_file_get_string (config, "LDAP", "HOST");
196 if (!manager->ldap_host)
197 return 0;
198
199 manager->use_ldap = TRUE;
200
201 #ifdef WIN32
202 manager->use_ssl = g_key_file_get_boolean (config, "LDAP", "USE_SSL", NULL);
203 #endif
204
205 char *base_list = ccnet_key_file_get_string (config, "LDAP", "BASE");
206 if (!base_list) {
207 ccnet_warning ("LDAP: BASE not found in config file.\n");
208 return -1;
209 }
210 manager->base_list = g_strsplit (base_list, ";", -1);
211
212 manager->filter = ccnet_key_file_get_string (config, "LDAP", "FILTER");
213
214 manager->user_dn = ccnet_key_file_get_string (config, "LDAP", "USER_DN");
215 if (manager->user_dn) {
216 manager->password = ccnet_key_file_get_string (config, "LDAP", "PASSWORD");
217 if (!manager->password) {
218 ccnet_warning ("LDAP: PASSWORD not found in config file.\n");
219 return -1;
220 }
221 }
222 /* Use anonymous if user_dn is not set. */
223
224 manager->login_attr = ccnet_key_file_get_string (config, "LDAP", "LOGIN_ATTR");
225 if (!manager->login_attr)
226 manager->login_attr = g_strdup("mail");
227
228 GError *error = NULL;
229 manager->follow_referrals = g_key_file_get_boolean (config,
230 "LDAP", "FOLLOW_REFERRALS",
231 &error);
232 if (error) {
233 /* Default is follow referrals. */
234 g_clear_error (&error);
235 manager->follow_referrals = TRUE;
236 }
237
238 return 0;
239 }
240
ldap_init_and_bind(CcnetUserManager * manager,const char * host,gboolean use_ssl,const char * user_dn,const char * password)241 static LDAP *ldap_init_and_bind (CcnetUserManager *manager,
242 const char *host,
243 #ifdef WIN32
244 gboolean use_ssl,
245 #endif
246 const char *user_dn,
247 const char *password)
248 {
249 LDAP *ld;
250 int res;
251 int desired_version = LDAP_VERSION3;
252
253 #ifndef WIN32
254 res = ldap_initialize (&ld, host);
255 if (res != LDAP_SUCCESS) {
256 ccnet_warning ("ldap_initialize failed: %s.\n", ldap_err2string(res));
257 return NULL;
258 }
259 #else
260 char *host_copy = g_strdup (host);
261 if (!use_ssl)
262 ld = ldap_init (host_copy, LDAP_PORT);
263 else
264 ld = ldap_sslinit (host_copy, LDAP_SSL_PORT, 1);
265 g_free (host_copy);
266 if (!ld) {
267 ccnet_warning ("ldap_init failed: %ul.\n", LdapGetLastError());
268 return NULL;
269 }
270 #endif
271
272 /* set the LDAP version to be 3 */
273 res = ldap_set_option (ld, LDAP_OPT_PROTOCOL_VERSION, &desired_version);
274 if (res != LDAP_OPT_SUCCESS) {
275 ccnet_warning ("ldap_set_option failed: %s.\n", ldap_err2string(res));
276 return NULL;
277 }
278
279 res = ldap_set_option (ld, LDAP_OPT_REFERRALS,
280 manager->follow_referrals ? LDAP_OPT_ON : LDAP_OPT_OFF);
281 if (res != LDAP_OPT_SUCCESS) {
282 ccnet_warning ("ldap_set_option referrals failed: %s.\n",
283 ldap_err2string(res));
284 return NULL;
285 }
286
287 if (user_dn) {
288 #ifndef WIN32
289 res = ldap_bind_s (ld, user_dn, password, LDAP_AUTH_SIMPLE);
290 #else
291 char *dn_copy = g_strdup(user_dn);
292 char *password_copy = g_strdup(password);
293 res = ldap_bind_s (ld, dn_copy, password_copy, LDAP_AUTH_SIMPLE);
294 g_free (dn_copy);
295 g_free (password_copy);
296 #endif
297 if (res != LDAP_SUCCESS ) {
298 ccnet_warning ("ldap_bind failed for user %s: %s.\n",
299 user_dn, ldap_err2string(res));
300 ldap_unbind_s (ld);
301 return NULL;
302 }
303 }
304
305 return ld;
306 }
307
308 static gboolean
get_uid_cb(CcnetDBRow * row,void * data)309 get_uid_cb (CcnetDBRow *row, void *data)
310 {
311 int *id = data;
312 *id = seaf_db_row_get_column_int (row, 0);
313 return FALSE;
314 }
315
316 static int
add_ldapuser(CcnetDB * db,const char * email,const char * password,gboolean is_staff,gboolean is_active,const char * extra_attrs)317 add_ldapuser (CcnetDB *db,
318 const char *email,
319 const char *password,
320 gboolean is_staff,
321 gboolean is_active,
322 const char *extra_attrs)
323 {
324 int rc;
325 int uid = -1;
326
327 rc = seaf_db_statement_foreach_row (db,
328 "SELECT id FROM LDAPUsers WHERE email = ?",
329 get_uid_cb, &uid, 1, "string", email);
330
331 if (rc < 0) {
332 return rc;
333 }
334
335 if (rc == 1) {
336 return uid;
337 }
338
339 if (extra_attrs)
340 rc = seaf_db_statement_query (db,
341 "INSERT INTO LDAPUsers (email, password, is_staff, "
342 "is_active, extra_attrs) VALUES (?, ?, ?, ?, ?)",
343 5, "string", email, "string", password, "int",
344 is_staff, "int", is_active, "string", extra_attrs);
345 else
346 rc = seaf_db_statement_query (db,
347 "INSERT INTO LDAPUsers (email, password, is_staff, "
348 "is_active) VALUES (?, ?, ?, ?)", 4, "string", email,
349 "string", password, "int", is_staff, "int", is_active);
350 if (rc < 0) {
351 return rc;
352 }
353
354 seaf_db_statement_foreach_row (db,
355 "SELECT id FROM LDAPUsers WHERE email = ?",
356 get_uid_cb, &uid, 1, "string", email);
357
358 return uid;
359 }
360
ldap_verify_user_password(CcnetUserManager * manager,const char * uid,const char * password)361 static int ldap_verify_user_password (CcnetUserManager *manager,
362 const char *uid,
363 const char *password)
364 {
365 LDAP *ld = NULL;
366 int res;
367 GString *filter;
368 char *filter_str = NULL;
369 char *attrs[2];
370 LDAPMessage *msg = NULL, *entry;
371 char *dn = NULL;
372 int ret = 0;
373
374 /* First search for the DN with the given uid. */
375
376 ld = ldap_init_and_bind (manager,
377 manager->ldap_host,
378 #ifdef WIN32
379 manager->use_ssl,
380 #endif
381 manager->user_dn,
382 manager->password);
383 if (!ld) {
384 ccnet_warning ("Please check USER_DN and PASSWORD settings.\n");
385 return -1;
386 }
387
388 filter = g_string_new (NULL);
389 if (!manager->filter)
390 g_string_printf (filter, "(%s=%s)", manager->login_attr, uid);
391 else
392 g_string_printf (filter, "(&(%s=%s) (%s))",
393 manager->login_attr, uid, manager->filter);
394 filter_str = g_string_free (filter, FALSE);
395
396 attrs[0] = manager->login_attr;
397 attrs[1] = NULL;
398
399 char **base;
400 for (base = manager->base_list; *base; base++) {
401 res = ldap_search_s (ld, *base, LDAP_SCOPE_SUBTREE,
402 filter_str, attrs, 0, &msg);
403 if (res != LDAP_SUCCESS) {
404 ccnet_warning ("ldap_search user '%s=%s' failed for base %s: %s.\n",
405 manager->login_attr, uid, *base, ldap_err2string(res));
406 ccnet_warning ("Please check BASE setting in ccnet.conf.\n");
407 ret = -1;
408 ldap_msgfree (msg);
409 goto out;
410 }
411
412 entry = ldap_first_entry (ld, msg);
413 if (entry) {
414 dn = ldap_get_dn (ld, entry);
415 ldap_msgfree (msg);
416 break;
417 }
418
419 ldap_msgfree (msg);
420 }
421
422 if (!dn) {
423 ccnet_debug ("Cannot find user %s in LDAP.\n", uid);
424 ret = -1;
425 goto out;
426 }
427
428 /* Then bind the DN with password. */
429
430 ldap_unbind_s (ld);
431
432 ld = ldap_init_and_bind (manager,
433 manager->ldap_host,
434 #ifdef WIN32
435 manager->use_ssl,
436 #endif
437 dn, password);
438 if (!ld) {
439 ccnet_debug ("Password incorrect for %s in LDAP.\n", uid);
440 ret = -1;
441 }
442
443 out:
444 ldap_memfree (dn);
445 g_free (filter_str);
446 if (ld) ldap_unbind_s (ld);
447 return ret;
448 }
449
450 /*
451 * @uid: user's uid, list all users if * is passed in.
452 */
ldap_list_users(CcnetUserManager * manager,const char * uid,int start,int limit)453 static GList *ldap_list_users (CcnetUserManager *manager, const char *uid,
454 int start, int limit)
455 {
456 LDAP *ld = NULL;
457 GList *ret = NULL;
458 int res;
459 GString *filter;
460 char *filter_str;
461 char *attrs[2];
462 LDAPMessage *msg = NULL, *entry;
463
464 ld = ldap_init_and_bind (manager,
465 manager->ldap_host,
466 #ifdef WIN32
467 manager->use_ssl,
468 #endif
469 manager->user_dn,
470 manager->password);
471 if (!ld) {
472 ccnet_warning ("Please check USER_DN and PASSWORD settings.\n");
473 return NULL;
474 }
475
476 filter = g_string_new (NULL);
477 if (!manager->filter)
478 g_string_printf (filter, "(%s=%s)", manager->login_attr, uid);
479 else
480 g_string_printf (filter, "(&(%s=%s) (%s))",
481 manager->login_attr, uid, manager->filter);
482 filter_str = g_string_free (filter, FALSE);
483
484 attrs[0] = manager->login_attr;
485 attrs[1] = NULL;
486
487 int i = 0;
488 if (start == -1)
489 start = 0;
490
491 char **base;
492 for (base = manager->base_list; *base; ++base) {
493 res = ldap_search_s (ld, *base, LDAP_SCOPE_SUBTREE,
494 filter_str, attrs, 0, &msg);
495 if (res != LDAP_SUCCESS) {
496 ccnet_warning ("ldap_search user '%s=%s' failed for base %s: %s.\n",
497 manager->login_attr, uid, *base, ldap_err2string(res));
498 ccnet_warning ("Please check BASE setting in ccnet.conf.\n");
499 ret = NULL;
500 ldap_msgfree (msg);
501 goto out;
502 }
503
504 for (entry = ldap_first_entry (ld, msg);
505 entry != NULL;
506 entry = ldap_next_entry (ld, entry), ++i) {
507 char *attr;
508 char **vals;
509 BerElement *ber;
510 CcnetEmailUser *user;
511
512 if (i < start)
513 continue;
514 if (limit >= 0 && i >= start + limit) {
515 ldap_msgfree (msg);
516 goto out;
517 }
518
519 attr = ldap_first_attribute (ld, entry, &ber);
520 vals = ldap_get_values (ld, entry, attr);
521
522 char *email_l = g_ascii_strdown (vals[0], -1);
523 user = g_object_new (CCNET_TYPE_EMAIL_USER,
524 "id", 0,
525 "email", email_l,
526 "is_staff", FALSE,
527 "is_active", TRUE,
528 "ctime", (gint64)0,
529 "source", "LDAP",
530 "password", "!",
531 NULL);
532 g_free (email_l);
533 ret = g_list_prepend (ret, user);
534
535 ldap_memfree (attr);
536 ldap_value_free (vals);
537 ber_free (ber, 0);
538 }
539
540 ldap_msgfree (msg);
541 }
542
543 out:
544 g_free (filter_str);
545 if (ld) ldap_unbind_s (ld);
546 return ret;
547 }
548
549 #endif /* HAVE_LDAP */
550
551 /* -------- DB Operations -------- */
552
check_db_table(SeafDB * db)553 static int check_db_table (SeafDB *db)
554 {
555 char *sql;
556
557 int db_type = seaf_db_type (db);
558 if (db_type == SEAF_DB_TYPE_MYSQL) {
559 sql = "CREATE TABLE IF NOT EXISTS EmailUser ("
560 "id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT, "
561 "email VARCHAR(255), passwd VARCHAR(256), "
562 "is_staff BOOL NOT NULL, is_active BOOL NOT NULL, "
563 "ctime BIGINT, reference_id VARCHAR(255),"
564 "UNIQUE INDEX (email), UNIQUE INDEX (reference_id))"
565 "ENGINE=INNODB";
566 if (seaf_db_query (db, sql) < 0)
567 return -1;
568 sql = "CREATE TABLE IF NOT EXISTS Binding (id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT, "
569 "email VARCHAR(255), peer_id CHAR(41),"
570 "UNIQUE INDEX (peer_id), INDEX (email(20)))"
571 "ENGINE=INNODB";
572 if (seaf_db_query (db, sql) < 0)
573 return -1;
574
575 sql = "CREATE TABLE IF NOT EXISTS UserRole ("
576 "id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT, "
577 "email VARCHAR(255), role VARCHAR(255), UNIQUE INDEX (email)) "
578 "ENGINE=INNODB";
579 if (seaf_db_query (db, sql) < 0)
580 return -1;
581
582 sql = "CREATE TABLE IF NOT EXISTS LDAPUsers ("
583 "id BIGINT PRIMARY KEY AUTO_INCREMENT, "
584 "email VARCHAR(255) NOT NULL, password varchar(255) NOT NULL, "
585 "is_staff BOOL NOT NULL, is_active BOOL NOT NULL, extra_attrs TEXT, "
586 "reference_id VARCHAR(255), "
587 "UNIQUE INDEX(email), UNIQUE INDEX (reference_id)) ENGINE=INNODB";
588 if (seaf_db_query (db, sql) < 0)
589 return -1;
590
591 sql = "CREATE TABLE IF NOT EXISTS LDAPConfig ( "
592 "id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT, cfg_group VARCHAR(255) NOT NULL,"
593 "cfg_key VARCHAR(255) NOT NULL, value VARCHAR(255), property INTEGER) ENGINE=INNODB";
594 if (seaf_db_query (db, sql) < 0)
595 return -1;
596
597 } else if (db_type == SEAF_DB_TYPE_SQLITE) {
598 sql = "CREATE TABLE IF NOT EXISTS EmailUser ("
599 "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
600 "email TEXT, passwd TEXT, is_staff bool NOT NULL, "
601 "is_active bool NOT NULL, ctime INTEGER, "
602 "reference_id TEXT)";
603 if (seaf_db_query (db, sql) < 0)
604 return -1;
605
606 sql = "CREATE UNIQUE INDEX IF NOT EXISTS email_index on EmailUser (email)";
607 if (seaf_db_query (db, sql) < 0)
608 return -1;
609
610 sql = "CREATE UNIQUE INDEX IF NOT EXISTS reference_id_index on EmailUser (reference_id)";
611 if (seaf_db_query (db, sql) < 0)
612 return -1;
613
614 sql = "CREATE TABLE IF NOT EXISTS Binding (email TEXT, peer_id TEXT)";
615 if (seaf_db_query (db, sql) < 0)
616 return -1;
617
618 sql = "CREATE INDEX IF NOT EXISTS email_index on Binding (email)";
619 if (seaf_db_query (db, sql) < 0)
620 return -1;
621
622 sql = "CREATE UNIQUE INDEX IF NOT EXISTS peer_index on Binding (peer_id)";
623 if (seaf_db_query (db, sql) < 0)
624 return -1;
625
626 sql = "CREATE TABLE IF NOT EXISTS UserRole (email TEXT, role TEXT)";
627 if (seaf_db_query (db, sql) < 0)
628 return -1;
629
630 sql = "CREATE INDEX IF NOT EXISTS userrole_email_index on UserRole (email)";
631 if (seaf_db_query (db, sql) < 0)
632 return -1;
633
634 sql = "CREATE UNIQUE INDEX IF NOT EXISTS userrole_userrole_index on UserRole (email, role)";
635 if (seaf_db_query (db, sql) < 0)
636 return -1;
637
638 sql = "CREATE TABLE IF NOT EXISTS LDAPUsers ("
639 "id INTEGER PRIMARY KEY AUTOINCREMENT, "
640 "email TEXT NOT NULL, password TEXT NOT NULL, "
641 "is_staff BOOL NOT NULL, is_active BOOL NOT NULL, extra_attrs TEXT, "
642 "reference_id TEXT)";
643 if (seaf_db_query (db, sql) < 0)
644 return -1;
645
646 sql = "CREATE UNIQUE INDEX IF NOT EXISTS ldapusers_email_index on LDAPUsers(email)";
647 if (seaf_db_query (db, sql) < 0)
648 return -1;
649
650 sql = "CREATE UNIQUE INDEX IF NOT EXISTS ldapusers_reference_id_index on LDAPUsers(reference_id)";
651 if (seaf_db_query (db, sql) < 0)
652 return -1;
653
654 sql = "CREATE TABLE IF NOT EXISTS LDAPConfig (cfg_group VARCHAR(255) NOT NULL,"
655 "cfg_key VARCHAR(255) NOT NULL, value VARCHAR(255), property INTEGER)";
656 if (seaf_db_query (db, sql) < 0)
657 return -1;
658
659 } else if (db_type == SEAF_DB_TYPE_PGSQL) {
660 sql = "CREATE TABLE IF NOT EXISTS EmailUser ("
661 "id SERIAL PRIMARY KEY, "
662 "email VARCHAR(255), passwd VARCHAR(256), "
663 "is_staff INTEGER NOT NULL, is_active INTEGER NOT NULL, "
664 "ctime BIGINT, reference_id VARCHAR(255), UNIQUE (email))";
665 if (seaf_db_query (db, sql) < 0)
666 return -1;
667
668 //if (!pgsql_index_exists (db, "emailuser_reference_id_idx")) {
669 // sql = "CREATE UNIQUE INDEX emailuser_reference_id_idx ON EmailUser (reference_id)";
670 // if (seaf_db_query (db, sql) < 0)
671 // return -1;
672 //}
673
674 sql = "CREATE TABLE IF NOT EXISTS Binding (email VARCHAR(255), peer_id CHAR(41),"
675 "UNIQUE (peer_id))";
676 if (seaf_db_query (db, sql) < 0)
677 return -1;
678
679 sql = "CREATE TABLE IF NOT EXISTS UserRole (email VARCHAR(255), "
680 " role VARCHAR(255), UNIQUE (email, role))";
681 if (seaf_db_query (db, sql) < 0)
682 return -1;
683
684 //if (!pgsql_index_exists (db, "userrole_email_idx")) {
685 // sql = "CREATE INDEX userrole_email_idx ON UserRole (email)";
686 // if (seaf_db_query (db, sql) < 0)
687 // return -1;
688 //}
689
690 sql = "CREATE TABLE IF NOT EXISTS LDAPUsers ("
691 "id SERIAL PRIMARY KEY, "
692 "email VARCHAR(255) NOT NULL, password VARCHAR(255) NOT NULL, "
693 "is_staff SMALLINT NOT NULL, is_active SMALLINT NOT NULL, extra_attrs TEXT,"
694 "reference_id VARCHAR(255))";
695 if (seaf_db_query (db, sql) < 0)
696 return -1;
697
698 //if (!pgsql_index_exists (db, "ldapusers_email_idx")) {
699 // sql = "CREATE UNIQUE INDEX ldapusers_email_idx ON LDAPUsers (email)";
700 // if (seaf_db_query (db, sql) < 0)
701 // return -1;
702 //}
703
704 //if (!pgsql_index_exists (db, "ldapusers_reference_id_idx")) {
705 // sql = "CREATE UNIQUE INDEX ldapusers_reference_id_idx ON LDAPUsers (reference_id)";
706 // if (seaf_db_query (db, sql) < 0)
707 // return -1;
708 //}
709
710 sql = "CREATE TABLE IF NOT EXISTS LDAPConfig (cfg_group VARCHAR(255) NOT NULL,"
711 "cfg_key VARCHAR(255) NOT NULL, value VARCHAR(255), property INTEGER)";
712 if (seaf_db_query (db, sql) < 0)
713 return -1;
714 }
715
716 return 0;
717 }
718
719
720 static CcnetDB *
open_sqlite_db(CcnetUserManager * manager)721 open_sqlite_db (CcnetUserManager *manager)
722 {
723 CcnetDB *db = NULL;
724 char *db_dir;
725 char *db_path;
726
727 db_dir = g_build_filename (manager->session->ccnet_dir, "PeerMgr", NULL);
728 if (checkdir_with_mkdir(db_dir) < 0) {
729 ccnet_error ("Cannot open db dir %s: %s\n", db_dir,
730 strerror(errno));
731 return NULL;
732 }
733 g_free (db_dir);
734
735 db_path = g_build_filename (manager->session->ccnet_dir, "PeerMgr",
736 "usermgr.db", NULL);
737 db = seaf_db_new_sqlite (db_path, DEFAULT_MAX_CONNECTIONS);
738 g_free (db_path);
739
740 return db;
741 }
742
743 static int
open_db(CcnetUserManager * manager)744 open_db (CcnetUserManager *manager)
745 {
746 CcnetDB *db = NULL;
747
748 switch (seaf_db_type(manager->session->ccnet_db)) {
749 /* To be compatible with the db file layout of 0.9.1 version,
750 * we don't use conf-dir/ccnet.db for user and peer info, but
751 * user conf-dir/PeerMgr/peermgr.db and conf-dir/PeerMgr/usermgr.db instead.
752 */
753 case SEAF_DB_TYPE_SQLITE:
754 db = open_sqlite_db (manager);
755 break;
756 case SEAF_DB_TYPE_PGSQL:
757 case SEAF_DB_TYPE_MYSQL:
758 db = manager->session->ccnet_db;
759 break;
760 }
761
762 if (!db)
763 return -1;
764
765 manager->priv->db = db;
766 if ((manager->session->ccnet_create_tables || seaf_db_type(db) == SEAF_DB_TYPE_PGSQL)
767 && check_db_table (db) < 0) {
768 ccnet_warning ("Failed to create user db tables.\n");
769 return -1;
770 }
771 return 0;
772 }
773
774
775 /* -------- EmailUser Management -------- */
776
777 /* This fixed salt is used in very early versions. It's kept for compatibility.
778 * For the current password hashing algorithm, please see hash_password_pbkdf2_sha256()
779 */
780 static unsigned char salt[8] = { 0xdb, 0x91, 0x45, 0xc3, 0x06, 0xc7, 0xcc, 0x26 };
781
782 static void
hash_password(const char * passwd,char * hashed_passwd)783 hash_password (const char *passwd, char *hashed_passwd)
784 {
785 unsigned char sha1[20];
786 SHA_CTX s;
787
788 SHA1_Init (&s);
789 SHA1_Update (&s, passwd, strlen(passwd));
790 SHA1_Final (sha1, &s);
791 rawdata_to_hex (sha1, hashed_passwd, 20);
792 }
793
794 static void
hash_password_salted(const char * passwd,char * hashed_passwd)795 hash_password_salted (const char *passwd, char *hashed_passwd)
796 {
797 unsigned char sha[SHA256_DIGEST_LENGTH];
798 SHA256_CTX s;
799
800 SHA256_Init (&s);
801 SHA256_Update (&s, passwd, strlen(passwd));
802 SHA256_Update (&s, salt, sizeof(salt));
803 SHA256_Final (sha, &s);
804 rawdata_to_hex (sha, hashed_passwd, SHA256_DIGEST_LENGTH);
805 }
806
807 static void
hash_password_pbkdf2_sha256(const char * passwd,int iterations,char ** db_passwd)808 hash_password_pbkdf2_sha256 (const char *passwd,
809 int iterations,
810 char **db_passwd)
811 {
812 guint8 sha[SHA256_DIGEST_LENGTH];
813 guint8 salt[SHA256_DIGEST_LENGTH];
814 char hashed_passwd[SHA256_DIGEST_LENGTH*2+1];
815 char salt_str[SHA256_DIGEST_LENGTH*2+1];
816
817 if (!RAND_bytes (salt, sizeof(salt))) {
818 ccnet_warning ("Failed to generate salt "
819 "with RAND_bytes(), use RAND_pseudo_bytes().\n");
820 RAND_pseudo_bytes (salt, sizeof(salt));
821 }
822
823 PKCS5_PBKDF2_HMAC (passwd, strlen(passwd),
824 salt, sizeof(salt),
825 iterations,
826 EVP_sha256(),
827 sizeof(sha), sha);
828
829 rawdata_to_hex (sha, hashed_passwd, SHA256_DIGEST_LENGTH);
830
831 rawdata_to_hex (salt, salt_str, SHA256_DIGEST_LENGTH);
832
833 /* Encode password hash related information into one string, similar to Django. */
834 GString *buf = g_string_new (NULL);
835 g_string_printf (buf, "PBKDF2SHA256$%d$%s$%s",
836 iterations, salt_str, hashed_passwd);
837 *db_passwd = g_string_free (buf, FALSE);
838 }
839
840 static gboolean
validate_passwd_pbkdf2_sha256(const char * passwd,const char * db_passwd)841 validate_passwd_pbkdf2_sha256 (const char *passwd, const char *db_passwd)
842 {
843 char **tokens;
844 char *salt_str, *hash;
845 int iter;
846 guint8 sha[SHA256_DIGEST_LENGTH];
847 guint8 salt[SHA256_DIGEST_LENGTH];
848 char hashed_passwd[SHA256_DIGEST_LENGTH*2+1];
849
850 tokens = g_strsplit (db_passwd, "$", -1);
851 if (!tokens || g_strv_length (tokens) != 4) {
852 ccnet_warning ("Invalide db passwd format %s.\n", db_passwd);
853 return FALSE;
854 }
855
856 iter = atoi (tokens[1]);
857 salt_str = tokens[2];
858 hash = tokens[3];
859
860 hex_to_rawdata (salt_str, salt, SHA256_DIGEST_LENGTH);
861
862 PKCS5_PBKDF2_HMAC (passwd, strlen(passwd),
863 salt, sizeof(salt),
864 iter,
865 EVP_sha256(),
866 sizeof(sha), sha);
867 rawdata_to_hex (sha, hashed_passwd, SHA256_DIGEST_LENGTH);
868
869 gboolean ret = (strcmp (hash, hashed_passwd) == 0);
870
871 g_strfreev (tokens);
872 return ret;
873 }
874
875 static gboolean
validate_passwd(const char * passwd,const char * stored_passwd,gboolean * need_upgrade)876 validate_passwd (const char *passwd, const char *stored_passwd,
877 gboolean *need_upgrade)
878 {
879 char hashed_passwd[SHA256_DIGEST_LENGTH * 2 + 1];
880 int hash_len = strlen(stored_passwd);
881
882 *need_upgrade = FALSE;
883
884 if (hash_len == SHA256_DIGEST_LENGTH * 2) {
885 hash_password_salted (passwd, hashed_passwd);
886 *need_upgrade = TRUE;
887 } else if (hash_len == SHA_DIGEST_LENGTH * 2) {
888 hash_password (passwd, hashed_passwd);
889 *need_upgrade = TRUE;
890 } else {
891 return validate_passwd_pbkdf2_sha256 (passwd, stored_passwd);
892 }
893
894 if (strcmp (hashed_passwd, stored_passwd) == 0)
895 return TRUE;
896 else
897 return FALSE;
898 }
899
900 static int
update_user_passwd(CcnetUserManager * manager,const char * email,const char * passwd)901 update_user_passwd (CcnetUserManager *manager,
902 const char *email, const char *passwd)
903 {
904 CcnetDB *db = manager->priv->db;
905 char *db_passwd = NULL;
906 int ret;
907
908 hash_password_pbkdf2_sha256 (passwd, manager->passwd_hash_iter,
909 &db_passwd);
910
911 /* convert email to lower case for case insensitive lookup. */
912 char *email_down = g_ascii_strdown (email, strlen(email));
913
914 ret = seaf_db_statement_query (db,
915 "UPDATE EmailUser SET passwd=? WHERE email=?",
916 2, "string", db_passwd, "string", email_down);
917
918 g_free (db_passwd);
919 g_free (email_down);
920
921 if (ret < 0)
922 return ret;
923
924 return 0;
925 }
926
927 int
ccnet_user_manager_add_emailuser(CcnetUserManager * manager,const char * email,const char * passwd,int is_staff,int is_active)928 ccnet_user_manager_add_emailuser (CcnetUserManager *manager,
929 const char *email,
930 const char *passwd,
931 int is_staff, int is_active)
932 {
933 CcnetDB *db = manager->priv->db;
934 gint64 now = get_current_time();
935 char *db_passwd = NULL;
936 int ret;
937
938 if (!check_user_number (manager, FALSE)) {
939 return -1;
940 }
941
942 /* A user with unhashed "!" as password cannot be logged in.
943 * Such users are created for book keeping, such as users from
944 * Shibboleth.
945 */
946 if (g_strcmp0 (passwd, "!") != 0)
947 hash_password_pbkdf2_sha256 (passwd, manager->passwd_hash_iter,
948 &db_passwd);
949 else
950 db_passwd = g_strdup(passwd);
951
952 /* convert email to lower case for case insensitive lookup. */
953 char *email_down = g_ascii_strdown (email, strlen(email));
954
955 ret = seaf_db_statement_query (db,
956 "INSERT INTO EmailUser(email, passwd, is_staff, "
957 "is_active, ctime) VALUES (?, ?, ?, ?, ?)",
958 5, "string", email_down, "string", db_passwd,
959 "int", is_staff, "int", is_active, "int64", now);
960
961 g_free (db_passwd);
962 g_free (email_down);
963
964 if (ret < 0)
965 return ret;
966
967 return 0;
968 }
969
970 int
ccnet_user_manager_remove_emailuser(CcnetUserManager * manager,const char * source,const char * email)971 ccnet_user_manager_remove_emailuser (CcnetUserManager *manager,
972 const char *source,
973 const char *email)
974 {
975 CcnetDB *db = manager->priv->db;
976 int ret;
977
978 seaf_db_statement_query (db,
979 "DELETE FROM UserRole WHERE email=?",
980 1, "string", email);
981
982 if (strcmp (source, "DB") == 0) {
983 ret = seaf_db_statement_query (db,
984 "DELETE FROM EmailUser WHERE email=?",
985 1, "string", email);
986 return ret;
987 }
988
989 #ifdef HAVE_LDAP
990 if (strcmp (source, "LDAP") == 0 && manager->use_ldap) {
991 ret = seaf_db_statement_query (db,
992 "DELETE FROM LDAPUsers WHERE email=?",
993 1, "string", email);
994 return ret;
995 }
996 #endif
997
998 return -1;
999 }
1000
1001 static gboolean
get_password(CcnetDBRow * row,void * data)1002 get_password (CcnetDBRow *row, void *data)
1003 {
1004 char **p_passwd = data;
1005
1006 *p_passwd = g_strdup(seaf_db_row_get_column_text (row, 0));
1007 return FALSE;
1008 }
1009
1010 int
ccnet_user_manager_validate_emailuser(CcnetUserManager * manager,const char * email,const char * passwd)1011 ccnet_user_manager_validate_emailuser (CcnetUserManager *manager,
1012 const char *email,
1013 const char *passwd)
1014 {
1015 CcnetDB *db = manager->priv->db;
1016 int ret = -1;
1017 char *sql;
1018 char *email_down;
1019 char *login_id;
1020 char *stored_passwd = NULL;
1021 gboolean need_upgrade = FALSE;
1022
1023 /* Users with password "!" are for internal book keeping only. */
1024 if (g_strcmp0 (passwd, "!") == 0)
1025 return -1;
1026
1027 login_id = ccnet_user_manager_get_login_id (manager, email);
1028 if (!login_id) {
1029 ccnet_warning ("Failed to get login_id for %s\n", email);
1030 return -1;
1031 }
1032
1033 #ifdef HAVE_LDAP
1034 if (manager->use_ldap) {
1035 if (ldap_verify_user_password (manager, login_id, passwd) == 0) {
1036 ret = 0;
1037 goto out;
1038 }
1039 }
1040 #endif
1041
1042 sql = "SELECT passwd FROM EmailUser WHERE email=?";
1043 if (seaf_db_statement_foreach_row (db, sql,
1044 get_password, &stored_passwd,
1045 1, "string", login_id) > 0) {
1046 if (validate_passwd (passwd, stored_passwd, &need_upgrade)) {
1047 if (need_upgrade)
1048 update_user_passwd (manager, login_id, passwd);
1049 ret = 0;
1050 goto out;
1051 } else {
1052 goto out;
1053 }
1054 }
1055
1056 email_down = g_ascii_strdown (email, strlen(login_id));
1057 if (seaf_db_statement_foreach_row (db, sql,
1058 get_password, &stored_passwd,
1059 1, "string", email_down) > 0) {
1060 g_free (email_down);
1061 if (validate_passwd (passwd, stored_passwd, &need_upgrade)) {
1062 if (need_upgrade)
1063 update_user_passwd (manager, login_id, passwd);
1064 ret = 0;
1065 goto out;
1066 } else {
1067 goto out;
1068 }
1069 }
1070 g_free (email_down);
1071
1072 out:
1073
1074 g_free (login_id);
1075 g_free (stored_passwd);
1076
1077 return ret;
1078 }
1079
1080 static gboolean
get_emailuser_cb(CcnetDBRow * row,void * data)1081 get_emailuser_cb (CcnetDBRow *row, void *data)
1082 {
1083 CcnetEmailUser **p_emailuser = data;
1084
1085 int id = seaf_db_row_get_column_int (row, 0);
1086 const char *email = (const char *)seaf_db_row_get_column_text (row, 1);
1087 int is_staff = seaf_db_row_get_column_int (row, 2);
1088 int is_active = seaf_db_row_get_column_int (row, 3);
1089 gint64 ctime = seaf_db_row_get_column_int64 (row, 4);
1090 const char *password = seaf_db_row_get_column_text (row, 5);
1091 const char *reference_id = seaf_db_row_get_column_text (row, 6);
1092 const char *role = seaf_db_row_get_column_text (row, 7);
1093
1094 char *email_l = g_ascii_strdown (email, -1);
1095 *p_emailuser = g_object_new (CCNET_TYPE_EMAIL_USER,
1096 "id", id,
1097 "email", email_l,
1098 "is_staff", is_staff,
1099 "is_active", is_active,
1100 "ctime", ctime,
1101 "source", "DB",
1102 "password", password,
1103 "reference_id", reference_id,
1104 "role", role ? role : "",
1105 NULL);
1106 g_free (email_l);
1107
1108 return FALSE;
1109 }
1110
1111 static char*
1112 ccnet_user_manager_get_role_emailuser (CcnetUserManager *manager,
1113 const char* email);
1114
1115 static gboolean
get_ldap_emailuser_cb(CcnetDBRow * row,void * data)1116 get_ldap_emailuser_cb (CcnetDBRow *row, void *data)
1117 {
1118 CcnetEmailUser **p_emailuser = data;
1119
1120 int id = seaf_db_row_get_column_int (row, 0);
1121 const char *email = (const char *)seaf_db_row_get_column_text (row, 1);
1122 int is_staff = seaf_db_row_get_column_int (row, 2);
1123 int is_active = seaf_db_row_get_column_int (row, 3);
1124 const char *reference_id = seaf_db_row_get_column_text (row, 4);
1125 const char *role = seaf_db_row_get_column_text (row, 5);
1126
1127 *p_emailuser = g_object_new (CCNET_TYPE_EMAIL_USER,
1128 "id", id,
1129 "email", email,
1130 "is_staff", is_staff,
1131 "is_active", is_active,
1132 "ctime", (gint64)0,
1133 "source", "LDAPImport",
1134 "password", "!",
1135 "reference_id", reference_id,
1136 "role", role ? role : "",
1137 NULL);
1138
1139 return FALSE;
1140 }
1141
1142 static CcnetEmailUser*
get_emailuser(CcnetUserManager * manager,const char * email,gboolean import)1143 get_emailuser (CcnetUserManager *manager,
1144 const char *email,
1145 gboolean import)
1146 {
1147 CcnetDB *db = manager->priv->db;
1148 char *sql;
1149 CcnetEmailUser *emailuser = NULL;
1150 char *email_down;
1151
1152 sql = "SELECT e.id, e.email, is_staff, is_active, ctime, passwd, reference_id, role "
1153 " FROM EmailUser e LEFT JOIN UserRole ON e.email = UserRole.email "
1154 " WHERE e.email=?";
1155 if (seaf_db_statement_foreach_row (db, sql, get_emailuser_cb, &emailuser,
1156 1, "string", email) > 0) {
1157 return emailuser;
1158 }
1159
1160 email_down = g_ascii_strdown (email, strlen(email));
1161 if (seaf_db_statement_foreach_row (db, sql, get_emailuser_cb, &emailuser,
1162 1, "string", email_down) > 0) {
1163 g_free (email_down);
1164 return emailuser;
1165 }
1166
1167 #ifdef HAVE_LDAP
1168 if (manager->use_ldap) {
1169 int ret = seaf_db_statement_foreach_row (db,
1170 "SELECT l.id, l.email, is_staff, is_active, "
1171 "reference_id, role "
1172 "FROM LDAPUsers l LEFT JOIN UserRole ON "
1173 "l.email = UserRole.email WHERE l.email = ?",
1174 get_ldap_emailuser_cb,
1175 &emailuser, 1, "string", email_down);
1176 if (ret < 0) {
1177 ccnet_warning ("get ldapuser from db failed.\n");
1178 g_free (email_down);
1179 return NULL;
1180 }
1181
1182 if (!emailuser) {
1183 GList *users, *ptr;
1184
1185 users = ldap_list_users (manager, email, -1, -1);
1186 if (!users) {
1187 /* Only print warning if this function is called in login. */
1188 if (import)
1189 ccnet_warning ("Cannot find user %s in LDAP.\n", email);
1190 g_free (email_down);
1191 return NULL;
1192 }
1193 emailuser = users->data;
1194
1195 /* Free all except the first user. */
1196 for (ptr = users->next; ptr; ptr = ptr->next)
1197 g_object_unref (ptr->data);
1198 g_list_free (users);
1199
1200 if (import) {
1201 if (!check_user_number (manager, FALSE)) {
1202 g_free (email_down);
1203 g_object_unref (emailuser);
1204 return NULL;
1205 }
1206
1207 // add user to LDAPUsers
1208 ret = add_ldapuser (manager->priv->db, email_down, "",
1209 FALSE, TRUE, NULL);
1210 if (ret < 0) {
1211 ccnet_warning ("add ldapuser to db failed.\n");
1212 g_free (email_down);
1213 g_object_unref (emailuser);
1214 return NULL;
1215 }
1216
1217 g_object_set (emailuser, "id", ret, NULL);
1218 }
1219 }
1220
1221 g_free (email_down);
1222 return emailuser;
1223 }
1224 #endif
1225
1226 g_free (email_down);
1227
1228 return NULL;
1229
1230 }
1231
1232 CcnetEmailUser*
ccnet_user_manager_get_emailuser(CcnetUserManager * manager,const char * email)1233 ccnet_user_manager_get_emailuser (CcnetUserManager *manager,
1234 const char *email)
1235 {
1236 return get_emailuser (manager, email, FALSE);
1237 }
1238
1239 CcnetEmailUser*
ccnet_user_manager_get_emailuser_with_import(CcnetUserManager * manager,const char * email)1240 ccnet_user_manager_get_emailuser_with_import (CcnetUserManager *manager,
1241 const char *email)
1242 {
1243 return get_emailuser (manager, email, TRUE);
1244 }
1245
1246 CcnetEmailUser*
ccnet_user_manager_get_emailuser_by_id(CcnetUserManager * manager,int id)1247 ccnet_user_manager_get_emailuser_by_id (CcnetUserManager *manager, int id)
1248 {
1249 CcnetDB *db = manager->priv->db;
1250 char *sql;
1251 CcnetEmailUser *emailuser = NULL;
1252
1253 sql = "SELECT e.id, e.email, is_staff, is_active, ctime, passwd, reference_id, role "
1254 " FROM EmailUser e LEFT JOIN UserRole ON e.email = UserRole.email "
1255 " WHERE e.id=?";
1256 if (seaf_db_statement_foreach_row (db, sql, get_emailuser_cb, &emailuser,
1257 1, "int", id) < 0)
1258 return NULL;
1259
1260 return emailuser;
1261 }
1262
1263 static gboolean
get_emailusers_cb(CcnetDBRow * row,void * data)1264 get_emailusers_cb (CcnetDBRow *row, void *data)
1265 {
1266 GList **plist = data;
1267 CcnetEmailUser *emailuser;
1268
1269 int id = seaf_db_row_get_column_int (row, 0);
1270 const char *email = (const char *)seaf_db_row_get_column_text (row, 1);
1271 int is_staff = seaf_db_row_get_column_int (row, 2);
1272 int is_active = seaf_db_row_get_column_int (row, 3);
1273 gint64 ctime = seaf_db_row_get_column_int64 (row, 4);
1274 const char *role = (const char *)seaf_db_row_get_column_text (row, 5);
1275 const char *password = seaf_db_row_get_column_text (row, 6);
1276
1277 char *email_l = g_ascii_strdown (email, -1);
1278 emailuser = g_object_new (CCNET_TYPE_EMAIL_USER,
1279 "id", id,
1280 "email", email_l,
1281 "is_staff", is_staff,
1282 "is_active", is_active,
1283 "ctime", ctime,
1284 "role", role ? role : "",
1285 "source", "DB",
1286 "password", password,
1287 NULL);
1288 g_free (email_l);
1289
1290 *plist = g_list_prepend (*plist, emailuser);
1291
1292 return TRUE;
1293 }
1294
1295 static gboolean
get_ldap_emailusers_cb(CcnetDBRow * row,void * data)1296 get_ldap_emailusers_cb (CcnetDBRow *row, void *data)
1297 {
1298 GList **plist = data;
1299 CcnetEmailUser *emailuser = NULL;
1300
1301 int id = seaf_db_row_get_column_int (row, 0);
1302 const char *email = (const char *)seaf_db_row_get_column_text (row, 1);
1303 int is_staff = seaf_db_row_get_column_int (row, 2);
1304 int is_active = seaf_db_row_get_column_int (row, 3);
1305 const char *role = seaf_db_row_get_column_text (row, 4);
1306
1307 emailuser = g_object_new (CCNET_TYPE_EMAIL_USER,
1308 "id", id,
1309 "email", email,
1310 "is_staff", is_staff,
1311 "is_active", is_active,
1312 "ctime", (gint64)0,
1313 "role", role ? role : "",
1314 "source", "LDAPImport",
1315 "password", "!",
1316 NULL);
1317 if (!emailuser)
1318 return FALSE;
1319
1320 *plist = g_list_prepend (*plist, emailuser);
1321
1322 return TRUE;
1323 }
1324
1325 GList*
ccnet_user_manager_get_emailusers(CcnetUserManager * manager,const char * source,int start,int limit,const char * status)1326 ccnet_user_manager_get_emailusers (CcnetUserManager *manager,
1327 const char *source,
1328 int start, int limit,
1329 const char *status)
1330 {
1331 CcnetDB *db = manager->priv->db;
1332 const char *status_condition = "";
1333 char *sql = NULL;
1334 GList *ret = NULL;
1335 int rc;
1336
1337 #ifdef HAVE_LDAP
1338 if (manager->use_ldap) {
1339 GList *users = NULL;
1340
1341 if (g_strcmp0 (source, "LDAP") == 0) {
1342 users = ldap_list_users (manager, "*", start, limit);
1343 return g_list_reverse (users);
1344 } else if (g_strcmp0 (source, "LDAPImport") == 0) {
1345 if (start == -1 && limit == -1) {
1346 if (g_strcmp0(status, "active") == 0)
1347 status_condition = "WHERE t1.is_active = 1";
1348 else if (g_strcmp0(status, "inactive") == 0)
1349 status_condition = "WHERE t1.is_active = 0";
1350
1351 sql = g_strdup_printf ("SELECT t1.id, t1.email, t1.is_staff, "
1352 "t1.is_active, t2.role "
1353 "FROM LDAPUsers t1 LEFT JOIN UserRole t2 "
1354 "ON t1.email = t2.email %s",
1355 status_condition);
1356
1357 rc = seaf_db_statement_foreach_row (db,
1358 sql,
1359 get_ldap_emailusers_cb,
1360 &users, 0);
1361 g_free (sql);
1362 } else {
1363 if (g_strcmp0(status, "active") == 0)
1364 status_condition = "WHERE t1.is_active = 1";
1365 else if (g_strcmp0(status, "inactive") == 0)
1366 status_condition = "WHERE t1.is_active = 0";
1367
1368 sql = g_strdup_printf ("SELECT t1.id, t1.email, t1.is_staff, "
1369 "t1.is_active, t2.role "
1370 "FROM LDAPUsers t1 LEFT JOIN UserRole t2 "
1371 "ON t1.email = t2.email %s LIMIT ? OFFSET ?",
1372 status_condition);
1373
1374 rc = seaf_db_statement_foreach_row (db,
1375 sql,
1376 get_ldap_emailusers_cb,
1377 &users, 2, "int", limit, "int", start);
1378 g_free (sql);
1379 }
1380
1381 if (rc < 0) {
1382 while (users) {
1383 g_object_unref (users->data);
1384 users = g_list_delete_link (users, users);
1385 }
1386 return NULL;
1387 }
1388 return g_list_reverse (users);
1389 }
1390 }
1391 #endif
1392
1393 if (g_strcmp0 (source, "DB") != 0)
1394 return NULL;
1395
1396 if (start == -1 && limit == -1) {
1397 if (g_strcmp0(status, "active") == 0)
1398 status_condition = "WHERE t1.is_active = 1";
1399 else if (g_strcmp0(status, "inactive") == 0)
1400 status_condition = "WHERE t1.is_active = 0";
1401
1402 sql = g_strdup_printf ("SELECT t1.id, t1.email, "
1403 "t1.is_staff, t1.is_active, t1.ctime, "
1404 "t2.role, t1.passwd FROM EmailUser t1 "
1405 "LEFT JOIN UserRole t2 "
1406 "ON t1.email = t2.email %s "
1407 "WHERE t1.email NOT LIKE '%%@seafile_group'",
1408 status_condition);
1409
1410 rc = seaf_db_statement_foreach_row (db,
1411 sql,
1412 get_emailusers_cb, &ret,
1413 0);
1414 g_free (sql);
1415 } else {
1416 if (g_strcmp0(status, "active") == 0)
1417 status_condition = "WHERE t1.is_active = 1";
1418 else if (g_strcmp0(status, "inactive") == 0)
1419 status_condition = "WHERE t1.is_active = 0";
1420
1421 sql = g_strdup_printf ("SELECT t1.id, t1.email, "
1422 "t1.is_staff, t1.is_active, t1.ctime, "
1423 "t2.role, t1.passwd FROM EmailUser t1 "
1424 "LEFT JOIN UserRole t2 "
1425 "ON t1.email = t2.email %s "
1426 "WHERE t1.email NOT LIKE '%%@seafile_group' "
1427 "ORDER BY t1.id LIMIT ? OFFSET ?",
1428 status_condition);
1429
1430 rc = seaf_db_statement_foreach_row (db,
1431 sql,
1432 get_emailusers_cb, &ret,
1433 2, "int", limit, "int", start);
1434 g_free (sql);
1435 }
1436
1437 if (rc < 0) {
1438 while (ret != NULL) {
1439 g_object_unref (ret->data);
1440 ret = g_list_delete_link (ret, ret);
1441 }
1442 return NULL;
1443 }
1444
1445 return g_list_reverse (ret);
1446 }
1447
1448 GList*
ccnet_user_manager_search_emailusers(CcnetUserManager * manager,const char * source,const char * keyword,int start,int limit)1449 ccnet_user_manager_search_emailusers (CcnetUserManager *manager,
1450 const char *source,
1451 const char *keyword,
1452 int start, int limit)
1453 {
1454 CcnetDB *db = manager->priv->db;
1455 GList *ret = NULL;
1456 int rc;
1457 char *db_patt = g_strdup_printf ("%%%s%%", keyword);
1458
1459 #ifdef HAVE_LDAP
1460 if (manager->use_ldap) {
1461 if (strcmp (source, "LDAP") == 0) {
1462 if (start == -1 && limit == -1) {
1463 rc = seaf_db_statement_foreach_row (db,
1464 "SELECT t1.id, t1.email, t1.is_staff, "
1465 "t1.is_active, t2.role "
1466 "FROM LDAPUsers t1 LEFT JOIN UserRole t2 "
1467 "ON t1.email = t2.email WHERE t1.email LIKE ?",
1468 get_ldap_emailusers_cb,
1469 &ret, 1, "string", db_patt);
1470 } else {
1471 rc = seaf_db_statement_foreach_row (db,
1472 "SELECT t1.id, t1.email, t1.is_staff, "
1473 "t1.is_active, t2.role "
1474 "FROM LDAPUsers t1 LEFT JOIN UserRole t2 "
1475 "ON t1.email = t2.email WHERE t1.email LIKE ? "
1476 "LIMIT ? OFFSET ?",
1477 get_ldap_emailusers_cb,
1478 &ret, 3, "string", db_patt,
1479 "int", limit, "int", start);
1480 }
1481
1482 g_free (db_patt);
1483
1484 if (rc < 0) {
1485 while (ret) {
1486 g_object_unref (ret->data);
1487 ret = g_list_delete_link (ret, ret);
1488 }
1489 return NULL;
1490 }
1491 return g_list_reverse (ret);
1492 }
1493 }
1494 #endif
1495
1496 if (strcmp (source, "DB") != 0) {
1497 g_free (db_patt);
1498 return NULL;
1499 }
1500
1501 if (start == -1 && limit == -1)
1502 rc = seaf_db_statement_foreach_row (db,
1503 "SELECT t1.id, t1.email, "
1504 "t1.is_staff, t1.is_active, t1.ctime, "
1505 "t2.role, t1.passwd FROM EmailUser t1 "
1506 "LEFT JOIN UserRole t2 "
1507 "ON t1.email = t2.email "
1508 "WHERE t1.Email LIKE ? "
1509 "AND t1.email NOT LIKE '%%@seafile_group' "
1510 "ORDER BY t1.id",
1511 get_emailusers_cb, &ret,
1512 1, "string", db_patt);
1513 else
1514 rc = seaf_db_statement_foreach_row (db,
1515 "SELECT t1.id, t1.email, "
1516 "t1.is_staff, t1.is_active, t1.ctime, "
1517 "t2.role, t1.passwd FROM EmailUser t1 "
1518 "LEFT JOIN UserRole t2 "
1519 "ON t1.email = t2.email "
1520 "WHERE t1.Email LIKE ? "
1521 "AND t1.email NOT LIKE '%%@seafile_group' "
1522 "ORDER BY t1.id LIMIT ? OFFSET ?",
1523 get_emailusers_cb, &ret,
1524 3, "string", db_patt,
1525 "int", limit, "int", start);
1526 g_free (db_patt);
1527 if (rc < 0) {
1528 while (ret != NULL) {
1529 g_object_unref (ret->data);
1530 ret = g_list_delete_link (ret, ret);
1531 }
1532 return NULL;
1533 }
1534
1535 return g_list_reverse (ret);
1536 }
1537
1538 GList*
ccnet_user_manager_search_ldapusers(CcnetUserManager * manager,const char * keyword,int start,int limit)1539 ccnet_user_manager_search_ldapusers (CcnetUserManager *manager,
1540 const char *keyword,
1541 int start, int limit)
1542 {
1543 GList *ret = NULL;
1544
1545 #ifdef HAVE_LDAP
1546 if (!manager->use_ldap) {
1547 return NULL;
1548 }
1549
1550 char *ldap_patt = g_strdup_printf ("*%s*", keyword);
1551
1552 ret = ldap_list_users (manager, ldap_patt, start, limit);
1553
1554 g_free (ldap_patt);
1555 #endif
1556
1557 return ret;
1558 }
1559
1560 gint64
ccnet_user_manager_count_emailusers(CcnetUserManager * manager,const char * source)1561 ccnet_user_manager_count_emailusers (CcnetUserManager *manager, const char *source)
1562 {
1563 CcnetDB* db = manager->priv->db;
1564 char sql[512];
1565 gint64 ret;
1566
1567 #ifdef HAVE_LDAP
1568 if (manager->use_ldap && g_strcmp0(source, "LDAP") == 0) {
1569 gint64 ret = seaf_db_get_int64 (db, "SELECT COUNT(id) FROM LDAPUsers WHERE is_active = 1");
1570 if (ret < 0)
1571 return -1;
1572 return ret;
1573 }
1574 #endif
1575
1576 if (g_strcmp0 (source, "DB") != 0)
1577 return -1;
1578
1579 snprintf (sql, 512, "SELECT COUNT(id) FROM EmailUser WHERE is_active = 1");
1580
1581 ret = seaf_db_get_int64 (db, sql);
1582 if (ret < 0)
1583 return -1;
1584 return ret;
1585 }
1586
1587 gint64
ccnet_user_manager_count_inactive_emailusers(CcnetUserManager * manager,const char * source)1588 ccnet_user_manager_count_inactive_emailusers (CcnetUserManager *manager, const char *source)
1589 {
1590 CcnetDB* db = manager->priv->db;
1591 char sql[512];
1592 gint64 ret;
1593
1594 #ifdef HAVE_LDAP
1595 if (manager->use_ldap && g_strcmp0(source, "LDAP") == 0) {
1596 gint64 ret = seaf_db_get_int64 (db, "SELECT COUNT(id) FROM LDAPUsers WHERE is_active = 0");
1597 if (ret < 0)
1598 return -1;
1599 return ret;
1600 }
1601 #endif
1602
1603 if (g_strcmp0 (source, "DB") != 0)
1604 return -1;
1605
1606 snprintf (sql, 512, "SELECT COUNT(id) FROM EmailUser WHERE is_active = 0");
1607
1608 ret = seaf_db_get_int64 (db, sql);
1609 if (ret < 0)
1610 return -1;
1611 return ret;
1612 }
1613
1614 #if 0
1615 GList*
1616 ccnet_user_manager_filter_emailusers_by_emails(CcnetUserManager *manager,
1617 const char *emails)
1618 {
1619 CcnetDB *db = manager->priv->db;
1620 char *copy = g_strdup (emails), *saveptr;
1621 GList *ret = NULL;
1622
1623 #ifdef HAVE_LDAP
1624 if (manager->use_ldap)
1625 return NULL; /* todo */
1626 #endif
1627
1628 GString *sql = g_string_new(NULL);
1629
1630 g_string_append (sql, "SELECT * FROM EmailUser WHERE Email IN (");
1631 char *name = strtok_r (copy, ", ", &saveptr);
1632 while (name != NULL) {
1633 g_string_append_printf (sql, "'%s',", name);
1634 name = strtok_r (NULL, ", ", &saveptr);
1635 }
1636 g_string_erase (sql, sql->len-1, 1); /* remove last "," */
1637 g_string_append (sql, ")");
1638
1639 if (seaf_db_foreach_selected_row (db, sql->str, get_emailusers_cb,
1640 &ret) < 0) {
1641 while (ret != NULL) {
1642 g_object_unref (ret->data);
1643 ret = g_list_delete_link (ret, ret);
1644 }
1645 return NULL;
1646 }
1647
1648 g_free (copy);
1649 g_string_free (sql, TRUE);
1650
1651 return g_list_reverse (ret);
1652 }
1653 #endif
1654
1655 int
ccnet_user_manager_update_emailuser(CcnetUserManager * manager,const char * source,int id,const char * passwd,int is_staff,int is_active)1656 ccnet_user_manager_update_emailuser (CcnetUserManager *manager,
1657 const char *source,
1658 int id, const char* passwd,
1659 int is_staff, int is_active)
1660 {
1661 CcnetDB* db = manager->priv->db;
1662 char *db_passwd = NULL;
1663
1664 // in case set user user1 to inactive, then add another active user user2,
1665 // if current user num already the max user num,
1666 // then reset user1 to active should fail
1667 if (is_active && !check_user_number (manager, FALSE)) {
1668 return -1;
1669 }
1670
1671 if (strcmp (source, "DB") == 0) {
1672 if (g_strcmp0 (passwd, "!") == 0) {
1673 /* Don't update passwd if it starts with '!' */
1674 return seaf_db_statement_query (db, "UPDATE EmailUser SET is_staff=?, "
1675 "is_active=? WHERE id=?",
1676 3, "int", is_staff, "int", is_active,
1677 "int", id);
1678 } else {
1679 hash_password_pbkdf2_sha256 (passwd, manager->passwd_hash_iter, &db_passwd);
1680
1681 return seaf_db_statement_query (db, "UPDATE EmailUser SET passwd=?, "
1682 "is_staff=?, is_active=? WHERE id=?",
1683 4, "string", db_passwd, "int", is_staff,
1684 "int", is_active, "int", id);
1685 }
1686 }
1687
1688 #ifdef HAVE_LDAP
1689 if (manager->use_ldap && strcmp (source, "LDAP") == 0) {
1690 return seaf_db_statement_query (db, "UPDATE LDAPUsers SET is_staff=?, "
1691 "is_active=? WHERE id=?",
1692 3, "int", is_staff, "int", is_active,
1693 "int", id);
1694 }
1695 #endif
1696
1697 return -1;
1698 }
1699
1700 static gboolean
get_role_emailuser_cb(CcnetDBRow * row,void * data)1701 get_role_emailuser_cb (CcnetDBRow *row, void *data)
1702 {
1703 *((char **)data) = g_strdup (seaf_db_row_get_column_text (row, 0));
1704
1705 return FALSE;
1706 }
1707
1708 static char*
ccnet_user_manager_get_role_emailuser(CcnetUserManager * manager,const char * email)1709 ccnet_user_manager_get_role_emailuser (CcnetUserManager *manager,
1710 const char* email)
1711 {
1712
1713 CcnetDB *db = manager->priv->db;
1714 const char *sql;
1715 char* role;
1716
1717 sql = "SELECT role FROM UserRole WHERE email=?";
1718 if (seaf_db_statement_foreach_row (db, sql, get_role_emailuser_cb, &role,
1719 1, "string", email) > 0)
1720 return role;
1721
1722 return NULL;
1723 }
1724
1725 int
ccnet_user_manager_update_role_emailuser(CcnetUserManager * manager,const char * email,const char * role)1726 ccnet_user_manager_update_role_emailuser (CcnetUserManager *manager,
1727 const char* email, const char* role)
1728 {
1729 CcnetDB* db = manager->priv->db;
1730 char *old_role = ccnet_user_manager_get_role_emailuser (manager, email);
1731 if (old_role) {
1732 g_free (old_role);
1733 return seaf_db_statement_query (db, "UPDATE UserRole SET role=? "
1734 "WHERE email=?",
1735 2, "string", role, "string", email);
1736 } else
1737 return seaf_db_statement_query (db, "INSERT INTO UserRole(role, email)"
1738 " VALUES (?, ?)",
1739 2, "string", role, "string", email);
1740 }
1741
1742 GList*
ccnet_user_manager_get_superusers(CcnetUserManager * manager)1743 ccnet_user_manager_get_superusers(CcnetUserManager *manager)
1744 {
1745 CcnetDB* db = manager->priv->db;
1746 GList *ret = NULL;
1747 char sql[512];
1748
1749 snprintf (sql, 512,
1750 "SELECT t1.id, t1.email, "
1751 "t1.is_staff, t1.is_active, t1.ctime, "
1752 "t2.role, t1.passwd FROM EmailUser t1 "
1753 "LEFT JOIN UserRole t2 "
1754 "ON t1.email = t2.email "
1755 "WHERE is_staff = 1 AND t1.email NOT LIKE '%%@seafile_group';");
1756
1757 if (seaf_db_foreach_selected_row (db, sql, get_emailusers_cb, &ret) < 0) {
1758 while (ret != NULL) {
1759 g_object_unref (ret->data);
1760 ret = g_list_delete_link (ret, ret);
1761 }
1762 return NULL;
1763 }
1764
1765 if (seaf_db_foreach_selected_row (db,
1766 "SELECT t1.id, t1.email, "
1767 "t1.is_staff, t1.is_active, "
1768 "t2.role FROM LDAPUsers t1 "
1769 "LEFT JOIN UserRole t2 "
1770 "ON t1.email = t2.email "
1771 "WHERE is_staff = 1",
1772 get_ldap_emailusers_cb, &ret) < 0) {
1773 while (ret != NULL) {
1774 g_object_unref (ret->data);
1775 ret = g_list_delete_link (ret, ret);
1776 }
1777 return NULL;
1778 }
1779
1780 return g_list_reverse (ret);
1781 }
1782
1783 int
ccnet_user_manager_set_reference_id(CcnetUserManager * manager,const char * primary_id,const char * reference_id,GError ** error)1784 ccnet_user_manager_set_reference_id (CcnetUserManager *manager,
1785 const char *primary_id,
1786 const char *reference_id,
1787 GError **error)
1788 {
1789 int rc;
1790 char *sql;
1791 gboolean exists, err;
1792
1793 #ifdef HAVE_LDAP
1794 if (manager->use_ldap) {
1795 sql = "SELECT email FROM LDAPUsers WHERE email = ?";
1796 exists = seaf_db_statement_exists (manager->priv->db, sql, &err,
1797 1, "string", primary_id);
1798 if (err)
1799 return -1;
1800 /* Make sure reference_id is unique */
1801 if (exists) {
1802 sql = "SELECT 1 FROM EmailUser e, LDAPUsers l "
1803 "WHERE (e.reference_id=? AND e.email!=?) OR "
1804 "(l.reference_id=? AND l.email!=?) OR "
1805 "(e.email=? AND e.email!=?) OR (l.email=? AND l.email!=?)";
1806 exists = seaf_db_statement_exists (manager->priv->db, sql, &err,
1807 8, "string", reference_id,
1808 "string", primary_id,
1809 "string", reference_id,
1810 "string", primary_id,
1811 "string", reference_id,
1812 "string", primary_id,
1813 "string", reference_id,
1814 "string", primary_id);
1815 if (err)
1816 return -1;
1817 if (exists) {
1818 ccnet_warning ("Failed to set reference id, email '%s' exists\n", reference_id);
1819 return -1;
1820 }
1821
1822 sql = "UPDATE LDAPUsers SET reference_id=? WHERE email=?";
1823 rc = seaf_db_statement_query (manager->priv->db, sql, 2,
1824 "string", reference_id, "string", primary_id);
1825 if (rc < 0){
1826 ccnet_warning ("Failed to set reference id for '%s'\n", primary_id);
1827 }
1828 return rc;
1829 }
1830 }
1831 #endif
1832
1833 sql = "SELECT email FROM EmailUser WHERE email = ?";
1834 exists = seaf_db_statement_exists (manager->priv->db, sql, &err,
1835 1, "string", primary_id);
1836 if (err)
1837 return -1;
1838 /* Make sure reference_id is unique */
1839 if (exists) {
1840 sql = "SELECT 1 FROM EmailUser e, LDAPUsers l "
1841 "WHERE (e.reference_id=? AND e.email!=?) OR "
1842 "(l.reference_id=? AND l.email!=?) OR "
1843 "(e.email=? AND e.email!=?) OR (l.email=? AND l.email!=?)";
1844 exists = seaf_db_statement_exists (manager->priv->db, sql, &err,
1845 8, "string", reference_id,
1846 "string", primary_id,
1847 "string", reference_id,
1848 "string", primary_id,
1849 "string", reference_id,
1850 "string", primary_id,
1851 "string", reference_id,
1852 "string", primary_id);
1853 if (err)
1854 return -1;
1855 if (exists) {
1856 ccnet_warning ("Failed to set reference id, email '%s' exists\n", reference_id);
1857 return -1;
1858 }
1859
1860 sql = "UPDATE EmailUser SET reference_id=? WHERE email=?";
1861 rc = seaf_db_statement_query (manager->priv->db, sql, 2,
1862 "string", reference_id, "string", primary_id);
1863 if (rc < 0){
1864 ccnet_warning ("Failed to set reference id for %s\n", primary_id);
1865 return -1;
1866 }
1867 return rc;
1868 } else {
1869 ccnet_warning ("Failed to set reference id, Primary id '%s' not exists\n", primary_id);
1870 return -1;
1871 }
1872 }
1873
1874 char *
ccnet_user_manager_get_primary_id(CcnetUserManager * manager,const char * email)1875 ccnet_user_manager_get_primary_id (CcnetUserManager *manager, const char *email)
1876 {
1877 char *sql;
1878 char *primary_id = NULL;
1879
1880 #ifdef HAVE_LDAP
1881 if (manager->use_ldap) {
1882 sql = "SELECT email FROM LDAPUsers WHERE reference_id=?";
1883 primary_id = seaf_db_statement_get_string (manager->priv->db, sql, 1, "string", email);
1884 if (primary_id)
1885 return primary_id;
1886 }
1887 #endif
1888
1889 sql = "SELECT email FROM EmailUser WHERE reference_id=?";
1890 primary_id = seaf_db_statement_get_string (manager->priv->db, sql, 1, "string", email);
1891 if (primary_id)
1892 return primary_id;
1893 else
1894 return NULL;
1895 }
1896
1897 char *
ccnet_user_manager_get_login_id(CcnetUserManager * manager,const char * primary_id)1898 ccnet_user_manager_get_login_id (CcnetUserManager *manager, const char *primary_id)
1899 {
1900 #ifdef HAVE_LDAP
1901 if (manager->use_ldap) {
1902 char *sql = "SELECT reference_id FROM LDAPUsers WHERE email=?";
1903 char *ldap_login_id = seaf_db_statement_get_string (manager->priv->db, sql, 1, "string", primary_id);
1904
1905 if (ldap_login_id)
1906 return ldap_login_id;
1907 }
1908 #endif
1909 return g_strdup (primary_id);
1910 }
1911
1912 GList *
ccnet_user_manager_get_emailusers_in_list(CcnetUserManager * manager,const char * source,const char * user_list,GError ** error)1913 ccnet_user_manager_get_emailusers_in_list (CcnetUserManager *manager,
1914 const char *source,
1915 const char *user_list,
1916 GError **error)
1917 {
1918 int i;
1919 const char *username;
1920 json_t *j_array = NULL, *j_obj;
1921 json_error_t j_error;
1922 GList *ret = NULL;
1923 const char *args[20];
1924
1925 j_array = json_loadb (user_list, strlen(user_list), 0, &j_error);
1926 if (!j_array) {
1927 g_set_error (error, CCNET_DOMAIN, 0, "Bad args.");
1928 return NULL;
1929 }
1930 /* Query 20 users at most. */
1931 size_t user_num = json_array_size (j_array);
1932 if (user_num > 20) {
1933 g_set_error (error, CCNET_DOMAIN, 0, "Number of users exceeds 20.");
1934 json_decref (j_array);
1935 return NULL;
1936 }
1937 GString *sql = g_string_new ("");
1938 for (i = 0; i < 20; i++) {
1939 if (i < user_num) {
1940 j_obj = json_array_get (j_array, i);
1941 username = json_string_value(j_obj);
1942 args[i] = username;
1943 } else {
1944 args[i] = "";
1945 }
1946 }
1947
1948 #ifdef HAVE_LDAP
1949 if (manager->use_ldap) {
1950 if (strcmp (source, "LDAP") == 0) {
1951 g_string_printf (sql, "SELECT l.id, l.email, is_staff, is_active, role "
1952 "FROM LDAPUsers l LEFT JOIN UserRole r "
1953 "ON l.email = r.email "
1954 "WHERE l.email IN (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
1955 if (seaf_db_statement_foreach_row (manager->priv->db, sql->str, get_ldap_emailusers_cb, &ret, 20,
1956 "string", args[0], "string", args[1], "string", args[2],
1957 "string", args[3], "string", args[4], "string", args[5],
1958 "string", args[6], "string", args[7], "string", args[8],
1959 "string", args[9], "string", args[10], "string", args[11],
1960 "string", args[12], "string", args[13], "string", args[14],
1961 "string", args[15], "string", args[16], "string", args[17],
1962 "string", args[18], "string", args[19]) < 0)
1963 ccnet_warning("Failed to get users in list %s.\n", user_list);
1964
1965 goto out;
1966 }
1967 }
1968 #endif
1969 if (strcmp (source, "DB") != 0)
1970 goto out;
1971
1972 g_string_printf (sql, "SELECT e.id, e.email, is_staff, is_active, ctime, "
1973 "role, passwd FROM EmailUser e "
1974 "LEFT JOIN UserRole r ON e.email = r.email "
1975 "WHERE e.email IN (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
1976
1977 if (seaf_db_statement_foreach_row (manager->priv->db, sql->str, get_emailusers_cb, &ret, 20,
1978 "string", args[0], "string", args[1], "string", args[2],
1979 "string", args[3], "string", args[4], "string", args[5],
1980 "string", args[6], "string", args[7], "string", args[8],
1981 "string", args[9], "string", args[10], "string", args[11],
1982 "string", args[12], "string", args[13], "string", args[14],
1983 "string", args[15], "string", args[16], "string", args[17],
1984 "string", args[18], "string", args[19]) < 0)
1985 ccnet_warning("Failed to get users in list %s.\n", user_list);
1986
1987 out:
1988 json_decref (j_array);
1989 g_string_free (sql, TRUE);
1990
1991 return ret;
1992 }
1993
1994 int
ccnet_user_manager_update_emailuser_id(CcnetUserManager * manager,const char * old_email,const char * new_email,GError ** error)1995 ccnet_user_manager_update_emailuser_id (CcnetUserManager *manager,
1996 const char *old_email,
1997 const char *new_email,
1998 GError **error)
1999 {
2000 int ret = -1;
2001 int rc;
2002 GString *sql = g_string_new ("");
2003
2004 //1.update RepoOwner
2005 g_string_printf (sql, "UPDATE RepoOwner SET owner_id=? WHERE owner_id=?");
2006 rc = seaf_db_statement_query (seaf->db, sql->str, 2,
2007 "string", new_email,
2008 "string", old_email);
2009 if (rc < 0){
2010 ccnet_warning ("Failed to update repo owner\n");
2011 goto out;
2012 }
2013
2014 //2.update SharedRepo
2015 g_string_printf (sql, "UPDATE SharedRepo SET from_email=? WHERE from_email=?");
2016 rc = seaf_db_statement_query (seaf->db, sql->str, 2,
2017 "string", new_email,
2018 "string", old_email);
2019 if (rc < 0){
2020 ccnet_warning ("Failed to update from_email\n");
2021 goto out;
2022 }
2023
2024 g_string_printf (sql, "UPDATE SharedRepo SET to_email=? WHERE to_email=?");
2025 rc = seaf_db_statement_query (seaf->db, sql->str, 2,
2026 "string", new_email,
2027 "string", old_email);
2028 if (rc < 0){
2029 ccnet_warning ("Failed to update to_email\n");
2030 goto out;
2031 }
2032
2033 //3.update GroupUser
2034 rc = ccnet_group_manager_update_group_user (seaf->group_mgr, old_email, new_email);
2035 if (rc < 0){
2036 ccnet_warning ("Failed to update group member\n");
2037 goto out;
2038 }
2039
2040 //4.update RepoUserToken
2041 g_string_printf (sql, "UPDATE RepoUserToken SET email=? WHERE email=?");
2042 rc = seaf_db_statement_query (seaf->db, sql->str, 2,
2043 "string", new_email,
2044 "string", old_email);
2045 if (rc < 0){
2046 ccnet_warning ("Failed to update repo user token\n");
2047 goto out;
2048 }
2049
2050 //5.uptede FolderUserPerm
2051 g_string_printf (sql, "UPDATE FolderUserPerm SET user=? WHERE user=?");
2052 rc = seaf_db_statement_query (seaf->db, sql->str, 2,
2053 "string", new_email,
2054 "string", old_email);
2055 if (rc < 0){
2056 ccnet_warning ("Failed to update user folder permission\n");
2057 goto out;
2058 }
2059
2060 //6.update EmailUser
2061 g_string_printf (sql, "UPDATE EmailUser SET email=? WHERE email=?");
2062 rc = seaf_db_statement_query (manager->priv->db, sql->str, 2,
2063 "string", new_email,
2064 "string", old_email);
2065 if (rc < 0){
2066 ccnet_warning ("Failed to update email user\n");
2067 goto out;
2068 }
2069
2070 g_string_printf (sql, "UPDATE LDAPUsers SET email=? WHERE email=?");
2071 rc = seaf_db_statement_query (manager->priv->db, sql->str, 2,
2072 "string", new_email,
2073 "string", old_email);
2074 if (rc < 0){
2075 ccnet_warning ("Failed to update LDAP user\n");
2076 goto out;
2077 }
2078 //7.update UserQuota
2079 g_string_printf (sql, "UPDATE UserQuota SET user=? WHERE user=?");
2080 rc = seaf_db_statement_query (seaf->db, sql->str, 2,
2081 "string", new_email,
2082 "string", old_email);
2083 if (rc < 0){
2084 ccnet_warning ("Failed to update user quota\n");
2085 goto out;
2086 }
2087
2088 ret = 0;
2089 out:
2090 g_string_free (sql, TRUE);
2091 return ret;
2092 }
2093