def get_group_info(group_id, show_size=False): group = ccnet_api.get_group(group_id) isoformat_timestr = timestamp_to_isoformat_timestr(group.timestamp) group_info = { "id": group.id, "name": group.group_name, "owner": group.creator_name, "owner_name": email2nickname(group.creator_name), "created_at": isoformat_timestr, "quota": seafile_api.get_group_quota(group_id) if is_pro_version() else 0, "parent_group_id": group.parent_group_id if is_pro_version() else 0 } if ccnet_api.is_org_group(group_id): org_id = ccnet_api.get_org_id_by_group(group_id) group_info['org_id'] = org_id if org_id: org = ccnet_api.get_org_by_id(org_id) if org: group_info['org_name'] = org.org_name if show_size: owner = '%s@seafile_group' % group_id workspace = Workspaces.objects.get_workspace_by_owner(owner) if workspace: repo = seafile_api.get_repo(workspace.repo_id) group_info['size'] = repo.size return group_info
def get_group_info(group_id): group = ccnet_api.get_group(group_id) isoformat_timestr = timestamp_to_isoformat_timestr(group.timestamp) group_info = { "id": group.id, "name": group.group_name, "owner": group.creator_name, "owner_name": email2nickname(group.creator_name), "created_at": isoformat_timestr, "quota": seafile_api.get_group_quota(group_id) if is_pro_version() else 0, "parent_group_id": group.parent_group_id if is_pro_version() else 0 } return group_info
def libraries(request): """ New URL to replace myhome """ username = request.user.username # options if request.cloud_mode and request.user.org is None: allow_public_share = False else: allow_public_share = True sub_lib_enabled = UserOptions.objects.is_sub_lib_enabled(username) max_upload_file_size = get_max_upload_file_size() guide_enabled = UserOptions.objects.is_user_guide_enabled(username) if guide_enabled: create_default_library(request) folder_perm_enabled = True if is_pro_version() and ENABLE_FOLDER_PERM else False can_add_pub_repo = True if is_org_repo_creation_allowed(request) else False if request.cloud_mode and request.user.org is not None: org_id = request.user.org.org_id joined_groups = seaserv.get_org_groups_by_user(org_id, username) else: joined_groups = seaserv.get_personal_groups_by_user(username) if joined_groups: joined_groups.sort(lambda x, y: cmp(x.group_name.lower(), y.group_name.lower())) return render_to_response('libraries.html', { "allow_public_share": allow_public_share, "guide_enabled": guide_enabled, "sub_lib_enabled": sub_lib_enabled, 'enable_upload_folder': settings.ENABLE_UPLOAD_FOLDER, 'enable_resumable_fileupload': settings.ENABLE_RESUMABLE_FILEUPLOAD, 'max_number_of_files_for_fileupload': settings.MAX_NUMBER_OF_FILES_FOR_FILEUPLOAD, 'enable_thumbnail': settings.ENABLE_THUMBNAIL, 'thumbnail_default_size': settings.THUMBNAIL_DEFAULT_SIZE, 'thumbnail_size_for_grid': settings.THUMBNAIL_SIZE_FOR_GRID, 'enable_encrypted_library': config.ENABLE_ENCRYPTED_LIBRARY, 'enable_repo_history_setting': config.ENABLE_REPO_HISTORY_SETTING, 'max_upload_file_size': max_upload_file_size, 'folder_perm_enabled': folder_perm_enabled, 'is_pro': True if is_pro_version() else False, 'file_audit_enabled': FILE_AUDIT_ENABLED, 'can_add_pub_repo': can_add_pub_repo, 'joined_groups': joined_groups, 'library_templates': LIBRARY_TEMPLATES.keys() if \ isinstance(LIBRARY_TEMPLATES, dict) else [] }, context_instance=RequestContext(request))
def libraries(request): """ New URL to replace myhome """ username = request.user.username # options if request.cloud_mode and request.user.org is None: allow_public_share = False else: allow_public_share = True sub_lib_enabled = UserOptions.objects.is_sub_lib_enabled(username) max_upload_file_size = get_max_upload_file_size() guide_enabled = UserOptions.objects.is_user_guide_enabled(username) if guide_enabled: create_default_library(request) folder_perm_enabled = True if is_pro_version( ) and ENABLE_FOLDER_PERM else False can_add_pub_repo = True if is_org_repo_creation_allowed(request) else False if request.cloud_mode and request.user.org is not None: org_id = request.user.org.org_id joined_groups = seaserv.get_org_groups_by_user(org_id, username) else: joined_groups = seaserv.get_personal_groups_by_user(username) if joined_groups: joined_groups.sort( lambda x, y: cmp(x.group_name.lower(), y.group_name.lower())) return render_to_response('libraries.html', { "allow_public_share": allow_public_share, "guide_enabled": guide_enabled, "sub_lib_enabled": sub_lib_enabled, 'enable_upload_folder': settings.ENABLE_UPLOAD_FOLDER, 'enable_resumable_fileupload': settings.ENABLE_RESUMABLE_FILEUPLOAD, 'enable_thumbnail': settings.ENABLE_THUMBNAIL, 'thumbnail_default_size': settings.THUMBNAIL_DEFAULT_SIZE, 'thumbnail_size_for_grid': settings.THUMBNAIL_SIZE_FOR_GRID, 'enable_encrypted_library': config.ENABLE_ENCRYPTED_LIBRARY, 'enable_repo_history_setting': config.ENABLE_REPO_HISTORY_SETTING, 'max_upload_file_size': max_upload_file_size, 'folder_perm_enabled': folder_perm_enabled, 'is_pro': True if is_pro_version() else False, 'file_audit_enabled': FILE_AUDIT_ENABLED, 'can_add_pub_repo': can_add_pub_repo, 'joined_groups': joined_groups, }, context_instance=RequestContext(request))
def get_group_info(group_id): group = ccnet_api.get_group(group_id) isoformat_timestr = timestamp_to_isoformat_timestr(group.timestamp) group_info = { "id": group.id, "name": group.group_name, "owner": group.creator_name, "created_at": isoformat_timestr, "quota": seafile_api.get_group_quota(group_id) if is_pro_version() else 0, "parent_group_id": group.parent_group_id if is_pro_version() else 0 } return group_info
def user_number_over_limit(new_users=0): logger = logging.getLogger(__name__) if is_pro_version(): try: # get license user limit license_dict = parse_license() max_users = int(license_dict.get('MaxUsers', 3)) # get active user number active_db_users = ccnet_api.count_emailusers('DB') active_ldap_users = ccnet_api.count_emailusers('LDAP') active_users = active_db_users + active_ldap_users if \ active_ldap_users > 0 else active_db_users if new_users < 0: logger.debug('`new_users` must be greater or equal to 0.') return False elif new_users == 0: return active_users >= max_users else: return active_users + new_users > max_users except Exception as e: logger.error(e) return False else: return False
def get_group_info(request, group_id, avatar_size=GROUP_AVATAR_DEFAULT_SIZE): group = ccnet_api.get_group(group_id) try: avatar_url, is_default, date_uploaded = api_grp_avatar_url(group.id, avatar_size) except Exception as e: logger.error(e) avatar_url = get_default_group_avatar_url() isoformat_timestr = timestamp_to_isoformat_timestr(group.timestamp) group_info = { "id": group.id, "parent_group_id": group.parent_group_id, "name": group.group_name, "owner": group.creator_name, "created_at": isoformat_timestr, "avatar_url": request.build_absolute_uri(avatar_url), "admins": get_group_admins(group.id), } # parent_group_id = 0: non department group # parent_group_id = -1: top department group # parent_group_id = n(n > 0): sub department group, n is parent group's id if group.parent_group_id != 0: group_info['group_quota'] = seafile_api.get_group_quota(group_id) group_info['group_quota_usage'] = '' if is_pro_version(): if is_org_context(request): org_id = request.user.org.org_id group_info['group_quota_usage'] = seafile_api.org_get_group_quota_usage(org_id, group_id) else: group_info['group_quota_usage'] = seafile_api.get_group_quota_usage(group_id) return group_info
def get(self, request): if not is_pro_version(): error_msg = 'Feature disabled.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # check the date format, should be like '2015-10-10' start = request.GET.get('start', None) end = request.GET.get('end', None) if not check_time_period_valid(start, end): error_msg = 'start or end date invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) result = [] events = get_log_events_by_type_and_time('file_update', start, end) if events: for ev in events: tmp_repo = seafile_api.get_repo(ev.repo_id) tmp_repo_name = tmp_repo.name if tmp_repo else '' result.append({ 'commit_id': ev.commit_id, 'repo_id': ev.repo_id, 'repo_name': tmp_repo_name, 'time': datetime_to_isoformat_timestr(ev.timestamp), 'file_operation': ev.file_oper, 'user_name': email2nickname(ev.user), 'user_email': ev.user }) return Response(result)
def get(self, request, format=None): info = { 'version': settings.SEAFILE_VERSION, 'encrypted_library_version': settings.ENCRYPTED_LIBRARY_VERSION if settings.ENCRYPTED_LIBRARY_VERSION >= 3 else 2, } features = ['seafile-basic'] if is_pro_version(): features.append('seafile-pro') if HAS_OFFICE_CONVERTER: features.append('office-preview') if HAS_FILE_SEARCH: features.append('file-search') if config.DISABLE_SYNC_WITH_ANY_FOLDER: features.append('disable-sync-with-any-folder') if hasattr(settings, 'DESKTOP_CUSTOM_LOGO'): info['desktop-custom-logo'] = settings.MEDIA_URL + getattr( settings, 'DESKTOP_CUSTOM_LOGO') if hasattr(settings, 'DESKTOP_CUSTOM_BRAND'): info['desktop-custom-brand'] = getattr(settings, 'DESKTOP_CUSTOM_BRAND') info['features'] = features return info
def populate_user_permissions(user): if is_pro_version(): from seahub_extra.auth_extra.utils import populate_user_permissions populate_user_permissions(user) else: # use default user permissions pass
def sysadmin_react_fake_view(request, **kwargs): try: expire_days = seafile_api.get_server_config_int('library_trash', 'expire_days') except Exception as e: logger.error(e) expire_days = -1 multi_institution = getattr(dj_settings, 'MULTI_INSTITUTION', False) institutions = None if multi_institution: institutions = [inst.name for inst in Institution.objects.all()] return render(request, 'sysadmin/sysadmin_react_app.html', { 'constance_enabled': dj_settings.CONSTANCE_ENABLED, 'multi_tenancy': MULTI_TENANCY, 'multi_institution': multi_institution, 'institutions': institutions, 'send_email_on_adding_system_member': SEND_EMAIL_ON_ADDING_SYSTEM_MEMBER, 'sysadmin_extra_enabled': True if is_pro_version() else False, 'enable_guest_invitation': ENABLE_GUEST_INVITATION, 'enable_terms_and_conditions': config.ENABLE_TERMS_AND_CONDITIONS, 'enable_file_scan': ENABLE_FILE_SCAN, 'enable_work_weixin': ENABLE_WORK_WEIXIN, 'enable_dingtalk': ENABLE_DINGTALK, 'enable_sys_admin_view_repo': ENABLE_SYS_ADMIN_VIEW_REPO, 'trash_repos_expire_days': expire_days if expire_days > 0 else 30, 'available_roles': get_available_roles(), 'available_admin_roles': get_available_admin_roles(), 'have_ldap': get_ldap_info(), 'two_factor_auth_enabled': has_two_factor_auth(), 'enable_share_link_report_abuse': ENABLE_SHARE_LINK_REPORT_ABUSE, })
def react_fake_view(request, **kwargs): folder_perm_enabled = True if is_pro_version( ) and ENABLE_FOLDER_PERM else False return render( request, "react_app.html", { 'seafile_collab_server': SEAFILE_COLLAB_SERVER, 'storages': get_library_storages(request), 'enable_repo_snapshot_label': settings.ENABLE_REPO_SNAPSHOT_LABEL, 'resumable_upload_file_block_size': settings.RESUMABLE_UPLOAD_FILE_BLOCK_SIZE, 'share_link_expire_days_default': settings.SHARE_LINK_EXPIRE_DAYS_DEFAULT, 'share_link_expire_days_min': SHARE_LINK_EXPIRE_DAYS_MIN, 'share_link_expire_days_max': SHARE_LINK_EXPIRE_DAYS_MAX, 'enable_encrypted_library': config.ENABLE_ENCRYPTED_LIBRARY, 'enable_repo_history_setting': config.ENABLE_REPO_HISTORY_SETTING, 'enable_reset_encrypted_repo_password': ENABLE_RESET_ENCRYPTED_REPO_PASSWORD, 'enableFileComment': settings.ENABLE_FILE_COMMENT, 'is_email_configured': IS_EMAIL_CONFIGURED, 'can_add_public_repo': request.user.permissions.can_add_public_repo(), 'folder_perm_enabled': folder_perm_enabled, 'file_audit_enabled': FILE_AUDIT_ENABLED })
def get(self, request): if not is_pro_version(): error_msg = 'Feature disabled.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # check the date format, should be like '2015-10-10' start = request.GET.get('start', None) end = request.GET.get('end', None) if not check_time_period_valid(start, end): error_msg = 'start or end date invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) result = [] events = get_log_events_by_type_and_time('file_audit', start, end) if events: for ev in events: tmp_repo = seafile_api.get_repo(ev.repo_id) tmp_repo_name = tmp_repo.name if tmp_repo else '' result.append({ 'repo_id': ev.repo_id, 'repo_name': tmp_repo_name, 'time': datetime_to_isoformat_timestr(ev.timestamp), 'etype': ev.etype, 'ip': ev.ip, 'file_path': ev.file_path, 'etype': ev.etype, 'user_name': email2nickname(ev.user), 'user_email': ev.user }) return Response(result)
def check_file_lock(repo_id, file_path, username): """ Check if file is locked to current user According to returned value of seafile_api.check_file_lock: 0: not locked 1: locked by other 2: locked by me -1: error Return (is_locked, locked_by_me) """ if not is_pro_version(): return (False, False) return_value = seafile_api.check_file_lock(repo_id, file_path.lstrip('/'), username) if return_value == 0: return (False, False) elif return_value == 1: return (True , False) elif return_value == 2: return (True, True) else: raise SearpcError('check file lock error')
def sys_check_license(request): """Check seafile license expiration. """ if not is_pro_version(): raise Http404 content_type = 'application/json; charset=utf-8' result = {} license_dict = parse_license() if license_dict: try: expiration = license_dict['Expiration'] except KeyError as e: logger.error(e) result['error'] = str(e) return HttpResponse(json.dumps(result), status=500, content_type=content_type) struct_time = datetime.datetime.strptime(expiration, "%Y-%m-%d") expiration_timestamp = time.mktime(struct_time.timetuple()) if time.time() > expiration_timestamp: # already expired result['already_expired'] = True elif time.time() + 30 * 24 * 60 * 60 > expiration_timestamp: # will be expired in 30 days result['to_be_expired'] = True result['expiration_date'] = expiration return HttpResponse(json.dumps(result), content_type=content_type)
def get_user_info(email): user = User.objects.get(email=email) d_profile = DetailedProfile.objects.get_detailed_profile_by_user(email) profile = Profile.objects.get_profile_by_user(email) info = {} info['email'] = email info['name'] = email2nickname(email) info['contact_email'] = profile.contact_email if profile and profile.contact_email else '' info['login_id'] = profile.login_id if profile and profile.login_id else '' info['is_staff'] = user.is_staff info['is_active'] = user.is_active info['create_time'] = user.ctime info['reference_id'] = user.reference_id if user.reference_id else '' info['department'] = d_profile.department if d_profile else '' info['quota_total'] = seafile_api.get_user_quota(email) info['quota_usage'] = seafile_api.get_user_self_usage(email) info['create_time'] = timestamp_to_isoformat_timestr(user.ctime) if is_pro_version(): info['role'] = user.role return info
def get(self, request): if not is_pro_version(): error_msg = 'Feature disabled.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # check the date format, should be like '2015-10-10' start = request.GET.get('start', None) end = request.GET.get('end', None) if not check_time_period_valid(start, end): error_msg = 'start or end date invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # Filtering a DateTimeField with dates won't include items on the last day, # because the bounds are interpreted as '0am on the given date'. end = end + ' 23:59:59' result = [] from seahub_extra.sysadmin_extra.models import UserLoginLog logs = UserLoginLog.objects.filter(login_date__range=(start, end)) for log in logs: result.append({ 'login_time': datetime_to_isoformat_timestr(log.login_date), 'login_ip': log.login_ip, 'name': email2nickname(log.username), 'email':log.username }) return Response(result)
def _decorated(view, request, *args, **kwargs): if not is_pro_version() or not EVENTS_ENABLED: return api_error(status.HTTP_404_NOT_FOUND, 'Events not enabled.') start_time = request.GET.get("start", "") end_time = request.GET.get("end", "") if not start_time: error_msg = "Start time can not be empty" return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if not end_time: error_msg = "End time can not be empty" return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: start_time = datetime.datetime.strptime(start_time, "%Y-%m-%d %H:%M:%S") except: error_msg = "Start time %s invalid" % start_time return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: end_time = datetime.datetime.strptime(end_time, "%Y-%m-%d %H:%M:%S") except: error_msg = "End time %s invalid" % end_time return api_error(status.HTTP_400_BAD_REQUEST, error_msg) return func(view, request, start_time, end_time, *args, **kwargs)
def update_user_info(request, user, password, is_active, is_staff, role, nickname, login_id, contact_email, reference_id, quota_total_mb, institution_name): # update basic user info if is_active is not None: user.is_active = is_active if password: user.set_password(password) if is_staff is not None: user.is_staff = is_staff # update user user.save() email = user.username # update additional user info if is_pro_version() and role: User.objects.update_role(email, role) if nickname is not None: Profile.objects.add_or_update(email, nickname) key = normalize_cache_key(nickname, NICKNAME_CACHE_PREFIX) cache.set(key, nickname, NICKNAME_CACHE_TIMEOUT) if login_id is not None: Profile.objects.add_or_update(email, login_id=login_id) if contact_email is not None: Profile.objects.add_or_update(email, contact_email=contact_email) key = normalize_cache_key(email, CONTACT_CACHE_PREFIX) cache.set(key, contact_email, CONTACT_CACHE_TIMEOUT) if reference_id is not None: if reference_id.strip(): ccnet_api.set_reference_id(email, reference_id.strip()) else: # remove reference id ccnet_api.set_reference_id(email, None) if institution_name is not None: Profile.objects.add_or_update(email, institution=institution_name) if institution_name == '': InstitutionAdmin.objects.filter(user=email).delete() if quota_total_mb: quota_total = int(quota_total_mb) * get_file_size_unit('MB') orgs = ccnet_api.get_orgs_by_user(email) try: if orgs: org_id = orgs[0].org_id seafile_api.set_org_user_quota(org_id, email, quota_total) else: seafile_api.set_user_quota(email, quota_total) except Exception as e: logger.error(e) seafile_api.set_user_quota(email, -1)
def react_fake_view(request, **kwargs): username = request.user.username guide_enabled = UserOptions.objects.is_user_guide_enabled(username) if guide_enabled: create_default_library(request) try: expire_days = seafile_api.get_server_config_int( 'library_trash', 'expire_days') except Exception as e: logger.error(e) expire_days = -1 folder_perm_enabled = True if is_pro_version( ) and ENABLE_FOLDER_PERM else False try: max_upload_file_size = seafile_api.get_server_config_int( 'fileserver', 'max_upload_size') except Exception as e: logger.error(e) max_upload_file_size = -1 return render( request, "react_app.html", { "guide_enabled": guide_enabled, 'trash_repos_expire_days': expire_days if expire_days > 0 else 30, 'dtable_web_server': DTABLE_WEB_SERVER, 'max_upload_file_size': max_upload_file_size, 'seafile_collab_server': SEAFILE_COLLAB_SERVER, 'storages': get_library_storages(request), 'enable_repo_snapshot_label': settings.ENABLE_REPO_SNAPSHOT_LABEL, 'resumable_upload_file_block_size': settings.RESUMABLE_UPLOAD_FILE_BLOCK_SIZE, 'max_number_of_files_for_fileupload': settings.MAX_NUMBER_OF_FILES_FOR_FILEUPLOAD, 'share_link_expire_days_default': SHARE_LINK_EXPIRE_DAYS_DEFAULT, 'share_link_expire_days_min': SHARE_LINK_EXPIRE_DAYS_MIN, 'share_link_expire_days_max': SHARE_LINK_EXPIRE_DAYS_MAX, 'upload_link_expire_days_default': UPLOAD_LINK_EXPIRE_DAYS_DEFAULT, 'upload_link_expire_days_min': UPLOAD_LINK_EXPIRE_DAYS_MIN, 'upload_link_expire_days_max': UPLOAD_LINK_EXPIRE_DAYS_MAX, 'enable_encrypted_library': config.ENABLE_ENCRYPTED_LIBRARY, 'enable_repo_history_setting': config.ENABLE_REPO_HISTORY_SETTING, 'enable_reset_encrypted_repo_password': ENABLE_RESET_ENCRYPTED_REPO_PASSWORD, 'enableFileComment': settings.ENABLE_FILE_COMMENT, 'is_email_configured': IS_EMAIL_CONFIGURED, 'can_add_public_repo': request.user.permissions.can_add_public_repo(), 'folder_perm_enabled': folder_perm_enabled, 'file_audit_enabled': FILE_AUDIT_ENABLED, 'custom_nav_items': json.dumps(CUSTOM_NAV_ITEMS), 'enable_show_contact_email_when_search_user': settings.ENABLE_SHOW_CONTACT_EMAIL_WHEN_SEARCH_USER, 'additional_share_dialog_note': ADDITIONAL_SHARE_DIALOG_NOTE, 'additional_app_bottom_links': ADDITIONAL_APP_BOTTOM_LINKS, 'additional_about_dialog_links': ADDITIONAL_ABOUT_DIALOG_LINKS })
def delete(self): """ When delete user, we should also delete group relationships. """ if self.source == "DB": source = "DB" else: source = "LDAP" username = self.username orgs = [] if is_pro_version(): orgs = ccnet_api.get_orgs_by_user(username) # remove owned repos owned_repos = [] if orgs: for org in orgs: owned_repos += seafile_api.get_org_owned_repo_list( org.org_id, username) else: owned_repos += seafile_api.get_owned_repo_list(username) for r in owned_repos: seafile_api.remove_repo(r.id) # remove shared in repos shared_in_repos = [] if orgs: for org in orgs: org_id = org.org_id shared_in_repos = seafile_api.get_org_share_in_repo_list( org_id, username, -1, -1) for r in shared_in_repos: seafile_api.org_remove_share(org_id, r.repo_id, r.user, username) else: shared_in_repos = seafile_api.get_share_in_repo_list( username, -1, -1) for r in shared_in_repos: seafile_api.remove_share(r.repo_id, r.user, username) ExtraSharePermission.objects.filter(share_to=username).delete() # clear web api and repo sync token # when delete user try: clear_token(self.username) except Exception as e: logger.error(e) # remove current user from joined groups ccnet_api.remove_group_user(username) ccnet_api.remove_emailuser(source, username) Profile.objects.delete_profile_by_user(username) if settings.ENABLE_TERMS_AND_CONDITIONS: from termsandconditions.models import UserTermsAndConditions UserTermsAndConditions.objects.filter(username=username).delete()
def get(self, request, email): """ return all groups user joined Permission checking: 1. Admin user; """ if not request.user.admin_permissions.can_manage_user(): return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.') try: User.objects.get(email=email) except User.DoesNotExist as e: logger.error(e) error_msg = 'User %s not found.' % email return api_error(status.HTTP_404_NOT_FOUND, error_msg) groups_info = [] try: groups = ccnet_api.get_groups(email) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) # Use dict to reduce memcache fetch cost in large for-loop. nickname_dict = {} creator_name_set = set([g.creator_name for g in groups]) for e in creator_name_set: if e not in nickname_dict: nickname_dict[e] = email2nickname(e) for group in groups: isoformat_timestr = timestamp_to_isoformat_timestr(group.timestamp) group_info = { "id": group.id, "name": group.group_name, "owner_email": group.creator_name, "owner_name": nickname_dict.get(group.creator_name, ''), "created_at": isoformat_timestr, "parent_group_id": group.parent_group_id if is_pro_version() else 0 } groups_info.append(group_info) try: is_group_staff = ccnet_api.check_group_staff(group.id, email) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if email == group.creator_name: group_info['role'] = 'Owner' elif is_group_staff: group_info['role'] = 'Admin' else: group_info['role'] = 'Member' return Response({'group_list': groups_info})
def check_file_lock(repo_id, file_path, username): """ Check if file is locked to current user According to returned value of seafile_api.check_file_lock: 0: not locked 1: locked by other 2: locked by me -1: error Return (is_locked, locked_by_me) """ if not is_pro_version() or not ENABLE_FOLDER_PERM: return (False, False) return_value = seafile_api.check_file_lock(repo_id, file_path.lstrip('/'), username) if return_value == 0: return (False, False) elif return_value == 1: return (True , False) elif return_value == 2: return (True, True) else: raise SearpcError('check file lock error')
def edit_profile(request): """ Show and edit user profile. """ username = request.user.username form_class = DetailedProfileForm if request.method == 'POST': form = form_class(request.POST) if form.is_valid(): form.save(username=username) messages.success(request, _(u'Successfully edited profile.')) return HttpResponseRedirect(reverse('edit_profile')) else: messages.error(request, _(u'Failed to edit profile')) else: profile = Profile.objects.get_profile_by_user(username) d_profile = DetailedProfile.objects.get_detailed_profile_by_user( username) init_dict = {} if profile: init_dict['nickname'] = profile.nickname init_dict['login_id'] = profile.login_id init_dict['contact_email'] = profile.contact_email if d_profile: init_dict['department'] = d_profile.department init_dict['telephone'] = d_profile.telephone form = form_class(init_dict) # common logic try: server_crypto = UserOptions.objects.is_server_crypto(username) except CryptoOptionNotSetError: # Assume server_crypto is ``False`` if this option is not set. server_crypto = False sub_lib_enabled = UserOptions.objects.is_sub_lib_enabled(username) default_repo_id = UserOptions.objects.get_default_repo(username) if default_repo_id: default_repo = seafile_api.get_repo(default_repo_id) else: default_repo = None owned_repos = get_owned_repo_list(request) owned_repos = filter(lambda r: not r.is_virtual, owned_repos) return render_to_response('profile/set_profile.html', { 'form': form, 'server_crypto': server_crypto, "sub_lib_enabled": sub_lib_enabled, 'force_server_crypto': settings.FORCE_SERVER_CRYPTO, 'default_repo': default_repo, 'owned_repos': owned_repos, 'is_pro': is_pro_version(), 'is_ldap_user': is_ldap_user(request.user), 'two_factor_auth_enabled': has_two_factor_auth(), }, context_instance=RequestContext(request))
def get(self, request): if not is_pro_version(): error_msg = 'Feature disabled.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # check the date format, should be like '2015-10-10' start = request.GET.get('start', None) end = request.GET.get('end', None) if not check_time_period_valid(start, end): error_msg = 'start or end date invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # Filtering a DateTimeField with dates won't include items on the last day, # because the bounds are interpreted as '0am on the given date'. end = end + ' 23:59:59' result = [] from seahub_extra.sysadmin_extra.models import UserLoginLog logs = UserLoginLog.objects.filter(login_date__range=(start, end)) for log in logs: result.append({ 'login_time': datetime_to_isoformat_timestr(log.login_date), 'login_ip': log.login_ip, 'name': email2nickname(log.username), 'email': log.username }) return Response(result)
def user_toggle_role(request, email): content_type = 'application/json; charset=utf-8' if not is_valid_username(email): return HttpResponse(json.dumps({'success': False}), status=400, content_type=content_type) if not is_pro_version(): return HttpResponse(json.dumps({'success': False}), status=403, content_type=content_type) try: user_role = request.POST.get('r', DEFAULT_USER) except ValueError: user_role = DEFAULT_USER try: user = User.objects.get(email) User.objects.update_role(user.email, user_role) return HttpResponse(json.dumps({'success': True}), content_type=content_type) except User.DoesNotExist: return HttpResponse(json.dumps({'success': False}), status=500, content_type=content_type)
def authenticate(self, username, password): if not is_pro_version() or not ENABLE_LDAP: return self.l = ldap.initialize(LDAP_SERVER_URL) try: self.l.protocol_version = ldap.VERSION3 self.l.simple_bind_s(LDAP_ADMIN_EMAIL, LDAP_ADMIN_PASSWORD) except ldap.INVALID_CREDENTIALS: logger.error('LDAP SETTINGS ERROR.') if LDAP_LOGIN_ATTR.lower() in ['email', 'mail']: filterstr = ldap.filter.filter_format( '(&(objectClass=user)(mail=%s))', [username]) else: logger.error('LDAP SETTINGS ERROR.') return try: ldap_result_id = self.l.search(LDAP_BASE_DN, ldap.SCOPE_SUBTREE, filterstr) result_type, result_data = self.l.result(ldap_result_id, 1) except Exception as e: return # user not found in ldap if not result_data: return # delete old ldap connection instance and create new, if not, some err will occur self.l.unbind_s() del self.l self.l = ldap.initialize(LDAP_SERVER_URL) try: user_pricinpal_name, display_name = parse_userPrincipalName_and_displayName( result_data) except Exception: return try: self.l.protocol_version = ldap.VERSION3 self.l.simple_bind_s(user_pricinpal_name, password) except ldap.INVALID_CREDENTIALS as e: return self.l.unbind_s() # check if existed user = self.get_user(username) if user: return user # user not in dtable, create user user = User.objects.create_ldap_user(email=username, nickname=display_name, is_active=True) return user
def post(self, request): if not request.user.admin_permissions.can_config_system(): return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.') license_file = request.FILES.get('license', None) if not license_file: error_msg = 'license can not be found.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) file_type, ext = get_file_type_and_ext(license_file.name) if ext != 'txt': error_msg = file_type_error_msg(ext, 'txt') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if license_file.size > 1024 * 1024 * 5: # 5mb error_msg = file_size_error_msg(license_file.size, 5 * 1024 * 1024) return api_error(status.HTTP_400_BAD_REQUEST, error_msg) license_dir = os.path.dirname(LICENSE_PATH) try: if not os.path.exists(license_dir): error_msg = 'path %s invalid.' % LICENSE_PATH return api_error(status.HTTP_400_BAD_REQUEST, error_msg) with open(LICENSE_PATH, 'wb') as fd: fd.write(license_file.read()) ccnet_api.reload_license() except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) # get license info is_pro = is_pro_version() if is_pro: license_dict = parse_license() else: license_dict = {} if license_dict: try: max_users = int(license_dict.get('MaxUsers', 3)) except ValueError as e: logger.error(e) max_users = 0 else: max_users = 0 license_info = { 'license_expiration': license_dict.get('Expiration', ''), 'license_mode': license_dict.get('Mode', ''), 'license_maxusers': max_users, 'license_to': license_dict.get('Name', ''), } return Response(license_info, status=status.HTTP_200_OK)
def if_locked_by_online_office(repo_id, path): locked_by_online_office = False if is_pro_version(): lock_info = seafile_api.get_lock_info(repo_id, path) if lock_info and lock_info.user == ONLINE_OFFICE_LOCK_OWNER: locked_by_online_office = True return locked_by_online_office
def put(self, request, repo_id, format=None): """ Currently only for lock and unlock file operation. Permission checking: 1. user with 'rw' permission for current file; """ if not is_pro_version(): error_msg = 'file lock feature only supported in professional edition.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # argument check path = request.GET.get('p', None) if not path: error_msg = 'p invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) operation = request.data.get('operation', None) if not operation: error_msg = 'operation invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) operation = operation.lower() if operation not in ('lock', 'unlock'): error_msg = "operation can only be 'lock', or 'unlock'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # resource check repo = seafile_api.get_repo(repo_id) if not repo: error_msg = 'Library %s not found.' % repo_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) file_id = seafile_api.get_file_id_by_path(repo_id, path) if not file_id: error_msg = 'File %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check parent_dir = os.path.dirname(path) if check_folder_permission(request, repo_id, parent_dir) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) username = request.user.username is_locked, locked_by_me = check_file_lock(repo_id, path, username) if operation == 'lock': if not is_locked: # lock file expire = request.data.get('expire', FILE_LOCK_EXPIRATION_DAYS) try: seafile_api.lock_file(repo_id, path.lstrip('/'), username, expire) except SearpcError, e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
def update_user_info(request): email = request.data.get("email") user = User.objects.get(email=email) # update basic user info password = request.data.get("password") if password: user.set_password(password) is_staff = request.data.get("is_staff") if is_staff: is_staff = to_python_boolean(is_staff) user.is_staff = is_staff is_active = request.data.get("is_active") if is_active: is_active = to_python_boolean(is_active) user.is_active = is_active # update user user.save() # update additional user info if is_pro_version(): role = request.data.get("role") if role: User.objects.update_role(email, role) name = request.data.get("name") if name: profile = Profile.objects.get_profile_by_user(email) if profile is None: profile = Profile(user=email) profile.nickname = name profile.save() department = request.data.get("department") if department: d_profile = DetailedProfile.objects.get_detailed_profile_by_user(email) if d_profile is None: d_profile = DetailedProfile(user=email) d_profile.department = department d_profile.save() quota_total_mb = request.data.get("quota_total") if quota_total_mb: quota_total = int(quota_total_mb) * get_file_size_unit('MB') if is_org_context(request): org_id = request.user.org.org_id seafile_api.set_org_user_quota(org_id, email, quota_total) else: seafile_api.set_user_quota(email, quota_total)
def unlock_file(request): key, value = generate_file_lock_key_value(request) cache.delete(key) if is_pro_version(): token = request.GET.get('access_token', None) info_dict = get_file_info_by_token(token) repo_id = info_dict['repo_id'] file_path = info_dict['file_path'] seafile_api.unlock_file(repo_id, file_path)
def can_view_sys_admin_repo(repo): default_repo_id = get_system_default_repo_id() is_default_repo = True if repo.id == default_repo_id else False if is_default_repo: return True elif repo.encrypted: return False elif is_pro_version() and ENABLE_SYS_ADMIN_VIEW_REPO: return True else: return False
def delete(self, request, format=None): if not is_pro_version(): error_msg = 'Feature disabled.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) try: seafile_api.clear_repo_sync_errors() except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) return Response({'success': True})
def libraries(request): """ New URL to replace myhome """ username = request.user.username # options if request.cloud_mode and request.user.org is None: allow_public_share = False else: allow_public_share = True sub_lib_enabled = UserOptions.objects.is_sub_lib_enabled(username) max_upload_file_size = get_max_upload_file_size() guide_enabled = UserOptions.objects.is_user_guide_enabled(username) if guide_enabled: create_default_library(request) folder_perm_enabled = True if is_pro_version() and ENABLE_FOLDER_PERM else False can_add_pub_repo = True if is_org_repo_creation_allowed(request) else False return render_to_response('libraries.html', { "allow_public_share": allow_public_share, "guide_enabled": guide_enabled, "sub_lib_enabled": sub_lib_enabled, 'enable_upload_folder': settings.ENABLE_UPLOAD_FOLDER, 'enable_resumable_fileupload': settings.ENABLE_RESUMABLE_FILEUPLOAD, 'enable_thumbnail': settings.ENABLE_THUMBNAIL, 'thumbnail_default_size': settings.THUMBNAIL_DEFAULT_SIZE, 'thumbnail_size_for_grid': settings.THUMBNAIL_SIZE_FOR_GRID, 'enable_encrypted_library': config.ENABLE_ENCRYPTED_LIBRARY, 'enable_repo_history_setting': config.ENABLE_REPO_HISTORY_SETTING, 'max_upload_file_size': max_upload_file_size, 'folder_perm_enabled': folder_perm_enabled, 'is_pro': True if is_pro_version() else False, 'file_audit_enabled': FILE_AUDIT_ENABLED, 'can_add_pub_repo': can_add_pub_repo, }, context_instance=RequestContext(request))
def is_sub_lib_enabled(self, username): """Return ``True`` if is not pro version AND sub lib enabled, otherwise ``False``. Arguments: - `self`: - `username`: """ if is_pro_version(): return False try: user_option = super(UserOptionsManager, self).get(email=username, option_key=KEY_SUB_LIB) return bool(int(user_option.option_val)) except UserOptions.DoesNotExist: return False
def _decorated(request, token, *args, **kwargs): assert token is not None # Checked by URLconf fileshare = FileShare.objects.get_valid_file_link_by_token(token) or \ FileShare.objects.get_valid_dir_link_by_token(token) or \ UploadLinkShare.objects.get_valid_upload_link_by_token(token) if fileshare is None: raise Http404 if not is_pro_version() or not settings.ENABLE_SHARE_LINK_AUDIT: return func(request, fileshare, *args, **kwargs) # no audit for authenticated user, since we've already got email address if request.user.is_authenticated(): return func(request, fileshare, *args, **kwargs) # anonymous user if request.session.get('anonymous_email') is not None: request.user.username = request.session.get('anonymous_email') return func(request, fileshare, *args, **kwargs) if request.method == 'GET': return render_to_response('share/share_link_audit.html', { 'token': token, }, context_instance=RequestContext(request)) elif request.method == 'POST': code = request.POST.get('code', '') email = request.POST.get('email', '') cache_key = normalize_cache_key(email, 'share_link_audit_') if code == cache.get(cache_key): # code is correct, add this email to session so that he will # not be asked again during this session, and clear this code. request.session['anonymous_email'] = email request.user.username = request.session.get('anonymous_email') cache.delete(cache_key) return func(request, fileshare, *args, **kwargs) else: return render_to_response('share/share_link_audit.html', { 'err_msg': 'Invalid token, please try again.', 'email': email, 'code': code, 'token': token, }, context_instance=RequestContext(request)) else: assert False, 'TODO'
def sub_lib_enable_set(request): """ """ if is_pro_version(): raise Http404 username = request.user.username enable_sub_lib = request.POST.get('enable-sub-lib', '') if enable_sub_lib: UserOptions.objects.enable_sub_lib(username) else: UserOptions.objects.disable_sub_lib(username) next = request.META.get('HTTP_REFERER', None) if next is None: next = SITE_ROOT return HttpResponseRedirect(next)
def get(self, request, format=None): if not is_pro_version(): error_msg = 'Feature disabled.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) return_results = [] try: device_errors = seafile_api.list_repo_sync_errors() except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) for error in device_errors: result = {} result['email'] = error.email if error.email else '' result['name'] = email2nickname(error.email) result['device_ip'] = error.peer_ip if error.peer_ip else '' result['repo_name'] = error.repo_name if error.repo_name else '' result['repo_id'] = error.repo_id if error.repo_id else '' result['error_msg'] = error.error_con if error.error_con else '' tokens = TokenV2.objects.filter(device_id = error.peer_id) if tokens: result['device_name'] = tokens[0].device_name result['client_version'] = tokens[0].client_version else: result['device_name'] = '' result['client_version'] = '' if error.error_time: result['error_time'] = timestamp_to_isoformat_timestr(error.error_time) else: result['error_time'] = '' return_results.append(result) return Response(return_results)
def sys_user_admin(request): """List all users from database. """ # Make sure page request is an int. If not, deliver first page. try: current_page = int(request.GET.get('page', '1')) per_page = int(request.GET.get('per_page', '25')) except ValueError: current_page = 1 per_page = 25 users_plus_one = get_emailusers('DB', per_page * (current_page - 1), per_page + 1) if len(users_plus_one) == per_page + 1: page_next = True else: page_next = False users = users_plus_one[:per_page] last_logins = UserLastLogin.objects.filter(username__in=[x.email for x in users]) if enable_trial_account: trial_users = TrialAccount.objects.filter(user_or_org__in=[x.email for x in users]) else: trial_users = [] for user in users: if user.props.id == request.user.id: user.is_self = True _populate_user_quota_usage(user) # check user's role if user.role == GUEST_USER: user.is_guest = True else: user.is_guest = False # populate user last login time user.last_login = None for last_login in last_logins: if last_login.username == user.email: user.last_login = last_login.last_login user.trial_info = None for trial_user in trial_users: if trial_user.user_or_org == user.email: user.trial_info = {'expire_date': trial_user.expire_date} have_ldap = True if len(get_emailusers('LDAP', 0, 1)) > 0 else False platform = get_platform_name() server_id = get_server_id() pro_server = 1 if is_pro_version() else 0 return render_to_response( 'sysadmin/sys_useradmin.html', { 'users': users, 'current_page': current_page, 'prev_page': current_page-1, 'next_page': current_page+1, 'per_page': per_page, 'page_next': page_next, 'CALC_SHARE_USAGE': CALC_SHARE_USAGE, 'have_ldap': have_ldap, 'platform': platform, 'server_id': server_id[:8], 'default_user': DEFAULT_USER, 'guest_user': GUEST_USER, 'enable_guest': ENABLE_GUEST, 'pro_server': pro_server, }, context_instance=RequestContext(request))
def post(self, request, repo_id, format=None): repo = seafile_api.get_repo(repo_id) if not repo: return api_error(status.HTTP_404_NOT_FOUND, 'Library not found.') path = request.GET.get('p', '') if not path or path[0] != '/': error_msg = 'p invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if path == '/': error_msg = 'Can not make or rename root dir.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if path[-1] == '/': path = path[:-1] username = request.user.username parent_dir = os.path.dirname(path) operation = request.POST.get('operation', '') if operation.lower() == 'mkdir': parent_dir = os.path.dirname(path) if check_folder_permission(request, repo_id, parent_dir) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) create_parents = request.POST.get('create_parents', '').lower() in ('true', '1') if not create_parents: parent_dir_id = seafile_api.get_dir_id_by_path(repo_id, parent_dir) if not parent_dir_id: error_msg = 'Folder %s not found.' % parent_dir return api_error(status.HTTP_404_NOT_FOUND, error_msg) new_dir_name = os.path.basename(path) new_dir_name = check_filename_with_rename(repo_id, parent_dir, new_dir_name) try: seafile_api.post_dir(repo_id, parent_dir, new_dir_name, username) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) else: if not is_pro_version(): error_msg = 'Feature not supported.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) try: seafile_api.mkdir_with_parents(repo_id, '/', path[1:], username) except SearpcError as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if request.GET.get('reloaddir', '').lower() == 'true': resp = reloaddir(request, repo, parent_dir) else: resp = Response({'success': True}) return resp elif operation.lower() == 'rename': dir_id = seafile_api.get_dir_id_by_path(repo_id, path) if not dir_id: error_msg = 'Folder %s not found.' % path return api_error(status.HTTP_404_NOT_FOUND, error_msg) if check_folder_permission(request, repo.id, path) != 'rw': error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) parent_dir = os.path.dirname(path) old_dir_name = os.path.basename(path) newname = request.POST.get('newname', '') if not newname: error_msg = 'newname invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if newname == old_dir_name: return Response({'success': True}) try: # rename duplicate name checked_newname = check_filename_with_rename(repo_id, parent_dir, newname) # rename dir seafile_api.rename_file(repo_id, parent_dir, old_dir_name, checked_newname, username) return Response({'success': True}) except SearpcError, e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
def update_user_info(request, user): # update basic user info password = request.data.get("password") if password: user.set_password(password) is_staff = request.data.get("is_staff") if is_staff: is_staff = to_python_boolean(is_staff) user.is_staff = is_staff is_active = request.data.get("is_active") if is_active: is_active = to_python_boolean(is_active) user.is_active = is_active # update user user.save() email = user.username # update additional user info if is_pro_version(): role = request.data.get("role") if role: User.objects.update_role(email, role) nickname = request.data.get("name", None) if nickname is not None: Profile.objects.add_or_update(email, nickname) # update account login_id login_id = request.data.get("login_id", None) if login_id is not None: Profile.objects.add_or_update(email, login_id=login_id) # update account contact email contact_email = request.data.get('contact_email', None) if contact_email is not None: Profile.objects.add_or_update(email, contact_email=contact_email) key = normalize_cache_key(email, CONTACT_CACHE_PREFIX) cache.set(key, contact_email, CONTACT_CACHE_TIMEOUT) reference_id = request.data.get("reference_id", None) if reference_id is not None: if reference_id.strip(): ccnet_api.set_reference_id(email, reference_id.strip()) else: # remove reference id ccnet_api.set_reference_id(email, None) department = request.data.get("department") if department: d_profile = DetailedProfile.objects.get_detailed_profile_by_user(email) if d_profile is None: d_profile = DetailedProfile(user=email) d_profile.department = department d_profile.save() quota_total_mb = request.data.get("quota_total") if quota_total_mb: quota_total = int(quota_total_mb) * get_file_size_unit('MB') if is_org_context(request): org_id = request.user.org.org_id seafile_api.set_org_user_quota(org_id, email, quota_total) else: seafile_api.set_user_quota(email, quota_total)
def get_library_storages(request): """ Return info of storages can be used. 1. If not enable user role feature OR haven't configured `storage_ids` option in user role setting: Return storage info getted from seafile_api. And always put the default storage as the first item in the returned list. 2. If have configured `storage_ids` option in user role setting: Only return storage info in `storage_ids`. Filter out the wrong stotage id(s). Not change the order of the `storage_ids` list. """ if not is_pro_version(): return [] if not ENABLE_STORAGE_CLASSES: return [] # get all storages info try: storage_classes = seafile_api.get_all_storage_classes() except Exception as e: logger.error(e) return [] all_storages = [] for storage in storage_classes: storage_info = { 'storage_id': storage.storage_id, 'storage_name': storage.storage_name, 'is_default': storage.is_default, } if storage.is_default: all_storages.insert(0, storage_info) else: all_storages.append(storage_info) if STORAGE_CLASS_MAPPING_POLICY == 'USER_SELECT': return all_storages elif STORAGE_CLASS_MAPPING_POLICY == 'ROLE_BASED': user_role_storage_ids = request.user.permissions.storage_ids() if not user_role_storage_ids: return [] user_role_storages = [] for user_role_storage_id in user_role_storage_ids: for storage in all_storages: if storage['storage_id'] == user_role_storage_id: user_role_storages.append(storage) continue return user_role_storages else: # STORAGE_CLASS_MAPPING_POLICY == 'REPO_ID_MAPPING' return []
def get(self, request, format=None): """ Only used for download dir when view dir share link from web. Permission checking: 1. authenticated user OR anonymous user has passed email code check(if necessary); """ # permission check if is_pro_version() and settings.ENABLE_SHARE_LINK_AUDIT: if not request.user.is_authenticated() and \ not request.session.get('anonymous_email'): # if anonymous user has passed email code check, # then his/her email info will be in session. error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # argument check share_link_token = request.GET.get('share_link_token', None) if not share_link_token: error_msg = 'share_link_token invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) req_path = request.GET.get('path', None) if not req_path: error_msg = 'path invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # recourse check fileshare = FileShare.objects.get_valid_dir_link_by_token(share_link_token) if not fileshare: error_msg = 'share_link_token %s not found.' % share_link_token return api_error(status.HTTP_404_NOT_FOUND, error_msg) if req_path[-1] != '/': req_path += '/' if req_path == '/': real_path = fileshare.path else: real_path = posixpath.join(fileshare.path, req_path.lstrip('/')) if real_path[-1] != '/': real_path += '/' repo_id = fileshare.repo_id repo = seafile_api.get_repo(repo_id) if not repo: error_msg = 'Library %s not found.' % repo_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) dir_id = seafile_api.get_dir_id_by_path(repo_id, real_path) if not dir_id: error_msg = 'Folder %s not found.' % real_path return api_error(status.HTTP_404_NOT_FOUND, error_msg) # get file server access token dir_name = repo.name if real_path == '/' else \ os.path.basename(real_path.rstrip('/')) dir_size = seafile_api.get_dir_size( repo.store_id, repo.version, dir_id) if dir_size > seaserv.MAX_DOWNLOAD_DIR_SIZE: error_msg = 'Unable to download directory "%s": size is too large.' % dir_name return api_error(status.HTTP_400_BAD_REQUEST, error_msg) is_windows = 0 if is_windows_operating_system(request): is_windows = 1 fake_obj_id = { 'obj_id': dir_id, 'dir_name': dir_name, 'is_windows': is_windows } username = request.user.username try: zip_token = seafile_api.get_fileserver_access_token( repo_id, json.dumps(fake_obj_id), 'download-dir', username) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if request.session.get('anonymous_email'): request.user.username = request.session.get('anonymous_email') send_file_access_msg(request, repo, real_path, 'share-link') return Response({'zip_token': zip_token})
def get_dir_file_info_list(username, request_type, repo_obj, parent_dir, with_thumbnail, thumbnail_size): repo_id = repo_obj.id dir_info_list = [] file_info_list = [] # get dirent(folder and file) list parent_dir_id = seafile_api.get_dir_id_by_path(repo_id, parent_dir) dir_file_list = seafile_api.list_dir_with_perm(repo_id, parent_dir, parent_dir_id, username, -1, -1) try: starred_items = UserStarredFiles.objects.filter(email=username, repo_id=repo_id, path__startswith=parent_dir, org_id=-1) starred_item_path_list = [f.path.rstrip('/') for f in starred_items] except Exception as e: logger.error(e) starred_item_path_list = [] # only get dir info list if not request_type or request_type == 'd': dir_list = [dirent for dirent in dir_file_list if stat.S_ISDIR(dirent.mode)] for dirent in dir_list: dir_info = {} dir_info["type"] = "dir" dir_info["id"] = dirent.obj_id dir_info["name"] = dirent.obj_name dir_info["mtime"] = dirent.mtime dir_info["permission"] = dirent.permission dir_info["parent_dir"] = parent_dir dir_info_list.append(dir_info) # get star info dir_info['starred'] = False dir_path = posixpath.join(parent_dir, dirent.obj_name) if dir_path.rstrip('/') in starred_item_path_list: dir_info['starred'] = True # only get file info list if not request_type or request_type == 'f': file_list = [dirent for dirent in dir_file_list if not stat.S_ISDIR(dirent.mode)] # Use dict to reduce memcache fetch cost in large for-loop. nickname_dict = {} contact_email_dict = {} modifier_set = set([x.modifier for x in file_list]) lock_owner_set = set([x.lock_owner for x in file_list]) for e in modifier_set | lock_owner_set: if e not in nickname_dict: nickname_dict[e] = email2nickname(e) if e not in contact_email_dict: contact_email_dict[e] = email2contact_email(e) try: files_tags_in_dir = get_files_tags_in_dir(repo_id, parent_dir) except Exception as e: logger.error(e) files_tags_in_dir = {} for dirent in file_list: file_name = dirent.obj_name file_path = posixpath.join(parent_dir, file_name) file_obj_id = dirent.obj_id file_info = {} file_info["type"] = "file" file_info["id"] = file_obj_id file_info["name"] = file_name file_info["mtime"] = dirent.mtime file_info["permission"] = dirent.permission file_info["parent_dir"] = parent_dir file_info["size"] = dirent.size modifier_email = dirent.modifier file_info['modifier_email'] = modifier_email file_info['modifier_name'] = nickname_dict.get(modifier_email, '') file_info['modifier_contact_email'] = contact_email_dict.get(modifier_email, '') # get lock info if is_pro_version(): file_info["is_locked"] = dirent.is_locked file_info["lock_time"] = dirent.lock_time lock_owner_email = dirent.lock_owner or '' file_info["lock_owner"] = lock_owner_email file_info['lock_owner_name'] = nickname_dict.get(lock_owner_email, '') file_info['lock_owner_contact_email'] = contact_email_dict.get(lock_owner_email, '') if username == lock_owner_email: file_info["locked_by_me"] = True else: file_info["locked_by_me"] = False # get star info file_info['starred'] = False if file_path.rstrip('/') in starred_item_path_list: file_info['starred'] = True # get tag info file_tags = files_tags_in_dir.get(file_name, []) if file_tags: file_info['file_tags'] = [] for file_tag in file_tags: file_info['file_tags'].append(file_tag) # get thumbnail info if with_thumbnail and not repo_obj.encrypted: # used for providing a way to determine # if send a request to create thumbnail. fileExt = os.path.splitext(file_name)[1][1:].lower() file_type = FILEEXT_TYPE_MAP.get(fileExt) if file_type in (IMAGE, XMIND) or \ file_type == VIDEO and ENABLE_VIDEO_THUMBNAIL: # if thumbnail has already been created, return its src. # Then web browser will use this src to get thumbnail instead of # recreating it. thumbnail_file_path = os.path.join(THUMBNAIL_ROOT, str(thumbnail_size), file_obj_id) if os.path.exists(thumbnail_file_path): src = get_thumbnail_src(repo_id, thumbnail_size, file_path) file_info['encoded_thumbnail_src'] = urlquote(src) file_info_list.append(file_info) dir_info_list.sort(lambda x, y: cmp(x['name'].lower(), y['name'].lower())) file_info_list.sort(lambda x, y: cmp(x['name'].lower(), y['name'].lower())) return dir_info_list, file_info_list
def get(self, request): """ Return repos user can access. Permission checking: 1. all authenticated user can perform this action. """ filter_by = { 'mine': False, 'shared': False, 'group': False, 'public': False, } request_type_list = request.GET.getlist('type', "") if not request_type_list: # set all to True, no filter applied filter_by = filter_by.fromkeys(filter_by.iterkeys(), True) for request_type in request_type_list: request_type = request_type.strip() filter_by[request_type] = True email = request.user.username # Use dict to reduce memcache fetch cost in large for-loop. contact_email_dict = {} nickname_dict = {} org_id = None if is_org_context(request): org_id = request.user.org.org_id try: starred_repos = UserStarredFiles.objects.get_starred_repos_by_user(email) starred_repo_id_list = [item.repo_id for item in starred_repos] except Exception as e: logger.error(e) starred_repo_id_list = [] repo_info_list = [] if filter_by['mine']: if org_id: owned_repos = seafile_api.get_org_owned_repo_list(org_id, email, ret_corrupted=True) else: owned_repos = seafile_api.get_owned_repo_list(email, ret_corrupted=True) # Reduce memcache fetch ops. modifiers_set = set([x.last_modifier for x in owned_repos]) for e in modifiers_set: if e not in contact_email_dict: contact_email_dict[e] = email2contact_email(e) if e not in nickname_dict: nickname_dict[e] = email2nickname(e) owned_repos.sort(lambda x, y: cmp(y.last_modify, x.last_modify)) for r in owned_repos: # do not return virtual repos if r.is_virtual: continue repo_info = { "type": "mine", "repo_id": r.id, "repo_name": r.name, "owner_email": email, "owner_name": email2nickname(email), "owner_contact_email": email2contact_email(email), "last_modified": timestamp_to_isoformat_timestr(r.last_modify), "modifier_email": r.last_modifier, "modifier_name": nickname_dict.get(r.last_modifier, ''), "modifier_contact_email": contact_email_dict.get(r.last_modifier, ''), "size": r.size, "encrypted": r.encrypted, "permission": 'rw', # Always have read-write permission to owned repo "starred": r.repo_id in starred_repo_id_list, } if is_pro_version() and ENABLE_STORAGE_CLASSES: repo_info['storage_name'] = r.storage_name repo_info['storage_id'] = r.storage_id repo_info_list.append(repo_info) if filter_by['shared']: if org_id: shared_repos = seafile_api.get_org_share_in_repo_list(org_id, email, -1, -1) else: shared_repos = seafile_api.get_share_in_repo_list( email, -1, -1) repos_with_admin_share_to = ExtraSharePermission.objects.\ get_repos_with_admin_permission(email) # Reduce memcache fetch ops. owners_set = set([x.user for x in shared_repos]) modifiers_set = set([x.last_modifier for x in shared_repos]) for e in owners_set | modifiers_set: if e not in contact_email_dict: contact_email_dict[e] = email2contact_email(e) if e not in nickname_dict: nickname_dict[e] = email2nickname(e) shared_repos.sort(lambda x, y: cmp(y.last_modify, x.last_modify)) for r in shared_repos: owner_email = r.user group_name = '' is_group_owned_repo = False if '@seafile_group' in owner_email: is_group_owned_repo = True group_id = get_group_id_by_repo_owner(owner_email) group_name= group_id_to_name(group_id) owner_name = group_name if is_group_owned_repo else \ nickname_dict.get(owner_email, '') owner_contact_email = '' if is_group_owned_repo else \ contact_email_dict.get(owner_email, '') repo_info = { "type": "shared", "repo_id": r.repo_id, "repo_name": r.repo_name, "last_modified": timestamp_to_isoformat_timestr(r.last_modify), "modifier_email": r.last_modifier, "modifier_name": nickname_dict.get(r.last_modifier, ''), "modifier_contact_email": contact_email_dict.get(r.last_modifier, ''), "owner_email": owner_email, "owner_name": owner_name, "owner_contact_email": owner_contact_email, "size": r.size, "encrypted": r.encrypted, "permission": r.permission, "starred": r.repo_id in starred_repo_id_list, } if r.repo_id in repos_with_admin_share_to: repo_info['is_admin'] = True else: repo_info['is_admin'] = False repo_info_list.append(repo_info) if filter_by['group']: if org_id: group_repos = seafile_api.get_org_group_repos_by_user(email, org_id) else: group_repos = seafile_api.get_group_repos_by_user(email) group_repos.sort(lambda x, y: cmp(y.last_modify, x.last_modify)) # Reduce memcache fetch ops. share_from_set = set([x.user for x in group_repos]) modifiers_set = set([x.last_modifier for x in group_repos]) for e in modifiers_set | share_from_set: if e not in contact_email_dict: contact_email_dict[e] = email2contact_email(e) if e not in nickname_dict: nickname_dict[e] = email2nickname(e) for r in group_repos: repo_info = { "type": "group", "group_id": r.group_id, "group_name": r.group_name, "repo_id": r.repo_id, "repo_name": r.repo_name, "last_modified": timestamp_to_isoformat_timestr(r.last_modify), "modifier_email": r.last_modifier, "modifier_name": nickname_dict.get(r.last_modifier, ''), "modifier_contact_email": contact_email_dict.get(r.last_modifier, ''), "size": r.size, "encrypted": r.encrypted, "permission": r.permission, "starred": r.repo_id in starred_repo_id_list, } repo_info_list.append(repo_info) if filter_by['public'] and request.user.permissions.can_view_org(): public_repos = list_inner_pub_repos(request) # get repo id owner dict all_repo_owner = [] repo_id_owner_dict = {} for repo in public_repos: repo_id = repo.repo_id if repo_id not in repo_id_owner_dict: repo_owner = get_repo_owner(request, repo_id) all_repo_owner.append(repo_owner) repo_id_owner_dict[repo_id] = repo_owner # Reduce memcache fetch ops. owner_set = set(all_repo_owner) share_from_set = set([x.user for x in public_repos]) modifiers_set = set([x.last_modifier for x in public_repos]) for e in modifiers_set | share_from_set | owner_set: if e not in contact_email_dict: contact_email_dict[e] = email2contact_email(e) if e not in nickname_dict: nickname_dict[e] = email2nickname(e) for r in public_repos: repo_owner = repo_id_owner_dict[r.repo_id] repo_info = { "type": "public", "repo_id": r.repo_id, "repo_name": r.repo_name, "last_modified": timestamp_to_isoformat_timestr(r.last_modify), "modifier_email": r.last_modifier, "modifier_name": nickname_dict.get(r.last_modifier, ''), "modifier_contact_email": contact_email_dict.get(r.last_modifier, ''), "owner_email": repo_owner, "owner_name": nickname_dict.get(repo_owner, ''), "owner_contact_email": contact_email_dict.get(repo_owner, ''), "size": r.size, "encrypted": r.encrypted, "permission": r.permission, "starred": r.repo_id in starred_repo_id_list, } repo_info_list.append(repo_info) utc_dt = datetime.datetime.utcnow() timestamp = utc_dt.strftime('%Y-%m-%d %H:%M:%S') org_id = request.user.org.org_id if is_org_context(request) else -1 try: send_message('seahub.stats', 'user-login\t%s\t%s\t%s' % (email, timestamp, org_id)) except Exception as e: logger.error('Error when sending user-login message: %s' % str(e)) return Response({'repos': repo_info_list})
def get(self, request, format=None): # count repos try: repos_count = seafile_api.count_repos() except SearpcError as e: logger.error(e) repos_count = 0 # count groups try: groups_count = len(ccnet_api.get_all_groups(-1, -1)) except Exception as e: logger.error(e) groups_count = 0 # count orgs if MULTI_TENANCY: multi_tenancy_enabled = True try: org_count = ccnet_api.count_orgs() except Exception as e: logger.error(e) org_count = 0 else: multi_tenancy_enabled = False org_count = 0 # count users try: active_db_users = ccnet_api.count_emailusers('DB') except Exception as e: logger.error(e) active_db_users = 0 try: active_ldap_users = ccnet_api.count_emailusers('LDAP') except Exception as e: logger.error(e) active_ldap_users = 0 try: inactive_db_users = ccnet_api.count_inactive_emailusers('DB') except Exception as e: logger.error(e) inactive_db_users = 0 try: inactive_ldap_users = ccnet_api.count_inactive_emailusers('LDAP') except Exception as e: logger.error(e) inactive_ldap_users = 0 active_users = active_db_users + active_ldap_users if \ active_ldap_users > 0 else active_db_users inactive_users = inactive_db_users + inactive_ldap_users if \ inactive_ldap_users > 0 else inactive_db_users # get license info is_pro = is_pro_version() if is_pro: license_dict = parse_license() else: license_dict = {} if license_dict: with_license = True try: max_users = int(license_dict.get('MaxUsers', 3)) except ValueError as e: logger.error(e) max_users = 0 else: with_license = False max_users = 0 # count total file number try: total_files_count = seafile_api.get_total_file_number() except Exception as e: logger.error(e) total_files_count = 0 # count total storage try: total_storage = seafile_api.get_total_storage() except Exception as e: logger.error(e) total_storage = 0 # count devices number try: total_devices_count = TokenV2.objects.get_total_devices_count() except Exception as e: logger.error(e) total_devices_count = 0 # count current connected devices try: current_connected_devices_count = TokenV2.objects.\ get_current_connected_devices_count() except Exception as e: logger.error(e) current_connected_devices_count = 0 info = { 'users_count': active_users + inactive_users, 'active_users_count': active_users, 'repos_count': repos_count, 'total_files_count': total_files_count, 'groups_count': groups_count, 'org_count': org_count, 'multi_tenancy_enabled': multi_tenancy_enabled, 'is_pro': is_pro, 'with_license': with_license, 'license_expiration': license_dict.get('Expiration', ''), 'license_mode': license_dict.get('Mode', ''), 'license_maxusers': max_users, 'license_to': license_dict.get('Name', ''), 'total_storage': total_storage, 'total_devices_count': total_devices_count, 'current_connected_devices_count': current_connected_devices_count } return Response(info)
def edit_profile(request): """ Show and edit user profile. """ username = request.user.username form_class = DetailedProfileForm if request.method == "POST": form = form_class(request.POST) if form.is_valid(): form.save(username=username) messages.success(request, _(u"Successfully edited profile.")) # refresh nickname cache refresh_cache(request.user.username) return HttpResponseRedirect(reverse("edit_profile")) else: messages.error(request, _(u"Failed to edit profile")) else: profile = Profile.objects.get_profile_by_user(username) d_profile = DetailedProfile.objects.get_detailed_profile_by_user(username) init_dict = {} if profile: init_dict["nickname"] = profile.nickname init_dict["intro"] = profile.intro if d_profile: init_dict["department"] = d_profile.department init_dict["telephone"] = d_profile.telephone form = form_class(init_dict) # common logic try: server_crypto = UserOptions.objects.is_server_crypto(username) except CryptoOptionNotSetError: # Assume server_crypto is ``False`` if this option is not set. server_crypto = False sub_lib_enabled = UserOptions.objects.is_sub_lib_enabled(username) default_repo_id = UserOptions.objects.get_default_repo(username) if default_repo_id: default_repo = seafile_api.get_repo(default_repo_id) else: default_repo = None owned_repos = get_owned_repo_list(request) return render_to_response( "profile/set_profile.html", { "form": form, "server_crypto": server_crypto, "sub_lib_enabled": sub_lib_enabled, "force_server_crypto": settings.FORCE_SERVER_CRYPTO, "default_repo": default_repo, "owned_repos": owned_repos, "is_pro": is_pro_version(), }, context_instance=RequestContext(request), )
def edit_profile(request): """ Show and edit user profile. """ username = request.user.username form_class = DetailedProfileForm if request.method == 'POST': form = form_class(user=request.user, data=request.POST) if form.is_valid(): form.save() messages.success(request, _(u'Successfully edited profile.')) return HttpResponseRedirect(reverse('edit_profile')) else: messages.error(request, _(u'Failed to edit profile')) else: profile = Profile.objects.get_profile_by_user(username) d_profile = DetailedProfile.objects.get_detailed_profile_by_user( username) init_dict = {} if profile: init_dict['nickname'] = profile.nickname init_dict['login_id'] = profile.login_id init_dict['contact_email'] = profile.contact_email init_dict['list_in_address_book'] = profile.list_in_address_book if d_profile: init_dict['department'] = d_profile.department init_dict['telephone'] = d_profile.telephone form = form_class(user=request.user, data=init_dict) # common logic try: server_crypto = UserOptions.objects.is_server_crypto(username) except CryptoOptionNotSetError: # Assume server_crypto is ``False`` if this option is not set. server_crypto = False sub_lib_enabled = UserOptions.objects.is_sub_lib_enabled(username) default_repo_id = UserOptions.objects.get_default_repo(username) if default_repo_id: default_repo = seafile_api.get_repo(default_repo_id) else: default_repo = None owned_repos = get_owned_repo_list(request) owned_repos = filter(lambda r: not r.is_virtual, owned_repos) if settings.ENABLE_WEBDAV_SECRET: decoded = UserOptions.objects.get_webdav_decoded_secret(username) webdav_passwd = decoded if decoded else '' else: webdav_passwd = '' email_inverval = UserOptions.objects.get_file_updates_email_interval(username) email_inverval = email_inverval if email_inverval is not None else 0 if settings.SOCIAL_AUTH_WEIXIN_WORK_KEY: enable_wechat_work = True from social_django.models import UserSocialAuth social_connected = UserSocialAuth.objects.filter( username=request.user.username, provider='weixin-work').count() > 0 else: enable_wechat_work = False social_connected = False resp_dict = { 'form': form, 'server_crypto': server_crypto, "sub_lib_enabled": sub_lib_enabled, 'ENABLE_ADDRESSBOOK_OPT_IN': settings.ENABLE_ADDRESSBOOK_OPT_IN, 'default_repo': default_repo, 'owned_repos': owned_repos, 'is_pro': is_pro_version(), 'is_ldap_user': is_ldap_user(request.user), 'two_factor_auth_enabled': has_two_factor_auth(), 'ENABLE_CHANGE_PASSWORD': settings.ENABLE_CHANGE_PASSWORD, 'ENABLE_WEBDAV_SECRET': settings.ENABLE_WEBDAV_SECRET, 'ENABLE_DELETE_ACCOUNT': ENABLE_DELETE_ACCOUNT, 'ENABLE_UPDATE_USER_INFO': ENABLE_UPDATE_USER_INFO, 'webdav_passwd': webdav_passwd, 'email_notification_interval': email_inverval, 'social_connected': social_connected, 'social_next_page': reverse('edit_profile'), 'enable_wechat_work': enable_wechat_work, 'ENABLE_USER_SET_CONTACT_EMAIL': settings.ENABLE_USER_SET_CONTACT_EMAIL, 'user_unusable_password': request.user.enc_password == UNUSABLE_PASSWORD, } if has_two_factor_auth(): from seahub.two_factor.models import StaticDevice, default_device try: backup_tokens = StaticDevice.objects.get( user=request.user.username).token_set.count() except StaticDevice.DoesNotExist: backup_tokens = 0 resp_dict['default_device'] = default_device(request.user) resp_dict['backup_tokens'] = backup_tokens #template = 'profile/set_profile.html' template = 'profile/set_profile_react.html' return render(request, template, resp_dict)
def get_available_repo_perms(): perms = [PERMISSION_READ, PERMISSION_READ_WRITE, PERMISSION_ADMIN] if is_pro_version(): perms += [PERMISSION_PREVIEW, PERMISSION_PREVIEW_EDIT] return perms
def has_permission(self, request, *args, **kwargs): return is_pro_version()