def seahub_filesizeformat(bytes): """ Formats the value like a 'human-readable' file size (i.e. 13 KB, 4.1 MB, 102 bytes, etc). """ try: bytes = float(bytes) except (TypeError, ValueError, UnicodeDecodeError): value = ungettext("%(size)d byte", "%(size)d bytes", 0) % {'size': 0} return avoid_wrapping(value) filesize_number_format = lambda value: formats.number_format(round(value, 1), 1) KB = get_file_size_unit('KB') MB = get_file_size_unit('MB') GB = get_file_size_unit('GB') TB = get_file_size_unit('TB') PB = get_file_size_unit('PB') if bytes < KB: value = ungettext("%(size)d byte", "%(size)d bytes", bytes) % {'size': bytes} elif bytes < MB: value = ugettext("%s KB") % filesize_number_format(bytes / KB) elif bytes < GB: value = ugettext("%s MB") % filesize_number_format(bytes / MB) elif bytes < TB: value = ugettext("%s GB") % filesize_number_format(bytes / GB) elif bytes < PB: value = ugettext("%s TB") % filesize_number_format(bytes / TB) else: value = ugettext("%s PB") % filesize_number_format(bytes / PB) return avoid_wrapping(value)
def org_user_set_quota(request, email): if not request.is_ajax() or request.method != 'POST': raise Http404 ct = 'application/json; charset=utf-8' result = {} if not is_valid_username(email): result['error'] = 'Failed to set quota: invalid email' return HttpResponse(json.dumps(result), status=400, content_type=ct) org_id = request.user.org.org_id # check whether user belong to that org if not seaserv.org_user_exists(org_id, email): raise Http404 quota_mb = int(request.POST.get('quota', 0)) quota = quota_mb * get_file_size_unit('mb') org_quota_mb = get_org_quota(org_id) / get_file_size_unit('mb') if quota_mb > org_quota_mb: result['error'] = _(u'Failed to set quota: maximum quota is %d MB' % \ org_quota_mb) return HttpResponse(json.dumps(result), status=400, content_type=ct) try: seaserv.seafserv_threaded_rpc.set_org_user_quota(org_id, email, quota) except SearpcError as e: logger.error(e) result['error'] = 'Failed to set quota: internal error' return HttpResponse(json.dumps(result), status=500, content_type=ct) result['success'] = True return HttpResponse(json.dumps(result), content_type=ct)
def user_set_quota(request, email): if request.method != 'POST': raise Http404 content_type = 'application/json; charset=utf-8' result = {} f = SetUserQuotaForm(request.POST) if f.is_valid(): space_quota_mb = f.cleaned_data['space_quota'] space_quota = space_quota_mb * get_file_size_unit('MB') org = ccnet_api.get_orgs_by_user(email) try: if not org: seafile_api.set_user_quota(email, space_quota) else: org_id = org[0].org_id org_quota_mb = seafserv_threaded_rpc.get_org_quota(org_id) / get_file_size_unit('MB') if space_quota_mb > org_quota_mb: result['error'] = _('Failed to set quota: maximum quota is %d MB' % \ org_quota_mb) return HttpResponse(json.dumps(result), status=400, content_type=content_type) else: seafile_api.set_org_user_quota(org_id, email, space_quota) except: result['error'] = _('Failed to set quota: internal server error') return HttpResponse(json.dumps(result), status=500, content_type=content_type) result['success'] = True return HttpResponse(json.dumps(result), content_type=content_type) else: result['error'] = str(list(f.errors.values())[0]) return HttpResponse(json.dumps(result), status=400, content_type=content_type)
def test_valid_type(self): assert get_file_size_unit('KB') == 1000 ** 1 assert get_file_size_unit('MB') == 1000 ** 2 assert get_file_size_unit('GB') == 1000 ** 3 assert get_file_size_unit('TB') == 1000 ** 4 assert get_file_size_unit('PB') == 1000 ** 5 assert get_file_size_unit('KiB') == 1024 ** 1 assert get_file_size_unit('MiB') == 1024 ** 2 assert get_file_size_unit('GiB') == 1024 ** 3 assert get_file_size_unit('TiB') == 1024 ** 4 assert get_file_size_unit('PiB') == 1024 ** 5
def get_org_user_info(self, user, org): user_info = {} user_info['org_id'] = org.org_id user_info['active'] = user.is_active user_info['email'] = user.email user_info['name'] = email2nickname(user.email) user_info['contact_email'] = email2contact_email(user.email) org_user_quota = seafile_api.get_org_user_quota(org.org_id, user.email) user_info['quota_total'] = org_user_quota / get_file_size_unit('MB') org_user_quota_usage = seafile_api.get_org_user_quota_usage(org.org_id, user.email) user_info['quota_usage'] = org_user_quota_usage / get_file_size_unit('MB') return user_info
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 get_org_user_info(org_id, email): user_info = {} user_obj = User.objects.get(email=email) user_info['org_id'] = org_id user_info['active'] = user_obj.is_active user_info['email'] = email user_info['name'] = email2nickname(email) user_info['contact_email'] = email2contact_email(email) org_user_quota = seafile_api.get_org_user_quota(org_id, email) user_info['quota_total'] = org_user_quota / get_file_size_unit('MB') org_user_quota_usage = seafile_api.get_org_user_quota_usage(org_id, email) user_info['quota_usage'] = org_user_quota_usage / get_file_size_unit('MB') return user_info
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 _update_account_additional_info(self, request, email): # update account profile name = request.data.get("name", None) if name is not None: profile = Profile.objects.get_profile_by_user(email) if profile is None: profile = Profile(user=email) profile.nickname = name profile.save() # update account loginid loginid = request.data.get("login_id", '').strip() if loginid != '': profile = Profile.objects.get_profile_by_user(email) if profile is None: profile = Profile(user=email) profile.login_id = loginid profile.save() # update account detailed profile department = request.data.get("department", None) if department is not None: 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() # update user quota space_quota_mb = request.data.get("storage", None) if space_quota_mb is not None: space_quota = int(space_quota_mb) * get_file_size_unit('MB') if is_org_context(request): org_id = request.user.org.org_id seaserv.seafserv_threaded_rpc.set_org_user_quota(org_id, email, space_quota) else: seafile_api.set_user_quota(email, space_quota) # update is_trial is_trial = request.data.get("is_trial", None) if is_trial is not None: try: from seahub_extra.trialaccount.models import TrialAccount except ImportError: pass else: if is_trial is True: expire_date = timezone.now() + relativedelta(days=7) TrialAccount.object.create_or_update(email, expire_date) else: TrialAccount.objects.filter(user_or_org=email).delete()
def test_update_quota_total(self): self.login_as(self.admin) # change user name quota_total = 1232 data = {"email": self.tmp_email, "quota_total": quota_total} resp = self.client.put(self.url, json.dumps(data), 'application/json') json_resp = json.loads(resp.content) self.assertEqual(200, resp.status_code) quota_total_mb = quota_total * get_file_size_unit('mb') assert json_resp['quota_total'] == quota_total_mb assert seafile_api.get_user_quota(self.tmp_email) == quota_total_mb
def user_set_quota(request, email): content_type = 'application/json; charset=utf-8' quota_mb = int(request.POST.get('space_quota', 0)) quota = quota_mb * get_file_size_unit('MB') available_quota = get_institution_available_quota(request.user.institution) if available_quota < quota: result = {} result['error'] = _(u'Failed to set quota: maximum quota is %d MB' % \ (available_quota / 10 ** 6)) return HttpResponse(json.dumps(result), status=400, content_type=content_type) seafile_api.set_user_quota(email, quota) return HttpResponse(json.dumps({'success': True}), content_type=content_type)
def create_org(self, username=org_user_name, password=org_user_password, org_name='org', prefix='org_p', quota=100, member_limit=100): new_org = ccnet_threaded_rpc.get_org_by_url_prefix(prefix) if new_org: return new_org quota = int(quota) User.objects.create_user(username, password, is_staff=False, is_active=True) create_org(org_name, prefix, username) new_org = ccnet_threaded_rpc.get_org_by_url_prefix(prefix) from seahub_extra.organizations.models import OrgMemberQuota OrgMemberQuota.objects.set_quota(new_org.org_id, member_limit) quota = quota * get_file_size_unit('MB') seafserv_threaded_rpc.set_org_quota(new_org.org_id, quota) return new_org
def put(self, request, institution_id): """Update (quota) of institution """ if not request.user.admin_permissions.other_permission(): return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.') try: institution = Institution.objects.get(id=institution_id) except Exception as e: logger.error(e) error_msg = "institution %s not found." % institution_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) quota_mb = request.data.get('quota', '') try: quota_mb = int(quota_mb) except Exception as e: logger.error(e) error_msg = 'quota invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) quota = quota_mb * get_file_size_unit('MB') try: InstitutionQuota.objects.update_or_create( institution=institution, defaults={'quota': quota}, ) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) info = {} info['id'] = institution.id info['name'] = institution.name info['user_count'] = Profile.objects.filter(institution=institution.name).count() info['quota_total'] = InstitutionQuota.objects.get_or_none(institution=institution) info['quota_used'] = get_institution_space_usage(institution) return Response(info)
def sys_org_set_quota(request, org_id): if request.method != 'POST': raise Http404 content_type = 'application/json; charset=utf-8' result = {} org_id = int(org_id) quota_mb = int(request.POST.get('quota', 0)) quota = quota_mb * get_file_size_unit('MB') try: seafserv_threaded_rpc.set_org_quota(org_id, quota) except SearpcError as e: logger.error(e) result['error'] = _('Failed to set quota: internal server error') return HttpResponse(json.dumps(result), status=500, content_type=content_type) result['success'] = True return HttpResponse(json.dumps(result), content_type=content_type)
def create_user_info(request, email, role, nickname, contact_email, quota_total_mb): # 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 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 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 sys_useradmin_export_excel(request): """ Export all users from database to excel """ next_page = request.META.get('HTTP_REFERER', None) if not next_page: next_page = SITE_ROOT try: users = ccnet_api.get_emailusers('DB', -1, -1) + \ ccnet_api.get_emailusers('LDAPImport', -1, -1) except Exception as e: logger.error(e) messages.error(request, _('Failed to export Excel')) return HttpResponseRedirect(next_page) if is_pro_version(): is_pro = True else: is_pro = False if is_pro: head = [ _("Email"), _("Name"), _("Contact Email"), _("Status"), _("Role"), _("Space Usage") + "(MB)", _("Space Quota") + "(MB)", _("Create At"), _("Last Login"), _("Admin"), _("LDAP(imported)"), ] else: head = [ _("Email"), _("Name"), _("Contact Email"), _("Status"), _("Space Usage") + "(MB)", _("Space Quota") + "(MB)", _("Create At"), _("Last Login"), _("Admin"), _("LDAP(imported)"), ] # only operate 100 users for every `for` loop looped = 0 limit = 100 data_list = [] while looped < len(users): current_users = users[looped:looped + limit] last_logins = UserLastLogin.objects.filter(username__in=[x.email \ for x in current_users]) user_profiles = Profile.objects.filter(user__in=[x.email \ for x in current_users]) for user in current_users: # populate name and contact email user.contact_email = '' user.name = '' for profile in user_profiles: if profile.user == user.email: user.contact_email = profile.contact_email user.name = profile.nickname # populate space usage and quota MB = get_file_size_unit('MB') _populate_user_quota_usage(user) if user.space_usage > 0: try: space_usage_MB = round(float(user.space_usage) / MB, 2) except Exception as e: logger.error(e) space_usage_MB = '--' else: space_usage_MB = '' if user.space_quota > 0: try: space_quota_MB = round(float(user.space_quota) / MB, 2) except Exception as e: logger.error(e) space_quota_MB = '--' else: space_quota_MB = '' # 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 if user.is_active: status = _('Active') else: status = _('Inactive') create_at = tsstr_sec(user.ctime) if user.ctime else '' last_login = user.last_login.strftime("%Y-%m-%d %H:%M:%S") if \ user.last_login else '' is_admin = _('Yes') if user.is_staff else '' ldap_import = _('Yes') if user.source == 'LDAPImport' else '' if is_pro: if user.role: if user.role == GUEST_USER: role = _('Guest') elif user.role == DEFAULT_USER: role = _('Default') else: role = user.role else: role = _('Default') row = [ user.email, user.name, user.contact_email, status, role, space_usage_MB, space_quota_MB, create_at, last_login, is_admin, ldap_import ] else: row = [ user.email, user.name, user.contact_email, status, space_usage_MB, space_quota_MB, create_at, last_login, is_admin, ldap_import ] data_list.append(row) # update `looped` value when `for` loop finished looped += limit wb = write_xls('users', head, data_list) if not wb: messages.error(request, _('Failed to export Excel')) return HttpResponseRedirect(next_page) response = HttpResponse(content_type='application/ms-excel') response['Content-Disposition'] = 'attachment; filename=users.xlsx' wb.save(response) return response
def put(self, request, email): if not request.user.admin_permissions.can_manage_user(): return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.') # basic user info check is_staff = request.data.get("is_staff", None) if is_staff: try: is_staff = to_python_boolean(is_staff) except ValueError: error_msg = 'is_staff invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) is_active = request.data.get("is_active", None) if is_active: try: is_active = to_python_boolean(is_active) except ValueError: error_msg = 'is_active invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # additional user info check role = request.data.get("role", None) if role: available_roles = get_available_roles() if role not in available_roles: error_msg = 'role must be in %s.' % str(available_roles) return api_error(status.HTTP_400_BAD_REQUEST, error_msg) name = request.data.get("name", None) if name: if len(name) > 64: error_msg = 'Name is too long (maximum is 64 characters).' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if "/" in name: error_msg = "Name should not include '/'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # argument check for login_id login_id = request.data.get("login_id", None) if login_id is not None: login_id = login_id.strip() username_by_login_id = Profile.objects.get_username_by_login_id( login_id) if username_by_login_id is not None: return api_error(status.HTTP_400_BAD_REQUEST, _("Login id %s already exists." % login_id)) contact_email = request.data.get("contact_email", None) if contact_email is not None and contact_email.strip() != '': if not is_valid_email(contact_email): error_msg = 'Contact email invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) password = request.data.get("password") reference_id = request.data.get("reference_id", None) if reference_id: if ' ' in reference_id: return api_error(status.HTTP_400_BAD_REQUEST, 'Reference ID can not contain spaces.') primary_id = ccnet_api.get_primary_id(reference_id) if primary_id: return api_error( status.HTTP_400_BAD_REQUEST, 'Reference ID %s already exists.' % reference_id) quota_total_mb = request.data.get("quota_total", None) if quota_total_mb: try: quota_total_mb = int(quota_total_mb) except ValueError: error_msg = "Must be an integer that is greater than or equal to 0." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if quota_total_mb < 0: error_msg = "Space quota is too low (minimum value is 0)." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if is_org_context(request): org_id = request.user.org.org_id org_quota_mb = seafile_api.get_org_quota(org_id) / \ get_file_size_unit('MB') if quota_total_mb > org_quota_mb: error_msg = 'Failed to set quota: maximum quota is %d MB' % org_quota_mb return api_error(status.HTTP_400_BAD_REQUEST, error_msg) institution = request.data.get("institution", None) if institution: try: Institution.objects.get(name=institution) except Institution.DoesNotExist: error_msg = 'Institution %s does not exist' % institution return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # query user info try: user_obj = User.objects.get(email=email) except User.DoesNotExist: error_msg = 'User %s not found.' % email return api_error(status.HTTP_404_NOT_FOUND, error_msg) try: update_user_info(request, user=user_obj, password=password, is_active=is_active, is_staff=is_staff, role=role, nickname=name, login_id=login_id, contact_email=contact_email, reference_id=reference_id, quota_total_mb=quota_total_mb, institution_name=institution) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) # update user try: user_obj.save() except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) update_status_tip = '' if is_active is not None: update_status_tip = _('Edit succeeded') if user_obj.is_active and IS_EMAIL_CONFIGURED: try: send_html_email( _(u'Your account on %s is activated') % get_site_name(), 'sysadmin/user_activation_email.html', {'username': user_obj.email}, None, [email2contact_email(user_obj.email)]) update_status_tip = _( 'Edit succeeded, an email has been sent.') except Exception as e: logger.error(e) update_status_tip = _( 'Edit succeeded, but failed to send email, please check your email configuration.' ) user_info = get_user_info(email) user_info['update_status_tip'] = update_status_tip return Response(user_info)
def post(self, request): """ Set user quota, set user institution, delete users, in batch. Permission checking: 1. admin user. """ # argument check emails = request.POST.getlist('email', None) if not emails: error_msg = 'email invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) operation = request.POST.get('operation', None) if operation not in ('set-quota', 'delete-user', 'set-institution'): error_msg = "operation can only be 'set-quota', 'delete-user', or 'set-institution'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) result = {} result['failed'] = [] result['success'] = [] existed_users = [] for email in emails: try: user = User.objects.get(email=email) existed_users.append(user) except User.DoesNotExist: result['failed'].append({ 'email': email, 'error_msg': 'User %s not found.' % email }) continue if operation == 'set-quota': quota_total_mb = request.POST.get('quota_total', None) if not quota_total_mb: error_msg = 'quota_total invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: quota_total_mb = int(quota_total_mb) except ValueError: error_msg = _('must be an integer that is greater than or equal to 0.') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if quota_total_mb < 0: error_msg = _('Space quota is too low (minimum value is 0)') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) quota_total_byte = quota_total_mb * get_file_size_unit('MB') for user in existed_users: email = user.email try: seafile_api.set_user_quota(email, quota_total_byte) except Exception as e: logger.error(e) result['failed'].append({ 'email': email, 'error_msg': 'Internal Server Error' }) continue result['success'].append({ 'email': email, 'quota_total': seafile_api.get_user_quota(email), }) if operation == 'delete-user': for user in existed_users: email = user.email try: user.delete() except Exception as e: logger.error(e) result['failed'].append({ 'email': email, 'error_msg': 'Internal Server Error' }) continue result['success'].append({ 'email': email, }) # send admin operation log signal admin_op_detail = { "email": email, } admin_operation.send(sender=None, admin_name=request.user.username, operation=USER_DELETE, detail=admin_op_detail) if operation == 'set-institution': institution = request.POST.get('institution', None) if institution is None: error_msg = 'Institution can not be blank.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if institution != '': try: obj_insti = Institution.objects.get(name=institution) except Institution.DoesNotExist: error_msg = 'Institution %s does not exist' % institution return api_error(status.HTTP_400_BAD_REQUEST, error_msg) for user in existed_users: email = user.email profile = Profile.objects.get_profile_by_user(email) if profile is None: profile = Profile(user=email) profile.institution = institution profile.save() result['success'].append({ 'email': email, 'institution': institution }) return Response(result)
def put(self, request, email): # basic user info check is_staff = request.data.get("is_staff", None) if is_staff: try: is_staff = to_python_boolean(is_staff) except ValueError: error_msg = 'is_staff invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) is_active = request.data.get("is_active", None) if is_active: try: is_active = to_python_boolean(is_active) except ValueError: error_msg = 'is_active invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # additional user info check role = request.data.get("role", None) if role: available_roles = get_available_roles() if role.lower() not in available_roles: error_msg = 'role must be in %s.' % str(available_roles) return api_error(status.HTTP_400_BAD_REQUEST, error_msg) name = request.data.get("name", None) if name: if len(name) > 64: error_msg = 'Name is too long (maximum is 64 characters).' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if "/" in name: error_msg = "Name should not include '/'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # argument check for login_id login_id = request.data.get("login_id", None) if login_id is not None: login_id = login_id.strip() username_by_login_id = Profile.objects.get_username_by_login_id(login_id) if username_by_login_id is not None: return api_error(status.HTTP_400_BAD_REQUEST, _(u"Login id %s already exists." % login_id)) contact_email = request.data.get("contact_email", None) if contact_email is not None and contact_email.strip() != '': if not is_valid_email(contact_email): error_msg = 'Contact email invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) profile = Profile.objects.get_profile_by_contact_email(contact_email) if profile: error_msg = 'Contact email %s already exists.' % contact_email return api_error(status.HTTP_400_BAD_REQUEST, error_msg) reference_id = request.data.get("reference_id", "") if reference_id: if ' ' in reference_id: return api_error(status.HTTP_400_BAD_REQUEST, 'Reference ID can not contain spaces.') primary_id = ccnet_api.get_primary_id(reference_id) if primary_id: return api_error(status.HTTP_400_BAD_REQUEST, 'Reference ID %s already exists.' % reference_id) department = request.data.get("department", None) if department: if len(department) > 512: error_msg = "Department is too long (maximum is 512 characters)." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) quota_total_mb = request.data.get("quota_total", None) if quota_total_mb: try: quota_total_mb = int(quota_total_mb) except ValueError: error_msg = "Must be an integer that is greater than or equal to 0." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if quota_total_mb < 0: error_msg = "Space quota is too low (minimum value is 0)." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if is_org_context(request): org_id = request.user.org.org_id org_quota_mb = seafile_api.get_org_quota(org_id) / \ get_file_size_unit('MB') if quota_total_mb > org_quota_mb: error_msg = 'Failed to set quota: maximum quota is %d MB' % org_quota_mb return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # query user info try: user_obj = User.objects.get(email=email) except User.DoesNotExist: error_msg = 'User %s not found.' % email return api_error(status.HTTP_404_NOT_FOUND, error_msg) try: update_user_info(request, user_obj) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) user_info = get_user_info(email) return Response(user_info)
def post(self, request): if not request.user.admin_permissions.can_manage_user(): return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.') if user_number_over_limit(): error_msg = _("The number of users exceeds the limit.") return api_error(status.HTTP_400_BAD_REQUEST, error_msg) email = request.data.get('email', None) if not email or not is_valid_email(email): error_msg = 'email invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # basic user info check is_staff = request.data.get("is_staff", 'False') try: is_staff = to_python_boolean(is_staff) except ValueError: error_msg = 'is_staff invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) is_active = request.data.get("is_active", 'True') try: is_active = to_python_boolean(is_active) except ValueError: error_msg = 'is_active invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # additional user info check role = '' if is_pro_version(): role = request.data.get("role", None) if role: available_roles = get_available_roles() if role not in available_roles: error_msg = 'role must be in %s.' % str(available_roles) return api_error(status.HTTP_400_BAD_REQUEST, error_msg) name = request.data.get("name", None) if name: if len(name) > 64: error_msg = 'Name is too long (maximum is 64 characters).' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if "/" in name: error_msg = "Name should not include '/'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) contact_email = request.data.get('contact_email', None) if contact_email and not is_valid_email(contact_email): error_msg = 'contact_email invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) quota_total_mb = request.data.get("quota_total", None) if quota_total_mb: try: quota_total_mb = int(quota_total_mb) except ValueError: error_msg = "Must be an integer that is greater than or equal to 0." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if quota_total_mb < 0: error_msg = "Space quota is too low (minimum value is 0)." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if is_org_context(request): org_id = request.user.org.org_id org_quota_mb = seafile_api.get_org_quota(org_id) / \ get_file_size_unit('MB') if quota_total_mb > org_quota_mb: error_msg = 'Failed to set quota: maximum quota is %d MB' % org_quota_mb return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: User.objects.get(email=email) user_exist = True except User.DoesNotExist: user_exist = False if user_exist: error_msg = "User %s already exists." % email return api_error(status.HTTP_400_BAD_REQUEST, error_msg) password = request.data.get('password', None) if not password: error_msg = 'password required.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # create user try: user_obj = User.objects.create_user(email, password, is_staff, is_active) create_user_info(request, email=user_obj.username, role=role, nickname=name, contact_email=contact_email, quota_total_mb=quota_total_mb) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) add_user_tip = _('Successfully added user %(user)s.') % {'user': email} if IS_EMAIL_CONFIGURED and SEND_EMAIL_ON_ADDING_SYSTEM_MEMBER: c = { 'user': request.user.username, 'email': email, 'password': password } try: send_html_email( _('You are invited to join %s') % get_site_name(), 'sysadmin/user_add_email.html', c, None, [email2contact_email(email)]) add_user_tip = _( 'Successfully added user %(user)s. An email notification has been sent.' ) % { 'user': email } except Exception as e: logger.error(str(e)) add_user_tip = _( 'Successfully added user %(user)s. But email notification can not be sent, because Email service is not properly configured.' ) % { 'user': email } user_info = get_user_info(email) user_info['add_user_tip'] = add_user_tip # send admin operation log signal admin_op_detail = { "email": email, } admin_operation.send(sender=None, admin_name=request.user.username, operation=USER_ADD, detail=admin_op_detail) return Response(user_info)
def handle(self, *args, **options): self.stdout.write("Export users to '../users.xlsx'.") try: users = ccnet_api.get_emailusers('DB', -1, -1) + \ ccnet_api.get_emailusers('LDAPImport', -1, -1) except Exception as e: self.stdout.write('Error: ' + str(e)) return if is_pro_version(): is_pro = True else: is_pro = False if is_pro: head = [ _("Email"), _("Name"), _("Contact Email"), _("Status"), _("Role"), _("Space Usage") + "(MB)", _("Space Quota") + "(MB)", _("Create At"), _("Last Login"), _("Admin"), _("LDAP(imported)"), ] else: head = [ _("Email"), _("Name"), _("Contact Email"), _("Status"), _("Space Usage") + "(MB)", _("Space Quota") + "(MB)", _("Create At"), _("Last Login"), _("Admin"), _("LDAP(imported)"), ] # only operate 100 users for every `for` loop looped = 0 limit = 100 data_list = [] while looped < len(users): current_users = users[looped:looped + limit] last_logins = UserLastLogin.objects.filter(username__in=[x.email \ for x in current_users]) user_profiles = Profile.objects.filter(user__in=[x.email \ for x in current_users]) for user in current_users: # populate name and contact email user.contact_email = '' user.name = '' for profile in user_profiles: if profile.user == user.email: user.contact_email = profile.contact_email user.name = profile.nickname # populate space usage and quota MB = get_file_size_unit('MB') # populate user quota usage orgs = ccnet_api.get_orgs_by_user(user.email) try: if orgs: user.org = orgs[0] org_id = user.org.org_id user.space_usage = seafile_api.get_org_user_quota_usage( org_id, user.email) user.space_quota = seafile_api.get_org_user_quota( org_id, user.email) else: user.space_usage = seafile_api.get_user_self_usage( user.email) user.space_quota = seafile_api.get_user_quota( user.email) except Exception as e: self.stdout.write('Debug: ' + str(e)) user.space_usage = -1 user.space_quota = -1 if user.space_usage > 0: try: space_usage_MB = round(float(user.space_usage) / MB, 2) except Exception as e: self.stdout.write('Debug: ' + str(e)) space_usage_MB = '--' else: space_usage_MB = '' if user.space_quota > 0: try: space_quota_MB = round(float(user.space_quota) / MB, 2) except Exception as e: self.stdout.write('Debug: ' + str(e)) space_quota_MB = '--' else: space_quota_MB = '' # 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 if user.is_active: status = _('Active') else: status = _('Inactive') create_at = tsstr_sec(user.ctime) if user.ctime else '' last_login = user.last_login.strftime("%Y-%m-%d %H:%M:%S") if \ user.last_login else '' is_admin = _('Yes') if user.is_staff else '' ldap_import = _('Yes') if user.source == 'LDAPImport' else '' if is_pro: if user.role: if user.role == GUEST_USER: role = _('Guest') elif user.role == DEFAULT_USER: role = _('Default') else: role = user.role else: role = _('Default') row = [ user.email, user.name, user.contact_email, status, role, space_usage_MB, space_quota_MB, create_at, last_login, is_admin, ldap_import ] else: row = [ user.email, user.name, user.contact_email, status, space_usage_MB, space_quota_MB, create_at, last_login, is_admin, ldap_import ] data_list.append(row) # update `looped` value when `for` loop finished looped += limit wb = write_xls('users', head, data_list) if not wb: self.stdout.write('Error: please check the log.') return wb.save('../users.xlsx') self.stdout.write('Done.\n')
def put(self, request, email): # basic user info check is_staff = request.data.get("is_staff", None) if is_staff: try: is_staff = to_python_boolean(is_staff) except ValueError: error_msg = 'is_staff invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) is_active = request.data.get("is_active", None) if is_active: try: is_active = to_python_boolean(is_active) except ValueError: error_msg = 'is_active invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # additional user info check role = request.data.get("role", None) if role: available_roles = get_available_roles() if role.lower() not in available_roles: error_msg = 'role must be in %s.' % str(available_roles) return api_error(status.HTTP_400_BAD_REQUEST, error_msg) name = request.data.get("name", None) if name: if len(name) > 64: error_msg = 'Name is too long (maximum is 64 characters).' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if "/" in name: error_msg = "Name should not include '/'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # argument check for login_id login_id = request.data.get("login_id", None) if login_id is not None: login_id = login_id.strip() username_by_login_id = Profile.objects.get_username_by_login_id( login_id) if username_by_login_id is not None: return api_error(status.HTTP_400_BAD_REQUEST, _(u"Login id %s already exists." % login_id)) reference_id = request.data.get("reference_id", "").strip() if reference_id: if ' ' in reference_id: return api_error(status.HTTP_400_BAD_REQUEST, 'Reference ID can not contain spaces.') primary_id = ccnet_api.get_primary_id(reference_id) if primary_id: return api_error( status.HTTP_400_BAD_REQUEST, 'Reference ID %s already exists.' % reference_id) department = request.data.get("department", None) if department: if len(department) > 512: error_msg = "Department is too long (maximum is 512 characters)." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) quota_total_mb = request.data.get("quota_total", None) if quota_total_mb: try: quota_total_mb = int(quota_total_mb) except ValueError: error_msg = "Must be an integer that is greater than or equal to 0." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if quota_total_mb < 0: error_msg = "Space quota is too low (minimum value is 0)." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if is_org_context(request): org_id = request.user.org.org_id org_quota_mb = seafile_api.get_org_quota(org_id) / \ get_file_size_unit('MB') if quota_total_mb > org_quota_mb: error_msg = 'Failed to set quota: maximum quota is %d MB' % org_quota_mb return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # query user info try: user_obj = User.objects.get(email=email) except User.DoesNotExist: error_msg = 'User %s not found.' % email return api_error(status.HTTP_404_NOT_FOUND, error_msg) try: update_user_info(request, user_obj) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) user_info = get_user_info(email) return Response(user_info)
def put(self, request, email, format=None): # argument check for email if not is_valid_username(email): return api_error(status.HTTP_400_BAD_REQUEST, 'Email %s invalid.' % email) # argument check for name name = request.data.get("name", None) if name is not None: if len(name) > 64: return api_error(status.HTTP_400_BAD_REQUEST, _(u'Name is too long (maximum is 64 characters)')) if "/" in name: return api_error(status.HTTP_400_BAD_REQUEST, _(u"Name should not include '/'.")) # argument check for list_in_address_book list_in_address_book = request.data.get("list_in_address_book", None) if list_in_address_book is not None: if list_in_address_book.lower() not in ('true', 'false'): return api_error(status.HTTP_400_BAD_REQUEST, 'list_in_address_book invalid') #argument check for loginid loginid = request.data.get("login_id", None) if loginid is not None: loginid = loginid.strip() if loginid == "": return api_error(status.HTTP_400_BAD_REQUEST, _(u"Login id can't be empty")) usernamebyloginid = Profile.objects.get_username_by_login_id(loginid) if usernamebyloginid is not None: return api_error(status.HTTP_400_BAD_REQUEST, _(u"Login id %s already exists." % loginid)) # argument check for department department = request.data.get("department", None) if department is not None: if len(department) > 512: return api_error(status.HTTP_400_BAD_REQUEST, _(u'Department is too long (maximum is 512 characters)')) # argument check for institution institution = request.data.get("institution", None) if institution is not None and institution != '': try: obj_insti = Institution.objects.get(name=institution) except Institution.DoesNotExist: return api_error(status.HTTP_400_BAD_REQUEST, "Institution %s does not exist" % institution) # argument check for storage space_quota_mb = request.data.get("storage", None) if space_quota_mb is not None: if space_quota_mb == '': return api_error(status.HTTP_400_BAD_REQUEST, _('Space quota can\'t be empty')) try: space_quota_mb = int(space_quota_mb) except ValueError: return api_error(status.HTTP_400_BAD_REQUEST, _('Must be an integer that is greater than or equal to 0.')) if space_quota_mb < 0: return api_error(status.HTTP_400_BAD_REQUEST, _('Space quota is too low (minimum value is 0)')) if is_org_context(request): org_id = request.user.org.org_id org_quota_mb = seaserv.seafserv_threaded_rpc.get_org_quota(org_id) / \ get_file_size_unit('MB') if space_quota_mb > org_quota_mb: return api_error(status.HTTP_400_BAD_REQUEST, \ _(u'Failed to set quota: maximum quota is %d MB' % org_quota_mb)) # argument check for is_trial is_trial = request.data.get("is_trial", None) if is_trial is not None: try: is_trial = to_python_boolean(is_trial) except ValueError: return api_error(status.HTTP_400_BAD_REQUEST, 'is_trial invalid') try: # update account basic info user = User.objects.get(email=email) # argument check for is_staff is_staff = request.data.get("is_staff", None) if is_staff is not None: try: is_staff = to_python_boolean(is_staff) except ValueError: return api_error(status.HTTP_400_BAD_REQUEST, 'is_staff invalid.') user.is_staff = is_staff # argument check for is_active is_active = request.data.get("is_active", None) if is_active is not None: try: is_active = to_python_boolean(is_active) except ValueError: return api_error(status.HTTP_400_BAD_REQUEST, 'is_active invalid.') user.is_active = is_active # update password password = request.data.get("password", None) if password is not None: user.set_password(password) # save user result_code = user.save() if result_code == -1: return api_error(status.HTTP_520_OPERATION_FAILED, 'Failed to update user.') try: # update account additional info self._update_account_additional_info(request, email) except Exception as e: logger.error(e) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error') # get account info and return info = get_account_info(user) return Response(info) except User.DoesNotExist: # create user account copy = request.data.copy() copy['email'] = email serializer = AccountSerializer(data=copy) if not serializer.is_valid(): return api_error(status.HTTP_400_BAD_REQUEST, serializer.errors) try: user = User.objects.create_user(serializer.data['email'], serializer.data['password'], serializer.data['is_staff'], serializer.data['is_active']) except User.DoesNotExist as e: logger.error(e) return api_error(status.HTTP_520_OPERATION_FAILED, 'Failed to add user.') try: # update account additional info self._update_account_additional_info(request, email) except Exception as e: logger.error(e) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error') # get account info and return info = get_account_info(user) resp = Response(info, status=status.HTTP_201_CREATED) resp['Location'] = reverse('api2-account', args=[email]) return resp
def _update_account_additional_info(self, request, email): # update account name name = request.data.get("name", None) if name is not None: profile = Profile.objects.get_profile_by_user(email) if profile is None: profile = Profile(user=email) profile.nickname = name profile.save() # update account list_in_address_book list_in_address_book = request.data.get("list_in_address_book", None) if list_in_address_book is not None: profile = Profile.objects.get_profile_by_user(email) if profile is None: profile = Profile(user=email) profile.list_in_address_book = list_in_address_book.lower() == 'true' profile.save() # update account loginid loginid = request.data.get("login_id", '').strip() if loginid != '': profile = Profile.objects.get_profile_by_user(email) if profile is None: profile = Profile(user=email) profile.login_id = loginid profile.save() # update account detailed profile department = request.data.get("department", None) if department is not None: 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() # update user quota space_quota_mb = request.data.get("storage", None) if space_quota_mb is not None: space_quota = int(space_quota_mb) * get_file_size_unit('MB') if is_org_context(request): org_id = request.user.org.org_id seaserv.seafserv_threaded_rpc.set_org_user_quota(org_id, email, space_quota) else: seafile_api.set_user_quota(email, space_quota) # update user institution institution = request.data.get("institution", None) if institution is not None: profile = Profile.objects.get_profile_by_user(email) if profile is None: profile = Profile(user=email) profile.institution = institution profile.save() # update is_trial is_trial = request.data.get("is_trial", None) if is_trial is not None: try: from seahub_extra.trialaccount.models import TrialAccount except ImportError: pass else: if is_trial is True: expire_date = timezone.now() + relativedelta(days=7) TrialAccount.object.create_or_update(email, expire_date) else: TrialAccount.objects.filter(user_or_org=email).delete()
def put(self, request, org_id, email): """ update base info of a org user Permission checking: 1. only admin can perform this action. """ try: user = User.objects.get(email=email) except User.DoesNotExist: error_msg = 'User %s not found.' % email return api_error(status.HTTP_404_NOT_FOUND, error_msg) # update active active = request.data.get('active', None) if active: active = active.lower() if active not in ('true', 'false'): error_msg = "active invalid, should be 'true' or 'false'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if active == 'true': user.is_active = True else: user.is_active = False try: # update user status result_code = user.save() except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if result_code == -1: error_msg = 'Fail to update user %s.' % email return api_error(status.HTTP_403_FORBIDDEN, error_msg) # update name name = request.data.get('name', None) if name: profile = Profile.objects.get_profile_by_user(email) if profile is None: profile = Profile(user=email) profile.nickname = name profile.save() # update contact_email contact_email = request.data.get('contact_email', None) if contact_email: profile = Profile.objects.get_profile_by_user(email) if profile is None: profile = Profile(user=email) profile.contact_email = contact_email profile.save() # update user quota user_quota_mb = request.data.get("quota_total", None) if user_quota_mb: try: user_quota_mb = int(user_quota_mb) except Exception as e: logger.error(e) error_msg = "quota_total invalid." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) user_quota = int(user_quota_mb) * get_file_size_unit('MB') org_quota = seafile_api.get_org_quota(org_id) # -1 means org has unlimited quota if org_quota > 0: org_quota_mb = org_quota / get_file_size_unit('MB') if user_quota_mb > org_quota_mb: error_msg = 'Failed to set quota: maximum quota is %d MB' % org_quota_mb return api_error(status.HTTP_400_BAD_REQUEST, error_msg) seafile_api.set_org_user_quota(org_id, email, user_quota) user_info = get_org_user_info(org_id, email) user_info['active'] = user.is_active return Response(user_info)
def put(self, request, org_id, email): """ update base info of a org user Permission checking: 1. only admin can perform this action. """ if not request.user.admin_permissions.other_permission(): return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.') try: user = User.objects.get(email=email) except User.DoesNotExist: error_msg = 'User %s not found.' % email return api_error(status.HTTP_404_NOT_FOUND, error_msg) # update active active = request.data.get('active', None) if active: active = active.lower() if active not in ('true', 'false'): error_msg = "active invalid, should be 'true' or 'false'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if active == 'true': user.is_active = True else: user.is_active = False try: # update user status result_code = user.save() except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) if result_code == -1: error_msg = 'Fail to update user %s.' % email return api_error(status.HTTP_403_FORBIDDEN, error_msg) # update name name = request.data.get('name', None) if name: profile = Profile.objects.get_profile_by_user(email) if profile is None: profile = Profile(user=email) profile.nickname = name profile.save() # update contact_email contact_email = request.data.get('contact_email', None) if contact_email: profile = Profile.objects.get_profile_by_user(email) if profile is None: profile = Profile(user=email) profile.contact_email = contact_email profile.save() # update user quota user_quota_mb = request.data.get("quota_total", None) if user_quota_mb: try: user_quota_mb = int(user_quota_mb) except Exception as e: logger.error(e) error_msg = "quota_total invalid." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) user_quota = int(user_quota_mb) * get_file_size_unit('MB') org_quota = seafile_api.get_org_quota(org_id) # -1 means org has unlimited quota if org_quota > 0: org_quota_mb = org_quota / get_file_size_unit('MB') if user_quota_mb > org_quota_mb: error_msg = 'Failed to set quota: maximum quota is %d MB' % org_quota_mb return api_error(status.HTTP_400_BAD_REQUEST, error_msg) seafile_api.set_org_user_quota(org_id, email, user_quota) user_info = get_org_user_info(org_id, user) user_info['active'] = user.is_active return Response(user_info)
def _update_account_additional_info(self, request, email): # update account name name = request.data.get("name", None) if name is not None: profile = Profile.objects.get_profile_by_user(email) if profile is None: profile = Profile(user=email) profile.nickname = name profile.save() # update account list_in_address_book list_in_address_book = request.data.get("list_in_address_book", None) if list_in_address_book is not None: profile = Profile.objects.get_profile_by_user(email) if profile is None: profile = Profile(user=email) profile.list_in_address_book = list_in_address_book.lower( ) == 'true' profile.save() # update account loginid loginid = request.data.get("login_id", '').strip() if loginid != '': profile = Profile.objects.get_profile_by_user(email) if profile is None: profile = Profile(user=email) profile.login_id = loginid profile.save() # update account detailed profile department = request.data.get("department", None) if department is not None: 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() # update user quota space_quota_mb = request.data.get("storage", None) if space_quota_mb is not None: space_quota = int(space_quota_mb) * get_file_size_unit('MB') if is_org_context(request): org_id = request.user.org.org_id seaserv.seafserv_threaded_rpc.set_org_user_quota( org_id, email, space_quota) else: seafile_api.set_user_quota(email, space_quota) # update user institution institution = request.data.get("institution", None) if institution is not None: profile = Profile.objects.get_profile_by_user(email) if profile is None: profile = Profile(user=email) profile.institution = institution profile.save()
def post(self, request): email = request.data.get('email', None) if not email or not is_valid_username(email): error_msg = 'email invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # basic user info check is_staff = request.data.get("is_staff", None) if is_staff: try: is_staff = to_python_boolean(is_staff) except ValueError: error_msg = 'is_staff invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) is_active = request.data.get("is_active", None) if is_active: try: is_active = to_python_boolean(is_active) except ValueError: error_msg = 'is_active invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # additional user info check role = request.data.get("role", None) if role: available_roles = get_available_roles() if role.lower() not in available_roles: error_msg = 'role must be in %s.' % str(available_roles) return api_error(status.HTTP_400_BAD_REQUEST, error_msg) name = request.data.get("name", None) if name: if len(name) > 64: error_msg = 'Name is too long (maximum is 64 characters).' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if "/" in name: error_msg = "Name should not include '/'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) department = request.data.get("department", None) if department: if len(department) > 512: error_msg = "Department is too long (maximum is 512 characters)." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) quota_total_mb = request.data.get("quota_total", None) if quota_total_mb: try: quota_total_mb = int(quota_total_mb) except ValueError: error_msg = "Must be an integer that is greater than or equal to 0." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if quota_total_mb < 0: error_msg = "Space quota is too low (minimum value is 0)." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if is_org_context(request): org_id = request.user.org.org_id org_quota_mb = seafile_api.get_org_quota(org_id) / \ get_file_size_unit('MB') if quota_total_mb > org_quota_mb: error_msg = 'Failed to set quota: maximum quota is %d MB' % org_quota_mb return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: User.objects.get(email=email) user_exist = True except User.DoesNotExist: user_exist = False if user_exist: error_msg = "User %s already exists." % email return api_error(status.HTTP_400_BAD_REQUEST, error_msg) password = request.data.get('password', None) if not password: error_msg = 'password required.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) # create user try: user_obj = User.objects.create_user(email) update_user_info(request, user_obj) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) user_info = get_user_info(email) return Response(user_info)
def put(self, request, email, format=None): # argument check for email if not is_valid_username(email): return api_error(status.HTTP_400_BAD_REQUEST, 'Email %s invalid.' % email) # argument check for name name = request.data.get("name", None) if name is not None: if len(name) > 64: return api_error( status.HTTP_400_BAD_REQUEST, _(u'Name is too long (maximum is 64 characters)')) if "/" in name: return api_error(status.HTTP_400_BAD_REQUEST, _(u"Name should not include '/'.")) # argument check for department department = request.data.get("department", None) if department is not None: if len(department) > 512: return api_error( status.HTTP_400_BAD_REQUEST, _(u'Department is too long (maximum is 512 characters)')) # argument check for storage space_quota_mb = request.data.get("storage", None) if space_quota_mb is not None: if space_quota_mb == '': return api_error(status.HTTP_400_BAD_REQUEST, _('Space quota can\'t be empty')) try: space_quota_mb = int(space_quota_mb) except ValueError: return api_error( status.HTTP_400_BAD_REQUEST, _('Must be an integer that is greater than or equal to 0.') ) if space_quota_mb < 0: return api_error( status.HTTP_400_BAD_REQUEST, _('Space quota is too low (minimum value is 0)')) if is_org_context(request): org_id = request.user.org.org_id org_quota_mb = seaserv.seafserv_threaded_rpc.get_org_quota(org_id) / \ get_file_size_unit('MB') if space_quota_mb > org_quota_mb: return api_error(status.HTTP_400_BAD_REQUEST, \ _(u'Failed to set quota: maximum quota is %d MB' % org_quota_mb)) # argument check for is_trial is_trial = request.data.get("is_trial", None) if is_trial is not None: try: is_trial = to_python_boolean(is_trial) except ValueError: return api_error(status.HTTP_400_BAD_REQUEST, 'is_trial invalid') try: # update account basic info user = User.objects.get(email=email) # argument check for is_staff is_staff = request.data.get("is_staff", None) if is_staff is not None: try: is_staff = to_python_boolean(is_staff) except ValueError: return api_error(status.HTTP_400_BAD_REQUEST, 'is_staff invalid.') user.is_staff = is_staff # argument check for is_active is_active = request.data.get("is_active", None) if is_active is not None: try: is_active = to_python_boolean(is_active) except ValueError: return api_error(status.HTTP_400_BAD_REQUEST, 'is_active invalid.') user.is_active = is_active # update password password = request.data.get("password", None) if password is not None: user.set_password(password) # save user result_code = user.save() if result_code == -1: return api_error(status.HTTP_520_OPERATION_FAILED, 'Failed to update user.') try: # update account additional info self._update_account_additional_info(request, email) except Exception as e: logger.error(e) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error') # get account info and return info = get_account_info(user) return Response(info) except User.DoesNotExist: # create user account copy = request.data.copy() copy['email'] = email serializer = AccountSerializer(data=copy) if not serializer.is_valid(): return api_error(status.HTTP_400_BAD_REQUEST, serializer.errors) try: user = User.objects.create_user(serializer.data['email'], serializer.data['password'], serializer.data['is_staff'], serializer.data['is_active']) except User.DoesNotExist as e: logger.error(e) return api_error(status.HTTP_520_OPERATION_FAILED, 'Failed to add user.') try: # update account additional info self._update_account_additional_info(request, email) except Exception as e: logger.error(e) return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, 'Internal Server Error') # get account info and return info = get_account_info(user) resp = Response(info, status=status.HTTP_201_CREATED) resp['Location'] = reverse('api2-account', args=[email]) return resp
def put(self, request, org_id): """ Update base info of a organization Permission checking: 1. only admin can perform this action. """ if not (CLOUD_MODE and MULTI_TENANCY): error_msg = 'Feature is not enabled.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) org_id = int(org_id) if org_id == 0: error_msg = 'org_id invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) org = ccnet_api.get_org_by_id(org_id) if not org: error_msg = 'Organization %s not found.' % org_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) # update org name new_name = request.data.get('org_name', None) if new_name: try: ccnet_api.set_org_name(org_id, new_name) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) # update org max user number max_user_number = request.data.get('max_user_number', None) if max_user_number and ORG_MEMBER_QUOTA_ENABLED: try: max_user_number = int(max_user_number) except ValueError: error_msg = 'max_user_number invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if max_user_number <= 0: error_msg = 'max_user_number invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: OrgMemberQuota.objects.set_quota(org_id, max_user_number) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) quota_mb = request.data.get('quota', None) if quota_mb: try: quota_mb = int(quota_mb) except ValueError: error_msg = 'quota invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if quota_mb < 0: error_msg = 'quota invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) quota = quota_mb * get_file_size_unit('MB') try: seafile_api.set_org_quota(org_id, quota) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) role = request.data.get('role', None) if role: if role not in get_available_roles(): error_msg = 'Role %s invalid.' % role return api_error(status.HTTP_400_BAD_REQUEST, error_msg) OrgSettings.objects.add_or_update(org, role) org = ccnet_api.get_org_by_id(org_id) org_info = get_org_info(org) return Response(org_info)
def test_invalid_type(self): with self.assertRaises(TypeError): get_file_size_unit('ff')
def handle(self, *args, **options): self.stdout.write("Export users to '../users.xlsx'.") try: users = ccnet_api.get_emailusers('DB', -1, -1) + \ ccnet_api.get_emailusers('LDAPImport', -1, -1) except Exception as e: self.stdout.write('Error: ' + str(e)) return if is_pro_version(): is_pro = True else: is_pro = False if is_pro: head = [_("Email"), _("Name"), _("Contact Email"), _("Status"), _("Role"), _("Space Usage") + "(MB)", _("Space Quota") + "(MB)", _("Create At"), _("Last Login"), _("Admin"), _("LDAP(imported)"),] else: head = [_("Email"), _("Name"), _("Contact Email"), _("Status"), _("Space Usage") + "(MB)", _("Space Quota") + "(MB)", _("Create At"), _("Last Login"), _("Admin"), _("LDAP(imported)"),] # only operate 100 users for every `for` loop looped = 0 limit = 100 data_list = [] while looped < len(users): current_users = users[looped:looped+limit] last_logins = UserLastLogin.objects.filter(username__in=[x.email \ for x in current_users]) user_profiles = Profile.objects.filter(user__in=[x.email \ for x in current_users]) for user in current_users: # populate name and contact email user.contact_email = '' user.name = '' for profile in user_profiles: if profile.user == user.email: user.contact_email = profile.contact_email user.name = profile.nickname # populate space usage and quota MB = get_file_size_unit('MB') # populate user quota usage orgs = ccnet_api.get_orgs_by_user(user.email) try: if orgs: user.org = orgs[0] org_id = user.org.org_id user.space_usage = seafile_api.get_org_user_quota_usage(org_id, user.email) user.space_quota = seafile_api.get_org_user_quota(org_id, user.email) else: user.space_usage = seafile_api.get_user_self_usage(user.email) user.space_quota = seafile_api.get_user_quota(user.email) except Exception as e: self.stdout.write('Debug: ' + str(e)) user.space_usage = -1 user.space_quota = -1 if user.space_usage > 0: try: space_usage_MB = round(float(user.space_usage) / MB, 2) except Exception as e: self.stdout.write('Debug: ' + str(e)) space_usage_MB = '--' else: space_usage_MB = '' if user.space_quota > 0: try: space_quota_MB = round(float(user.space_quota) / MB, 2) except Exception as e: self.stdout.write('Debug: ' + str(e)) space_quota_MB = '--' else: space_quota_MB = '' # 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 if user.is_active: status = _('Active') else: status = _('Inactive') create_at = tsstr_sec(user.ctime) if user.ctime else '' last_login = user.last_login.strftime("%Y-%m-%d %H:%M:%S") if \ user.last_login else '' is_admin = _('Yes') if user.is_staff else '' ldap_import = _('Yes') if user.source == 'LDAPImport' else '' if is_pro: if user.role: if user.role == GUEST_USER: role = _('Guest') elif user.role == DEFAULT_USER: role = _('Default') else: role = user.role else: role = _('Default') row = [user.email, user.name, user.contact_email, status, role, space_usage_MB, space_quota_MB, create_at, last_login, is_admin, ldap_import] else: row = [user.email, user.name, user.contact_email, status, space_usage_MB, space_quota_MB, create_at, last_login, is_admin, ldap_import] data_list.append(row) # update `looped` value when `for` loop finished looped += limit wb = write_xls('users', head, data_list) if not wb: self.stdout.write('Error: please check the log.') return wb.save('../users.xlsx') self.stdout.write('Done.\n')
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) 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() # update account login_id login_id = request.data.get("login_id", None) if login_id is not None: login_id = login_id.strip() profile = Profile.objects.get_profile_by_user(email) if profile is None: profile = Profile(user=email) profile.login_id = None if login_id == "" else login_id profile.save() reference_id = request.data.get("reference_id", None) if reference_id is not None: reference_id = reference_id.strip() ccnet_api.set_reference_id(email, reference_id) 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 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 post(self, request): """ Import users from xlsx file Permission checking: 1. admin user. """ xlsx_file = request.FILES.get('file', None) if not xlsx_file: error_msg = 'file can not be found.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) file_type, ext = get_file_type_and_ext(xlsx_file.name) if ext != 'xlsx': error_msg = file_type_error_msg(ext, 'xlsx') return api_error(status.HTTP_400_BAD_REQUEST, error_msg) content = xlsx_file.read() try: fs = BytesIO(content) wb = load_workbook(filename=fs, read_only=True) except Exception as e: logger.error(e) # example file is like: # Email Password Name(Optional) Role(Optional) Space Quota(MB, Optional) # [email protected] a a default 1024 # [email protected] b b default 2048 rows = wb.worksheets[0].rows records = [] # skip first row(head field). next(rows) for row in rows: records.append([col.value for col in row]) if user_number_over_limit(new_users=len(records)): error_msg = 'The number of users exceeds the limit.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) result = {} result['failed'] = [] result['success'] = [] for record in records: if record[0]: email = record[0].strip() if not is_valid_username(email): result['failed'].append({ 'email': email, 'error_msg': 'email %s invalid.' % email }) continue else: result['failed'].append({ 'email': '', 'error_msg': 'email invalid.' }) continue if record[1]: password = str(record[1]).strip() if not password: result['failed'].append({ 'email': email, 'error_msg': 'password invalid.' }) continue else: result['failed'].append({ 'email': email, 'error_msg': 'password invalid.' }) continue vid = get_virtual_id_by_email(email) try: User.objects.get(email=vid) result['failed'].append({ 'email': email, 'error_msg': 'user %s exists.' % email }) continue except User.DoesNotExist: pass user = User.objects.create_user(email, password, is_staff=False, is_active=True) virtual_id = get_virtual_id_by_email(email) if config.FORCE_PASSWORD_CHANGE: UserOptions.objects.set_force_passwd_change(virtual_id) # update the user's optional info # update nikename nickname = email.split('@')[0] try: if record[2]: input_nickname = str(record[2]).strip() if len(input_nickname) <= 64 and '/' not in input_nickname: nickname = input_nickname Profile.objects.add_or_update(virtual_id, nickname, '') except Exception as e: logger.error(e) # update role if record[3]: try: role = record[3].strip() if is_pro_version() and role in get_available_roles(): User.objects.update_role(virtual_id, role) except Exception as e: logger.error(e) # update quota if record[4]: try: space_quota_mb = int(record[4]) if space_quota_mb >= 0: space_quota = int(space_quota_mb) * get_file_size_unit('MB') seafile_api.set_user_quota(virtual_id, space_quota) except Exception as e: logger.error(e) try: send_html_email_with_dj_template( email, dj_template='sysadmin/user_batch_add_email.html', subject=_('You are invited to join %s') % get_site_name(), context={ 'user': email2nickname(request.user.username), 'email': email, 'password': password, }) except Exception as e: logger.error(e) user_info = get_user_info(virtual_id) result['success'].append(user_info) # send admin operation log signal admin_op_detail = { "email": email, } admin_operation.send(sender=None, admin_name=request.user.username, operation=USER_ADD, detail=admin_op_detail) return Response(result)
def put(self, request, org_id, email): """ update name of an org user. Permission checking: 1. only admin can perform this action. """ # resource check org_id = int(org_id) if not ccnet_api.get_org_by_id(org_id): error_msg = 'Organization %s not found.' % org_id return api_error(status.HTTP_404_NOT_FOUND, error_msg) try: user = User.objects.get(email=email) except User.DoesNotExist: error_msg = 'User %s not found.' % email return api_error(status.HTTP_404_NOT_FOUND, error_msg) # permission check if not is_org_user(email, org_id): error_msg = 'Permission denied.' return api_error(status.HTTP_403_FORBIDDEN, error_msg) # update user's name name = request.data.get("name", None) if name is not None: name = name.strip() if len(name) > 64: error_msg = 'Name is too long (maximum is 64 characters).' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if "/" in name: error_msg = "Name should not include '/'." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: Profile.objects.add_or_update(email, nickname=name) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) # update user's contact email contact_email = request.data.get("contact_email", None) if contact_email is not None: contact_email = contact_email.strip() if contact_email != '' and not is_valid_email(contact_email): error_msg = 'contact_email invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) try: Profile.objects.add_or_update(email, contact_email=contact_email) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) is_staff = request.data.get("is_staff", None) if is_staff is not None: try: is_staff = to_python_boolean(is_staff) except ValueError: error_msg = 'is_staff invalid.' return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if is_staff: if is_org_staff(org_id, user.username): error_msg = '%s is already organization staff.' % email return api_error(status.HTTP_400_BAD_REQUEST, error_msg) set_org_staff(org_id, user.username) if not is_staff: if not is_org_staff(org_id, user.username): error_msg = '%s is not organization staff.' % email return api_error(status.HTTP_400_BAD_REQUEST, error_msg) unset_org_staff(org_id, user.username) quota_total_mb = request.data.get("quota_total", None) if quota_total_mb: try: quota_total_mb = int(quota_total_mb) except ValueError: error_msg = "Must be an integer that is greater than or equal to 0." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) if quota_total_mb < 0: error_msg = "Space quota is too low (minimum value is 0)." return api_error(status.HTTP_400_BAD_REQUEST, error_msg) org_quota = seafile_api.get_org_quota(org_id) org_quota_mb = org_quota / get_file_size_unit('MB') # -1 means org has unlimited quota if org_quota > 0 and quota_total_mb > org_quota_mb: error_msg = _(u'Failed to set quota: maximum quota is %d MB' % org_quota_mb) return api_error(status.HTTP_400_BAD_REQUEST, error_msg) quota_total = int(quota_total_mb) * get_file_size_unit('MB') try: seafile_api.set_org_user_quota(org_id, email, quota_total) except Exception as e: logger.error(e) error_msg = 'Internal Server Error' return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg) info = get_user_info(email, org_id) info['is_active'] = user.is_active info['id'] = user.id info['ctime'] = timestamp_to_isoformat_timestr(user.ctime) try: last_login = UserLastLogin.objects.get(username=user.email) info['last_login'] = datetime_to_isoformat_timestr( last_login.last_login) except UserLastLogin.DoesNotExist: info['last_login'] = None # these two fields are designed to be compatible with the old API info['self_usage'] = info.get('quota_usage') info['quota'] = info.get('quota_total') return Response(info)