1from .service import seafserv_threaded_rpc, ccnet_threaded_rpc 2from pysearpc import SearpcError 3import json 4 5""" 6General rules for return values and exception handling of Seafile python API: 7- Read operations return corresponding values. Raises exceptions on parameter errors 8 or I/O errors in seaf-server. 9- Write or set operations return 0 on success, -1 on error. On error, an exceptioin 10 will be raised. 11 12All paths in parameters can be in absolute path format (like '/test') or 13relative path format (like 'test'). The API can handle both formats. 14""" 15 16REPO_STATUS_NORMAL = 0 17REPO_STATUS_READ_ONLY = 1 18 19class SeafileAPI(object): 20 21 def __init__(self): 22 pass 23 24 # fileserver token 25 26 def get_fileserver_access_token(self, repo_id, obj_id, op, username, use_onetime=True): 27 """Generate token for access file/dir in fileserver 28 29 op: the operation, can be 'view', 'download', 'download-dir', 'downloadblks', 30 'upload', 'update', 'upload-blks-api', 'upload-blks-aj', 31 'update-blks-api', 'update-blks-aj' 32 33 Return: the access token in string 34 """ 35 onetime = 1 if bool(use_onetime) else 0 36 return seafserv_threaded_rpc.web_get_access_token(repo_id, obj_id, op, username, 37 onetime) 38 39 def query_fileserver_access_token(self, token): 40 """Get the WebAccess object 41 42 token: the access token in string 43 44 Return: the WebAccess object (lib/webaccess.vala) 45 """ 46 return seafserv_threaded_rpc.web_query_access_token(token) 47 48 def query_zip_progress(self, token): 49 """Query zip progress for download-dir, download-multi 50 token: obtained by get_fileserver_access_token 51 Return: json formated string `{"zipped":, "total":}`, otherwise None. 52 """ 53 return seafserv_threaded_rpc.query_zip_progress(token) 54 55 def cancel_zip_task(self, token): 56 return seafserv_threaded_rpc.cancel_zip_task(token) 57 58 # password 59 60 def is_password_set(self, repo_id, username): 61 """ 62 Return non-zero if True, otherwise 0. 63 """ 64 return seafserv_threaded_rpc.is_passwd_set(repo_id, username) 65 66 def get_decrypt_key(self, repo_id, username): 67 """ 68 Return: a CryptKey object (lib/crypt.vala) 69 """ 70 return seafserv_threaded_rpc.get_decrypt_key(repo_id, username) 71 72 def change_repo_passwd(self, repo_id, old_passwd, new_passwd, user): 73 return seafserv_threaded_rpc.change_repo_passwd(repo_id, old_passwd, 74 new_passwd, user) 75 def check_passwd(self, repo_id, magic): 76 return seafserv_threaded_rpc.check_passwd(repo_id, magic) 77 78 def set_passwd(self, repo_id, user, passwd): 79 return seafserv_threaded_rpc.set_passwd(repo_id, user, passwd) 80 81 def unset_passwd(self, repo_id, user): 82 return seafserv_threaded_rpc.unset_passwd(repo_id, user) 83 84 def generate_magic_and_random_key(self, enc_version, repo_id, password): 85 return seafserv_threaded_rpc.generate_magic_and_random_key(enc_version, repo_id, password) 86 87 # repo manipulation 88 89 def create_repo(self, name, desc, username, passwd=None, enc_version=2, storage_id=None): 90 return seafserv_threaded_rpc.create_repo(name, desc, username, passwd, enc_version) 91 92 def create_enc_repo(self, repo_id, name, desc, username, magic, random_key, salt, enc_version): 93 return seafserv_threaded_rpc.create_enc_repo(repo_id, name, desc, username, magic, random_key, salt, enc_version) 94 95 def get_repo(self, repo_id): 96 """ 97 Return: a Repo object (lib/repo.vala) 98 """ 99 return seafserv_threaded_rpc.get_repo(repo_id) 100 101 def remove_repo(self, repo_id): 102 return seafserv_threaded_rpc.remove_repo(repo_id) 103 104 def get_repo_list(self, start, limit, order_by=None): 105 """ 106 Return: a list of Repo objects (lib/repo.vala) 107 """ 108 return seafserv_threaded_rpc.get_repo_list(start, limit, order_by) 109 110 def count_repos(self): 111 return seafserv_threaded_rpc.count_repos() 112 113 def edit_repo(self, repo_id, name, description, username): 114 return seafserv_threaded_rpc.edit_repo(repo_id, name, description, username) 115 116 def is_repo_owner(self, username, repo_id): 117 """ 118 Return 1 if True, otherwise 0. 119 """ 120 return seafserv_threaded_rpc.is_repo_owner(username, repo_id) 121 122 def set_repo_owner(self, email, repo_id): 123 return seafserv_threaded_rpc.set_repo_owner(email, repo_id) 124 125 def get_repo_owner(self, repo_id): 126 """ 127 Return: repo owner in string 128 """ 129 return seafserv_threaded_rpc.get_repo_owner(repo_id) 130 131 def get_owned_repo_list(self, username, ret_corrupted=False, start=-1, limit=-1): 132 """ 133 Return: a list of Repo objects 134 """ 135 return seafserv_threaded_rpc.list_owned_repos(username, 136 1 if ret_corrupted else 0, 137 start, limit) 138 139 def search_repos_by_name(self, name): 140 return seafserv_threaded_rpc.search_repos_by_name(name) 141 142 def get_orphan_repo_list(self): 143 return seafserv_threaded_rpc.get_orphan_repo_list() 144 145 def get_repo_size(self, repo_id): 146 return seafserv_threaded_rpc.server_repo_size(repo_id) 147 148 def revert_repo(self, repo_id, commit_id, username): 149 return seafserv_threaded_rpc.revert_on_server(repo_id, commit_id, username) 150 151 def diff_commits(self, repo_id, old_commit, new_commit, fold_dir_diff = 1): 152 """ 153 Return: a list of DiffEntry objects (lib/repo.vala) 154 """ 155 return seafserv_threaded_rpc.get_diff(repo_id, old_commit, new_commit, fold_dir_diff) 156 157 def get_commit_list(self, repo_id, offset, limit): 158 """ 159 Return: a list of Commit objects (lib/commit.vala) 160 """ 161 return seafserv_threaded_rpc.get_commit_list(repo_id, offset, limit) 162 163 def get_commit(self, repo_id, repo_version, cmt_id): 164 """ Get a commit. """ 165 try: 166 ret = seafserv_threaded_rpc.get_commit(repo_id, repo_version, cmt_id) 167 except SearpcError: 168 ret = None 169 return ret 170 171 def get_system_default_repo_id (self): 172 return seafserv_threaded_rpc.get_system_default_repo_id() 173 174 def get_org_id_by_repo_id (self, repo_id): 175 return seafserv_threaded_rpc.get_org_id_by_repo_id(repo_id) 176 177 def set_repo_status (self, repo_id, status): 178 return seafserv_threaded_rpc.set_repo_status(repo_id, status) 179 180 def get_repo_status (self, repo_id): 181 return seafserv_threaded_rpc.get_repo_status(repo_id) 182 183 # File property and dir listing 184 185 def is_valid_filename(self, repo_id, filename): 186 """ 187 Return: 0 on invalid; 1 on valid. 188 """ 189 return seafserv_threaded_rpc.is_valid_filename(repo_id, filename) 190 191 def get_file_size(self, store_id, version, file_id): 192 return seafserv_threaded_rpc.get_file_size(store_id, version, file_id) 193 194 def get_dir_size(self, store_id, version, dir_id): 195 """ 196 Return the size of a dir. It needs to recursively calculate the size 197 of the dir. It can cause great delay before returning. Use with caution! 198 """ 199 return seafserv_threaded_rpc.get_dir_size(store_id, version, dir_id) 200 201 def get_file_id_by_path(self, repo_id, path): 202 """ 203 Returns None if path not found. Only raise exception on parameter or IO error. 204 """ 205 return seafserv_threaded_rpc.get_file_id_by_path(repo_id, path) 206 207 def get_file_id_by_commit_and_path(self, repo_id, commit_id, path): 208 return seafserv_threaded_rpc.get_file_id_by_commit_and_path(repo_id, 209 commit_id, 210 path) 211 212 def get_dirent_by_path(self, repo_id, path): 213 """ 214 Return: a Dirent object (lib/dirent.vala) 215 """ 216 return seafserv_threaded_rpc.get_dirent_by_path(repo_id, path) 217 218 def list_file_by_file_id(self, repo_id, file_id, offset=-1, limit=-1): 219 # deprecated, use list_blocks_by_file_id instead. 220 return seafserv_threaded_rpc.list_file_blocks(repo_id, file_id, offset, limit) 221 222 def list_blocks_by_file_id(self, repo_id, file_id, offset=-1, limit=-1): 223 """ 224 list block ids of a file. 225 Return: a string containing block list. Each id is seperated by '\n' 226 """ 227 return seafserv_threaded_rpc.list_file_blocks(repo_id, file_id, offset, limit) 228 229 def get_dir_id_by_path(self, repo_id, path): 230 return seafserv_threaded_rpc.get_dir_id_by_path(repo_id, path) 231 232 def list_dir_by_dir_id(self, repo_id, dir_id, offset=-1, limit=-1): 233 """ 234 Return: a list of Dirent objects. The objects are sorted as follows: 235 - Directories are always before files 236 - Entries are sorted by names in ascending order 237 """ 238 return seafserv_threaded_rpc.list_dir(repo_id, dir_id, offset, limit) 239 240 def list_dir_by_path(self, repo_id, path, offset=-1, limit=-1): 241 dir_id = seafserv_threaded_rpc.get_dir_id_by_path(repo_id, path) 242 if dir_id is None: 243 return None 244 return seafserv_threaded_rpc.list_dir(repo_id, dir_id, offset, limit) 245 246 def list_dir_by_commit_and_path(self, repo_id, 247 commit_id, path, offset=-1, limit=-1): 248 dir_id = seafserv_threaded_rpc.get_dir_id_by_commit_and_path(repo_id, commit_id, path) 249 if dir_id is None: 250 return None 251 return seafserv_threaded_rpc.list_dir(repo_id, dir_id, offset, limit) 252 253 def get_dir_id_by_commit_and_path(self, repo_id, commit_id, path): 254 return seafserv_threaded_rpc.get_dir_id_by_commit_and_path(repo_id, commit_id, path) 255 256 def list_dir_with_perm(self, repo_id, dir_path, dir_id, user, offset=-1, limit=-1): 257 return seafserv_threaded_rpc.list_dir_with_perm (repo_id, dir_path, dir_id, user, offset, limit) 258 259 def mkdir_with_parents (self, repo_id, parent_dir, relative_path, username): 260 return seafserv_threaded_rpc.mkdir_with_parents(repo_id, parent_dir, relative_path, username) 261 262 def get_file_count_info_by_path(self, repo_id, path): 263 return seafserv_threaded_rpc.get_file_count_info_by_path(repo_id, path) 264 265 def get_total_storage (self): 266 return seafserv_threaded_rpc.get_total_storage() 267 268 def get_total_file_number (self): 269 return seafserv_threaded_rpc.get_total_file_number() 270 271 # file/dir operations 272 273 def post_file(self, repo_id, tmp_file_path, parent_dir, filename, username): 274 """Add a file to a directory""" 275 return seafserv_threaded_rpc.post_file(repo_id, tmp_file_path, parent_dir, 276 filename, username) 277 278 def post_empty_file(self, repo_id, parent_dir, filename, username): 279 return seafserv_threaded_rpc.post_empty_file(repo_id, parent_dir, 280 filename, username) 281 282 def put_file(self, repo_id, tmp_file_path, parent_dir, filename, 283 username, head_id): 284 """Update an existing file 285 286 head_id: the original commit id of the old file 287 """ 288 return seafserv_threaded_rpc.put_file(repo_id, tmp_file_path, parent_dir, 289 filename, username, head_id) 290 291 ''' 292 If you want to delete multiple files in a batch, @filename should be in 293 the following format: 'filename1\tfilename2\tfilename3' 294 ''' 295 def del_file(self, repo_id, parent_dir, filename, username): 296 return seafserv_threaded_rpc.del_file(repo_id, parent_dir, filename, username) 297 298 ''' 299 If you want to move or copy multiple files in a batch, @src_filename and @dst_filename 300 should be in the following format: 'filename1\tfilename2\tfilename3',make sure the number of files 301 in @src_filename and @dst_filename parameters match 302 ''' 303 def copy_file(self, src_repo, src_dir, src_filename, dst_repo, 304 dst_dir, dst_filename, username, need_progress, synchronous=0): 305 return seafserv_threaded_rpc.copy_file(src_repo, src_dir, src_filename, 306 dst_repo, dst_dir, dst_filename, 307 username, need_progress, synchronous) 308 309 def move_file(self, src_repo, src_dir, src_filename, dst_repo, dst_dir, 310 dst_filename, replace, username, need_progress, synchronous=0): 311 return seafserv_threaded_rpc.move_file(src_repo, src_dir, src_filename, 312 dst_repo, dst_dir, dst_filename, 313 replace, username, need_progress, synchronous) 314 315 def get_copy_task(self, task_id): 316 return seafserv_threaded_rpc.get_copy_task(task_id) 317 318 def cancel_copy_task(self, task_id): 319 return seafserv_threaded_rpc.cancel_copy_task(task_id) 320 321 def rename_file(self, repo_id, parent_dir, oldname, newname, username): 322 return seafserv_threaded_rpc.rename_file(repo_id, parent_dir, 323 oldname, newname, username) 324 325 def post_dir(self, repo_id, parent_dir, dirname, username): 326 """Add a directory""" 327 return seafserv_threaded_rpc.post_dir(repo_id, parent_dir, dirname, username) 328 329 def revert_file(self, repo_id, commit_id, path, username): 330 return seafserv_threaded_rpc.revert_file(repo_id, commit_id, path, username) 331 332 def revert_dir(self, repo_id, commit_id, path, username): 333 return seafserv_threaded_rpc.revert_dir(repo_id, commit_id, path, username) 334 335 def get_deleted(self, repo_id, show_days, path='/', scan_stat=None, limit=100): 336 """ 337 Get list of deleted paths. 338 339 @show_days: return deleted path in the last @show_days 340 @path: return deleted files under this path. The path will be recursively traversed. 341 @scan_stat: An opaque status returned by the last call. In the first call, None 342 must be passed. The last entry of the result list contains a 'scan_stat' 343 attribute. In the next call, pass in the returned 'scan_stat'. 344 @limit: Advisory maximum number of commits to traverse. Sometimes more than @limit 345 commits will be traversed. 346 347 Return a list of DeletedEntry objects (lib/repo.vala). 348 If no more deleted entries can be returned within the given time frame (specified by 349 @show_days) or all deleted entries in the history have been returned, a list with a 350 single entry will be returned. The 'scan_stat' attribute of this entry is set to 351 None. 352 """ 353 return seafserv_threaded_rpc.get_deleted(repo_id, show_days, path, scan_stat, limit) 354 355 def get_file_revisions(self, repo_id, commit_id, path, limit): 356 """ 357 Get revisions of a file. 358 359 @commit_id: start traversing from this commit 360 @limit: maximum number of commits to traverse when looking for revisions 361 362 Return a list of Commit objects (lib/commit.vala) related to the revisions. 363 A few special attributes are added to the commit object: 364 @rev_file_id: id of the file revision 365 @rev_file_size: size of the file revision 366 @rev_renamed_old_path: set if this revision is made by a rename operation. 367 It's set to the old path before rename. 368 @next_start_commit: commit_id for next page. An extra commit which only contains @next_start_commit 369 will be appended to the list. 370 """ 371 return seafserv_threaded_rpc.list_file_revisions(repo_id, commit_id, path, limit) 372 373 # This api is slow and should only be used for version 0 repos. 374 def get_files_last_modified(self, repo_id, parent_dir, limit): 375 """Get last modification time for files in a dir 376 377 limit: the max number of commits to analyze 378 """ 379 return seafserv_threaded_rpc.calc_files_last_modified(repo_id, 380 parent_dir, limit) 381 382 def get_repo_history_limit(self, repo_id): 383 """ 384 Return repo history limit in days. Returns -1 if it's unlimited. 385 """ 386 return seafserv_threaded_rpc.get_repo_history_limit(repo_id) 387 388 def set_repo_history_limit(self, repo_id, days): 389 """ 390 Set repo history limit in days. Pass -1 if set to unlimited. 391 """ 392 return seafserv_threaded_rpc.set_repo_history_limit(repo_id, days) 393 394 def check_repo_blocks_missing(self, repo_id, blklist): 395 return seafserv_threaded_rpc.check_repo_blocks_missing(repo_id, blklist) 396 397 def get_upload_tmp_file_offset (self, repo_id, file_path): 398 return seafserv_threaded_rpc.get_upload_tmp_file_offset (repo_id, file_path) 399 400 # file lock 401 def check_file_lock(self, repo_id, path, user): 402 """ 403 Always return 0 since CE doesn't support file locking. 404 """ 405 return 0 406 407 # share repo to user 408 def share_repo(self, repo_id, from_username, to_username, permission): 409 return seafserv_threaded_rpc.add_share(repo_id, from_username, 410 to_username, permission) 411 412 def remove_share(self, repo_id, from_username, to_username): 413 return seafserv_threaded_rpc.remove_share(repo_id, from_username, 414 to_username) 415 416 def set_share_permission(self, repo_id, from_username, to_username, permission): 417 return seafserv_threaded_rpc.set_share_permission(repo_id, from_username, 418 to_username, permission) 419 420 def share_subdir_to_user(self, repo_id, path, owner, share_user, permission, passwd=''): 421 return seafserv_threaded_rpc.share_subdir_to_user(repo_id, path, owner, 422 share_user, permission, passwd) 423 424 def unshare_subdir_for_user(self, repo_id, path, owner, share_user): 425 return seafserv_threaded_rpc.unshare_subdir_for_user(repo_id, path, owner, 426 share_user) 427 428 def update_share_subdir_perm_for_user(self, repo_id, path, owner, 429 share_user, permission): 430 return seafserv_threaded_rpc.update_share_subdir_perm_for_user(repo_id, path, owner, 431 share_user, permission) 432 433 def get_shared_repo_by_path(self, repo_id, path, shared_to, is_org=False): 434 """ 435 If path is NULL, 'repo_id' represents for the repo we want, 436 otherwise, 'repo_id' represents for the origin repo, return virtual repo 437 """ 438 return seafserv_threaded_rpc.get_shared_repo_by_path(repo_id, path, shared_to, 1 if is_org else 0) 439 440 def get_share_out_repo_list(self, username, start, limit): 441 """ 442 Get repo list shared by this user. 443 Return: a list of Repo objects 444 """ 445 return seafserv_threaded_rpc.list_share_repos(username, "from_email", 446 start, limit) 447 448 def get_share_in_repo_list(self, username, start, limit): 449 """ 450 Get repo list shared to this user. 451 """ 452 return seafserv_threaded_rpc.list_share_repos(username, "to_email", 453 start, limit) 454 455 def list_repo_shared_to(self, from_user, repo_id): 456 """ 457 Get user list this repo is shared to. 458 Return: a list of SharedUser objects (lib/repo.vala) 459 """ 460 return seafserv_threaded_rpc.list_repo_shared_to(from_user, repo_id) 461 462 def repo_has_been_shared(self, repo_id, including_groups=False): 463 return True if seafserv_threaded_rpc.repo_has_been_shared(repo_id, 1 if including_groups else 0) else False 464 465 # share repo to group 466 def group_share_repo(self, repo_id, group_id, username, permission): 467 # deprecated, use ``set_group_repo`` 468 return seafserv_threaded_rpc.group_share_repo(repo_id, group_id, 469 username, permission) 470 471 def set_group_repo(self, repo_id, group_id, username, permission): 472 return seafserv_threaded_rpc.group_share_repo(repo_id, group_id, 473 username, permission) 474 475 def group_unshare_repo(self, repo_id, group_id, username): 476 # deprecated, use ``unset_group_repo`` 477 return seafserv_threaded_rpc.group_unshare_repo(repo_id, group_id, username) 478 479 def unset_group_repo(self, repo_id, group_id, username): 480 return seafserv_threaded_rpc.group_unshare_repo(repo_id, group_id, username) 481 482 def get_shared_group_ids_by_repo(self, repo_id): 483 group_ids = seafserv_threaded_rpc.get_shared_groups_by_repo(repo_id) 484 485 if not group_ids: 486 return [] 487 488 ret = [] 489 for group_id in group_ids.split('\n'): 490 if not group_id: 491 continue 492 ret.append(group_id) 493 return ret 494 495 def list_repo_shared_group(self, from_user, repo_id): 496 # deprecated, use list_repo_shared_group_by_user instead. 497 return seafserv_threaded_rpc.list_repo_shared_group(from_user, repo_id) 498 499 def get_group_shared_repo_by_path (self, repo_id, path, group_id, is_org=False): 500 """ 501 If path is NULL, 'repo_id' represents for the repo we want, 502 otherwise, 'repo_id' represents for the origin repo, return virtual repo 503 """ 504 return seafserv_threaded_rpc.get_group_shared_repo_by_path(repo_id, path, group_id, 1 if is_org else 0) 505 506 def get_group_repos_by_user (self, user): 507 """ 508 Return all the repos in all groups that the @user belongs to. 509 """ 510 return seafserv_threaded_rpc.get_group_repos_by_user(user) 511 512 def get_org_group_repos_by_user (self, user, org_id): 513 return seafserv_threaded_rpc.get_org_group_repos_by_user(user, org_id) 514 515 def list_repo_shared_group_by_user(self, from_user, repo_id): 516 """ 517 Return: a list of SharedGroup objects (lib/repo.vala) 518 """ 519 return seafserv_threaded_rpc.list_repo_shared_group(from_user, repo_id) 520 521 def share_subdir_to_group(self, repo_id, path, owner, share_group, permission, passwd=''): 522 return seafserv_threaded_rpc.share_subdir_to_group(repo_id, path, owner, 523 share_group, permission, passwd) 524 525 def unshare_subdir_for_group(self, repo_id, path, owner, share_group): 526 return seafserv_threaded_rpc.unshare_subdir_for_group(repo_id, path, owner, 527 share_group) 528 529 def update_share_subdir_perm_for_group(self, repo_id, path, owner, 530 share_group, permission): 531 return seafserv_threaded_rpc.update_share_subdir_perm_for_group(repo_id, path, owner, 532 share_group, permission) 533 534 def get_group_repoids(self, group_id): 535 """ 536 Return the list of group repo ids 537 """ 538 repo_ids = seafserv_threaded_rpc.get_group_repoids(group_id) 539 if not repo_ids: 540 return [] 541 l = [] 542 for repo_id in repo_ids.split("\n"): 543 if repo_id == '': 544 continue 545 l.append(repo_id) 546 return l 547 548 def get_group_repo_list(self, group_id): 549 # deprecated, use get_repos_by_group instead. 550 ret = [] 551 for repo_id in self.get_group_repoids(group_id): 552 r = self.get_repo(repo_id) 553 if r is None: 554 continue 555 ret.append(r) 556 return ret 557 558 def get_repos_by_group(self, group_id): 559 """ 560 Return: a list of Repo objects 561 """ 562 return seafserv_threaded_rpc.get_repos_by_group(group_id) 563 564 def get_group_repos_by_owner(self, username): 565 """ 566 Get all repos a user share to any group 567 Return: a list of Repo objects 568 """ 569 return seafserv_threaded_rpc.get_group_repos_by_owner(username) 570 571 def remove_group_repos_by_owner(self, group_id, username): 572 """ 573 Unshare all repos a user shared to a group. 574 """ 575 return seafserv_threaded_rpc.remove_repo_group(group_id, username) 576 577 def remove_group_repos(self, group_id): 578 """ 579 Remove all repos under group. 580 Return: 0 success; -1 failed 581 """ 582 return seafserv_threaded_rpc.remove_repo_group(group_id, None) 583 584 def set_group_repo_permission(self, group_id, repo_id, permission): 585 return seafserv_threaded_rpc.set_group_repo_permission(group_id, repo_id, 586 permission) 587 588 def get_shared_users_for_subdir(self, repo_id, path, from_user): 589 """ 590 Get all users a path is shared to. 591 Return: a list of SharedUser objects. 592 """ 593 return seafserv_threaded_rpc.get_shared_users_for_subdir(repo_id, path, from_user) 594 595 def get_shared_groups_for_subdir(self, repo_id, path, from_user): 596 """ 597 Get all groups a path is shared to. 598 Return: a list of SharedGroup objects. 599 """ 600 return seafserv_threaded_rpc.get_shared_groups_for_subdir(repo_id, path, from_user) 601 602 def get_shared_users_by_repo(self, repo_id): 603 users = [] 604 # get users that the repo is shared to 605 shared_users = seafserv_threaded_rpc.get_shared_users_by_repo (repo_id) 606 for user in shared_users: 607 users.append(user.user) 608 609 # get users in groups that the repo is shared to 610 group_ids = seafserv_threaded_rpc.get_shared_groups_by_repo(repo_id) 611 if not group_ids: 612 return users 613 614 ids = [] 615 for group_id in group_ids.split('\n'): 616 if not group_id: 617 continue 618 ids.append(int(group_id)) 619 620 json_ids = json.dumps(ids) 621 group_users = ccnet_threaded_rpc.get_groups_members(json_ids) 622 623 for user in group_users: 624 if user.user_name not in users: 625 users.append(user.user_name) 626 627 return users 628 629 # organization wide repo 630 def add_inner_pub_repo(self, repo_id, permission): 631 return seafserv_threaded_rpc.set_inner_pub_repo(repo_id, permission) 632 633 def remove_inner_pub_repo(self, repo_id): 634 return seafserv_threaded_rpc.unset_inner_pub_repo(repo_id) 635 636 def get_inner_pub_repo_list(self): 637 """ 638 Return: a list of Repo objects. 639 """ 640 return seafserv_threaded_rpc.list_inner_pub_repos() 641 642 def list_inner_pub_repos_by_owner(self, repo_owner): 643 """ 644 Return: a list of Repo objects. 645 """ 646 return seafserv_threaded_rpc.list_inner_pub_repos_by_owner(repo_owner) 647 648 def count_inner_pub_repos(self): 649 return seafserv_threaded_rpc.count_inner_pub_repos() 650 651 def is_inner_pub_repo(self, repo_id): 652 return seafserv_threaded_rpc.is_inner_pub_repo(repo_id) 653 654 # permission checks 655 def check_permission(self, repo_id, user): 656 """ 657 Check repo share permissions. Only check user share, group share and inner-pub 658 shares. 659 Return: 'r', 'rw', or None 660 """ 661 return seafserv_threaded_rpc.check_permission(repo_id, user) 662 663 def check_permission_by_path(self, repo_id, path, user): 664 """ 665 Check both repo share permission and sub-folder access permissions. 666 This function should be used when updating file/folder in a repo. 667 In CE, this function is equivalent to check_permission. 668 Return: 'r', 'rw', or None 669 """ 670 return seafserv_threaded_rpc.check_permission_by_path(repo_id, path, user) 671 672 def is_repo_syncable(self, repo_id, user, repo_perm): 673 """ 674 Check if the permission of the repo is syncable. 675 """ 676 return '{"is_syncable":true}' 677 678 def is_dir_downloadable(self, repo_id, dir_path, user, repo_perm): 679 """ 680 Check if the permission of the dir is downloadable. 681 {"is_downloadable": false, "undownloadable_path":"path"} 682 - is_downloadable: true if the dir is downloadable, false if not. 683 - undownloadable_path: the undownloadable path of the repo if the path is not downloadable. 684 """ 685 return '{"is_downloadable":true}' 686 687 # token 688 def generate_repo_token(self, repo_id, username): 689 """Generate a token for sync a repo 690 """ 691 return seafserv_threaded_rpc.generate_repo_token(repo_id, username) 692 693 def delete_repo_token(self, repo_id, token, user): 694 return seafserv_threaded_rpc.delete_repo_token(repo_id, token, user) 695 696 def list_repo_tokens(self, repo_id): 697 """ 698 Return: a list of RepoTokenInfo objects. 699 """ 700 return seafserv_threaded_rpc.list_repo_tokens(repo_id) 701 702 def list_repo_tokens_by_email(self, username): 703 return seafserv_threaded_rpc.list_repo_tokens_by_email(username) 704 705 def delete_repo_tokens_by_peer_id(self, email, peer_id): 706 return seafserv_threaded_rpc.delete_repo_tokens_by_peer_id(email, peer_id) 707 708 def delete_repo_tokens_by_email(self, email): 709 return seafserv_threaded_rpc.delete_repo_tokens_by_email(email) 710 711 # quota 712 def get_user_self_usage(self, username): 713 """Get the sum of repos' size of the user""" 714 return seafserv_threaded_rpc.get_user_quota_usage(username) 715 716 def get_user_share_usage(self, username): 717 # sum (repo_size * number_of_shares) 718 return seafserv_threaded_rpc.get_user_share_usage(username) 719 720 def get_user_quota(self, username): 721 """ 722 Return: -2 if quota is unlimited; otherwise it must be number > 0. 723 """ 724 return seafserv_threaded_rpc.get_user_quota(username) 725 726 def set_user_quota(self, username, quota): 727 return seafserv_threaded_rpc.set_user_quota(username, quota) 728 729 def get_user_share_quota(self, username): 730 return -2 # unlimited 731 732 def set_user_share_quota(self, username, quota): 733 pass 734 735 def check_quota(self, repo_id, delta=0): 736 return seafserv_threaded_rpc.check_quota(repo_id, delta) 737 738 def list_user_quota_usage(self): 739 return seafserv_threaded_rpc.list_user_quota_usage() 740 741 # virtual repo 742 def create_virtual_repo(self, origin_repo_id, path, repo_name, repo_desc, owner, passwd=''): 743 return seafserv_threaded_rpc.create_virtual_repo(origin_repo_id, 744 path, 745 repo_name, 746 repo_desc, 747 owner, 748 passwd) 749 750 def get_virtual_repos_by_owner(self, owner): 751 return seafserv_threaded_rpc.get_virtual_repos_by_owner(owner) 752 753 def get_virtual_repo(self, origin_repo, path, owner): 754 return seafserv_threaded_rpc.get_virtual_repo(origin_repo, path, owner) 755 756 # Clean trash 757 758 def clean_up_repo_history(self, repo_id, keep_days): 759 return seafserv_threaded_rpc.clean_up_repo_history(repo_id, keep_days) 760 761 # Trashed repos 762 def get_trash_repo_list(self, start, limit): 763 return seafserv_threaded_rpc.get_trash_repo_list(start, limit) 764 765 def del_repo_from_trash(self, repo_id): 766 return seafserv_threaded_rpc.del_repo_from_trash(repo_id) 767 768 def restore_repo_from_trash(self, repo_id): 769 return seafserv_threaded_rpc.restore_repo_from_trash(repo_id) 770 771 def get_trash_repos_by_owner(self, owner): 772 return seafserv_threaded_rpc.get_trash_repos_by_owner(owner) 773 774 def get_trash_repo_owner (self, repo_id): 775 return seafserv_threaded_rpc.get_trash_repo_owner(repo_id) 776 777 def empty_repo_trash(self): 778 return seafserv_threaded_rpc.empty_repo_trash() 779 780 def empty_repo_trash_by_owner(self, owner): 781 return seafserv_threaded_rpc.empty_repo_trash_by_owner(owner) 782 783 # Server config 784 def get_server_config_int (self, group, key): 785 return seafserv_threaded_rpc.get_server_config_int (group, key) 786 787 def set_server_config_int (self, group, key, value): 788 return seafserv_threaded_rpc.set_server_config_int (group, key, value) 789 790 def get_server_config_int64 (self, group, key): 791 return seafserv_threaded_rpc.get_server_config_int64 (group, key) 792 793 def set_server_config_int64 (self, group, key, value): 794 return seafserv_threaded_rpc.set_server_config_int64 (group, key, value) 795 796 def get_server_config_string (self, group, key): 797 return seafserv_threaded_rpc.get_server_config_string (group, key) 798 799 def set_server_config_string (self, group, key, value): 800 return seafserv_threaded_rpc.set_server_config_string (group, key, value) 801 802 def get_server_config_boolean (self, group, key): 803 return bool(seafserv_threaded_rpc.get_server_config_boolean (group, key)) 804 805 def set_server_config_boolean (self, group, key, value): 806 i_value = 1 if bool(value) else 0 807 return seafserv_threaded_rpc.set_server_config_boolean (group, key, i_value) 808 809 def del_org_group_repo(self, repo_id, org_id, group_id): 810 seafserv_threaded_rpc.del_org_group_repo(repo_id, org_id, group_id) 811 812 def org_get_shared_users_by_repo(self, org_id, repo_id): 813 users = [] 814 # get users that the repo is shared to 815 shared_users = seafserv_threaded_rpc.org_get_shared_users_by_repo(org_id, repo_id) 816 for user in shared_users: 817 users.append(user.user) 818 819 # get users in groups that the repo is shared to 820 group_ids = seafserv_threaded_rpc.get_org_groups_by_repo(org_id, repo_id) 821 if not group_ids: 822 return users 823 824 ids = [] 825 for group_id in group_ids.split('\n'): 826 if not group_id: 827 continue 828 ids.append(int(group_id)) 829 830 json_ids = json.dumps(ids) 831 group_users = ccnet_threaded_rpc.get_groups_members(json_ids) 832 833 for user in group_users: 834 if user.user_name not in users: 835 users.append(user.user_name) 836 837 return users 838 839 def list_org_inner_pub_repos(self, org_id): 840 return seafserv_threaded_rpc.list_org_inner_pub_repos(org_id) 841 842 def convert_repo_path(self, repo_id, path, user, is_org=False): 843 return seafserv_threaded_rpc.convert_repo_path(repo_id, path, user, 1 if is_org else 0) 844 845 def publish_event(self, channel, content): 846 return seafserv_threaded_rpc.publish_event(channel, content) 847 848 def pop_event(self, channel): 849 return seafserv_threaded_rpc.pop_event(channel) 850 851 def search_files(self, repo_id, search_str): 852 return seafserv_threaded_rpc.search_files(repo_id, search_str) 853 854seafile_api = SeafileAPI() 855 856class CcnetAPI(object): 857 858 def __init__(self): 859 pass 860 861 # user management 862 def add_emailuser(self, email, passwd, is_staff, is_active): 863 return ccnet_threaded_rpc.add_emailuser(email, passwd, is_staff, is_active) 864 865 def remove_emailuser(self, source, email): 866 """ 867 source can be 'DB' or 'LDAP'. 868 - 'DB': remove a user created in local database 869 - 'LDAP': remove a user imported from LDAP 870 """ 871 return ccnet_threaded_rpc.remove_emailuser(source, email) 872 873 def validate_emailuser(self, email, passwd): 874 """ 875 Verify user's password on login. Can be used to verify DB and LDAP users. 876 The function first verify password with LDAP, then local database. 877 """ 878 return ccnet_threaded_rpc.validate_emailuser(email, passwd) 879 880 def get_emailuser(self, email): 881 """ 882 Only return local database user or imported LDAP user. 883 It first lookup user from local database, if not found, lookup imported 884 LDAP user. 885 Return: a list of EmailUser objects (ccnet/lib/ccnetobj.vala) 886 The 'source' attribute of EmailUser object is set to 'LDAPImport' for LDAP 887 imported user, and 'DB' for local database user. 888 """ 889 return ccnet_threaded_rpc.get_emailuser(email) 890 891 def get_emailuser_with_import(self, email): 892 """ 893 The same as get_emailuser() but import the user from LDAP if it was not 894 imported yet. 895 """ 896 return ccnet_threaded_rpc.get_emailuser_with_import(email) 897 898 def get_emailuser_by_id(self, user_id): 899 """ 900 Get a user from local database with the db index id. 901 """ 902 return ccnet_threaded_rpc.get_emailuser_by_id(user_id) 903 904 def get_emailusers(self, source, start, limit, is_active=None): 905 """ 906 source: 907 - 'DB': return local db users 908 - 'LDAPImport': return imported LDAP users 909 - 'LDAP': retrieve users directly from LDAP server 910 start: offset to start retrieving, -1 to start from the beginning 911 limit: number of users to get, -1 to get all user from start 912 is_active: True to return only active users; False to return inactive users; 913 None to return all users. 914 Return: a list of EmailUser objects. 915 """ 916 if is_active is True: 917 status = "active" # list active users 918 elif is_active is False: 919 status = "inactive" # list inactive users 920 else: 921 status = "" # list all users 922 923 return ccnet_threaded_rpc.get_emailusers(source, start, limit, status) 924 925 def search_emailusers(self, source, email_patt, start, limit): 926 """ 927 Search for users whose name contains @email_patt. 928 source: 'DB' for local db users; 'LDAP' for imported LDAP users. 929 This function cannot search LDAP users directly in LDAP server. 930 """ 931 return ccnet_threaded_rpc.search_emailusers(source, email_patt, start, limit) 932 933 def search_groups(self, group_patt, start, limit): 934 """ 935 Search for groups whose name contains @group_patt. 936 """ 937 return ccnet_threaded_rpc.search_groups(group_patt, start, limit) 938 939 def get_top_groups(self, including_org=False): 940 return ccnet_threaded_rpc.get_top_groups(1 if including_org else 0) 941 942 def get_child_groups(self, group_id): 943 return ccnet_threaded_rpc.get_child_groups(group_id) 944 945 def get_descendants_groups(self, group_id): 946 return ccnet_threaded_rpc.get_descendants_groups(group_id) 947 948 def get_ancestor_groups(self, group_id): 949 return ccnet_threaded_rpc.get_ancestor_groups(group_id) 950 951 def search_ldapusers(self, keyword, start, limit): 952 """ 953 Search for users whose name contains @keyword directly from LDAP server. 954 """ 955 return ccnet_threaded_rpc.search_ldapusers(keyword, start, limit) 956 957 def count_emailusers(self, source): 958 """ 959 Return the number of active users by source. 960 source: 'DB' for local db users; 'LDAP' for imported LDAP users. 961 """ 962 return ccnet_threaded_rpc.count_emailusers(source) 963 964 def count_inactive_emailusers(self, source): 965 """ 966 Return the number of inactive users by source. 967 source: 'DB' for local db users; 'LDAP' for imported LDAP users. 968 """ 969 return ccnet_threaded_rpc.count_inactive_emailusers(source) 970 971 def update_emailuser(self, source, user_id, password, is_staff, is_active): 972 """ 973 source: 'DB' for local db user; 'LDAP' for imported LDAP user. 974 user_id: usually not changed. 975 password: new password in plain text. Only effective for DB users. 976 If '!' is passed, the password won't be updated. 977 is_staff: change superuser status 978 is_active: activate or deactivate user 979 """ 980 return ccnet_threaded_rpc.update_emailuser(source, user_id, password, is_staff, is_active) 981 982 def update_role_emailuser(self, email, role): 983 return ccnet_threaded_rpc.update_role_emailuser(email, role) 984 985 def get_superusers(self): 986 """ 987 Return: a list of EmailUser objects. 988 """ 989 return ccnet_threaded_rpc.get_superusers() 990 991 def get_emailusers_in_list(self, source, user_list): 992 """ 993 @source: 'DB' or 'LDAP' 994 @user_list: json '[user1, user2, user3,...]' 995 """ 996 return ccnet_threaded_rpc.get_emailusers_in_list(source, user_list) 997 998 def update_emailuser_id (self, old_email, new_email): 999 return ccnet_threaded_rpc.update_emailuser_id (old_email, new_email) 1000 1001 # group management 1002 def create_group(self, group_name, user_name, gtype=None, parent_group_id=0): 1003 """ 1004 For CE, gtype is not used and should always be None. 1005 """ 1006 return ccnet_threaded_rpc.create_group(group_name, user_name, gtype, parent_group_id) 1007 1008 def create_org_group(self, org_id, group_name, user_name, parent_group_id=0): 1009 return ccnet_threaded_rpc.create_org_group(org_id, group_name, user_name, parent_group_id) 1010 1011 def remove_group(self, group_id): 1012 """ 1013 permission check should be done before calling this function. 1014 """ 1015 return ccnet_threaded_rpc.remove_group(group_id) 1016 1017 def group_add_member(self, group_id, user_name, member_name): 1018 """ 1019 user_name: unused. 1020 """ 1021 return ccnet_threaded_rpc.group_add_member(group_id, user_name, member_name) 1022 1023 def group_remove_member(self, group_id, user_name, member_name): 1024 """ 1025 user_name: unused. 1026 """ 1027 return ccnet_threaded_rpc.group_remove_member(group_id, user_name, member_name) 1028 1029 def group_set_admin(self, group_id, member_name): 1030 """ 1031 No effect if member_name is not in the group. 1032 """ 1033 return ccnet_threaded_rpc.group_set_admin(group_id, member_name) 1034 1035 def group_unset_admin(self, group_id, member_name): 1036 """ 1037 No effect if member_name is not in the group. 1038 """ 1039 return ccnet_threaded_rpc.group_unset_admin(group_id, member_name) 1040 1041 def set_group_name(self, group_id, group_name): 1042 return ccnet_threaded_rpc.set_group_name(group_id, group_name) 1043 1044 def quit_group(self, group_id, user_name): 1045 return ccnet_threaded_rpc.quit_group(group_id, user_name) 1046 1047 def get_groups(self, user_name, return_ancestors=False): 1048 """ 1049 Get all groups the user belongs to. 1050 Return: a list of Group objects (ccnet/lib/ccnetobj.vala) 1051 """ 1052 return ccnet_threaded_rpc.get_groups(user_name, 1 if return_ancestors else 0) 1053 1054 def get_all_groups(self, start, limit, source=None): 1055 """ 1056 For CE, source is not used and should alwasys be None. 1057 """ 1058 return ccnet_threaded_rpc.get_all_groups(start, limit, source) 1059 1060 def get_group(self, group_id): 1061 return ccnet_threaded_rpc.get_group(group_id) 1062 1063 def get_group_members(self, group_id, start=-1, limit=-1): 1064 """ 1065 Return a list of GroupUser objects (ccnet/lib/ccnetobj.vala) 1066 """ 1067 return ccnet_threaded_rpc.get_group_members(group_id, start, limit) 1068 1069 def get_members_with_prefix (self, group_id, prefix=None): 1070 """ 1071 Return a list of GroupUser objects 1072 """ 1073 return ccnet_threaded_rpc.get_members_with_prefix(group_id, prefix) 1074 1075 def check_group_staff(self, group_id, username, in_structure=False): 1076 """ 1077 Return non-zero value if true, 0 if not true 1078 """ 1079 return ccnet_threaded_rpc.check_group_staff(group_id, username, 1 if in_structure else 0) 1080 1081 def remove_group_user(self, username): 1082 return ccnet_threaded_rpc.remove_group_user(username) 1083 1084 def is_group_user(self, group_id, user, in_structure=True): 1085 """ 1086 Return non-zero value if true, 0 if not true 1087 If @in_structure is true, return whether user is in descendants groups and @group_id it self 1088 """ 1089 return ccnet_threaded_rpc.is_group_user(group_id, user, 1 if in_structure else 0) 1090 1091 def set_group_creator(self, group_id, user_name): 1092 return ccnet_threaded_rpc.set_group_creator(group_id, user_name) 1093 1094 # organization management 1095 def create_org(self, org_name, url_prefix, creator): 1096 return ccnet_threaded_rpc.create_org(org_name, url_prefix, creator) 1097 1098 def remove_org(self, org_id): 1099 return ccnet_threaded_rpc.remove_org(org_id) 1100 1101 def get_all_orgs(self, start, limit): 1102 """ 1103 Return a list of Organization objects (ccnet/lib/ccnetobj.vala) 1104 """ 1105 return ccnet_threaded_rpc.get_all_orgs(start, limit) 1106 1107 def count_orgs(self): 1108 return ccnet_threaded_rpc.count_orgs() 1109 1110 def get_org_by_url_prefix(self, url_prefix): 1111 """ 1112 Return an Organizaion object. 1113 """ 1114 return ccnet_threaded_rpc.get_org_by_url_prefix(url_prefix) 1115 1116 def get_org_by_id(self, org_id): 1117 return ccnet_threaded_rpc.get_org_by_id(org_id) 1118 1119 def add_org_user(self, org_id, email, is_staff): 1120 return ccnet_threaded_rpc.add_org_user(org_id, email, is_staff) 1121 1122 def remove_org_user(self, org_id, email): 1123 return ccnet_threaded_rpc.remove_org_user(org_id, email) 1124 1125 def get_orgs_by_user(self, email): 1126 return ccnet_threaded_rpc.get_orgs_by_user(email) 1127 1128 def get_org_emailusers(self, url_prefix, start, limit): 1129 """ 1130 Return a list of EmailUser objects. 1131 """ 1132 return ccnet_threaded_rpc.get_org_emailusers(url_prefix, start, limit) 1133 1134 def add_org_group(self, org_id, group_id): 1135 return ccnet_threaded_rpc.add_org_group(org_id, group_id) 1136 1137 def remove_org_group(self, org_id, group_id): 1138 return ccnet_threaded_rpc.remove_org_group(org_id, group_id) 1139 1140 def is_org_group(self, group_id): 1141 """ 1142 Return non-zero if True, otherwise 0. 1143 """ 1144 return ccnet_threaded_rpc.is_org_group(group_id) 1145 1146 def get_org_id_by_group(self, group_id): 1147 return ccnet_threaded_rpc.get_org_id_by_group(group_id) 1148 1149 def get_org_groups(self, org_id, start, limit): 1150 """ 1151 Return a list of int, each int is group id. 1152 """ 1153 return ccnet_threaded_rpc.get_org_groups(org_id, start, limit) 1154 1155 def get_org_top_groups(self, org_id): 1156 return ccnet_threaded_rpc.get_org_top_groups(org_id) 1157 1158 def org_user_exists(self, org_id, email): 1159 """ 1160 Return non-zero if True, otherwise 0. 1161 """ 1162 return ccnet_threaded_rpc.org_user_exists(org_id, email) 1163 1164 def is_org_staff(self, org_id, user): 1165 """ 1166 Return non-zero if True, otherwise 0. 1167 """ 1168 return ccnet_threaded_rpc.is_org_staff(org_id, user) 1169 1170 def set_org_staff(self, org_id, user): 1171 return ccnet_threaded_rpc.set_org_staff(org_id, user) 1172 1173 def unset_org_staff(self, org_id, user): 1174 return ccnet_threaded_rpc.unset_org_staff(org_id, user) 1175 1176 def set_org_name(self, org_id, org_name): 1177 return ccnet_threaded_rpc.set_org_name(org_id, org_name) 1178 1179 def get_primary_id (self, email): 1180 return ccnet_threaded_rpc.get_primary_id(email) 1181 1182 def set_reference_id (self, primary_id, reference_id): 1183 return ccnet_threaded_rpc.set_reference_id(primary_id, reference_id) 1184 1185 def get_groups_members(self, group_ids): 1186 """ 1187 @group_ids: json '[id1, id2, id3,...]' 1188 """ 1189 return ccnet_threaded_rpc.get_groups_members(group_ids) 1190 1191ccnet_api = CcnetAPI() 1192