Example #1
0
def search_user_when_global_address_book_disabled(request, q):

    email_list = []
    username = request.user.username

    # search from contact
    # get user's contact list
    contacts = Contact.objects.get_contacts_by_user(username)
    for contact in contacts:
        # search user from contact list
        if q in contact.contact_email:
            email_list.append(contact.contact_email)

    # search from profile, limit search range in user's contacts
    limited_emails = []
    for contact in contacts:
        limited_emails.append(contact.contact_email)

    email_list += search_user_from_profile_with_limits(q, limited_emails)

    if is_valid_email(q):
        # if `q` is a valid email
        email_list.append(q)

        # get user whose `contact_email` is `q`
        users = Profile.objects.filter(contact_email=q).values('user')
        for user in users:
            email_list.append(user['user'])

    return email_list
Example #2
0
def contact_add(request):
    """
    Handle normal request to add a contact.
    """
    if request.method != 'POST':
        raise Http404

    referer = request.META.get('HTTP_REFERER', None)
    if not referer:
        referer = SITE_ROOT
    
    username = request.user.username
    contact_email = request.POST.get('contact_email', '')
    if not is_valid_email(contact_email):
        messages.error(request, _(u"%s is not a valid email.") % contact_email)
        return HttpResponseRedirect(referer)

    if Contact.objects.get_contact_by_user(username, contact_email) is not None:
        messages.error(request, _(u"%s is already in your contacts.") % contact_email)
        return HttpResponseRedirect(referer)
    
    contact_name = request.POST.get('contact_name', '')
    note = request.POST.get('note', '')

    try:
        Contact.objects.add_contact(username, contact_email, contact_name, note)
        messages.success(request, _(u"Successfully added %s to contacts.") % contact_email)
    except Exception as e:
        logger.error(e)
        messages.error(request, _(u"Failed to add %s to contacts.") % contact_email)

    return HttpResponseRedirect(referer)
Example #3
0
def search_user_when_global_address_book_disabled(request, q):
    """ Return 10 items at most.
    """

    email_list = []
    username = request.user.username

    # search from contact
    # get user's contact list
    contacts = Contact.objects.get_contacts_by_user(username)
    for contact in contacts:
        # search user from contact list
        if q in contact.contact_email:
            email_list.append(contact.contact_email)

    # search from profile, limit search range in user's contacts
    limited_emails = []
    for contact in contacts:
        limited_emails.append(contact.contact_email)

    email_list += search_user_from_profile_with_limits(q, limited_emails)

    current_user = User.objects.get(email=username)
    if is_valid_email(q) and current_user.role.lower() != 'guest':
        # if `q` is a valid email and current is not a guest user
        email_list.append(q)

        # get user whose `contact_email` is `q`
        users = Profile.objects.filter(contact_email=q).values('user')
        for user in users:
            email_list.append(user['user'])

    return email_list
Example #4
0
    def clean(self):
        username = self.cleaned_data.get('login')
        password = self.cleaned_data.get('password')

        if username and password:

            if not is_valid_email(username):
                # convert login id to username if any
                username = Profile.objects.convert_login_str_to_username(
                    username)

            self.user_cache = authenticate(username=username,
                                           password=password)
            if self.user_cache is None:
                """then try login id/contact email/primary id"""
                # convert contact email to username if any
                username = Profile.objects.convert_login_str_to_username(
                    username)
                # convert username to primary id if any
                username = self.get_primary_id_by_username(username)

                self.user_cache = authenticate(username=username,
                                               password=password)
                if self.user_cache is None:
                    err_msg = _(
                        "Please enter a correct email/username and password. Note that both fields are case-sensitive."
                    )

                    if settings.LOGIN_ERROR_DETAILS:
                        try:
                            u = User.objects.get(email=username)
                        except User.DoesNotExist:
                            err_msg = _(
                                "That e-mail address doesn't have an associated user account. Are you sure you've registered?"
                            )
                            self.errors['not_found'] = err_msg

                    raise forms.ValidationError(err_msg)

            # user found for login string but inactive
            if not self.user_cache.is_active:
                if settings.ACTIVATE_AFTER_FIRST_LOGIN and \
                   not UserOptions.objects.is_user_logged_in(username):
                    """Activate user on first login."""
                    self.user_cache.is_active = True
                    self.user_cache.save()

                    UserOptions.objects.set_user_logged_in(username)
                else:
                    self.errors['inactive'] = _("This account is inactive.")
                    raise forms.ValidationError(_("This account is inactive."))

        # TODO: determine whether this should move to its own method.
        if self.request:
            if not self.request.session.test_cookie_worked():
                raise forms.ValidationError(
                    _("Your Web browser doesn't appear to have cookies enabled. Cookies are required for logging in."
                      ))

        return self.cleaned_data
Example #5
0
    def post(self, request, format=None):
        # Send a invitation.
        itype = request.data.get('type', '').lower()
        if not itype or itype != 'guest':
            return api_error(status.HTTP_400_BAD_REQUEST, 'type invalid.')

        accepter = request.data.get('accepter', '').lower()
        if not accepter:
            return api_error(status.HTTP_400_BAD_REQUEST, 'accepter invalid.')

        if not is_valid_email(accepter):
            return api_error(status.HTTP_400_BAD_REQUEST,
                             _('Email %s invalid.') % accepter)

        try:
            User.objects.get(accepter)
            user_exists = True
        except User.DoesNotExist:
            user_exists = False

        if user_exists:
            return api_error(status.HTTP_400_BAD_REQUEST,
                             _('User %s already exists.') % accepter)

        i = Invitation.objects.add(inviter=request.user.username,
                                   accepter=accepter)
        i.send_to(email=accepter)

        return Response(i.to_dict(), status=201)
Example #6
0
def contact_add_post(request):
    """
    Handle ajax post to add a contact.
    """
    result = {}
    content_type = 'application/json; charset=utf-8'

    username = request.user.username
    contact_email = request.POST.get('contact_email', '')
    if not is_valid_email(contact_email):
        result['success'] = False
        messages.error(request, _(u"%s is not a valid email.") % contact_email)
        return HttpResponseBadRequest(json.dumps(result), content_type=content_type)

    if Contact.objects.get_contact_by_user(username, contact_email) is not None:
        result['success'] = False
        messages.error(request, _(u"%s is already in your contacts.") % contact_email)
        return HttpResponseBadRequest(json.dumps(result), content_type=content_type)
        
    contact_name = request.POST.get('contact_name', '')
    note = request.POST.get('note', '')

    try:
        Contact.objects.add_contact(username, contact_email, contact_name, note)
        result['success'] = True
        messages.success(request, _(u"Successfully added %s to contacts.") % contact_email)
        return HttpResponse(json.dumps(result), content_type=content_type)
    except Exception as e:
        logger.error(e)
        result['success'] = False
        messages.error(request, _(u"Failed to add %s to contacts.") % contact_email)
        return HttpResponse(json.dumps(result), status=500, content_type=content_type)
Example #7
0
def search_user_when_global_address_book_disabled(request, q):
    """ Return 10 items at most.
    """

    email_list = []
    username = request.user.username

    # search from contact
    # get user's contact list
    contacts = Contact.objects.get_contacts_by_user(username)
    for contact in contacts:
        # search user from contact list
        if q in contact.contact_email:
            email_list.append(contact.contact_email)

    # search from profile, limit search range in user's contacts
    limited_emails = []
    for contact in contacts:
        limited_emails.append(contact.contact_email)

    email_list += search_user_from_profile_with_limits(q, limited_emails)

    current_user = User.objects.get(email=username)
    if is_valid_email(q) and current_user.role.lower() != 'guest':
        # if `q` is a valid email and current is not a guest user
        email_list.append(q)

        # get user whose `contact_email` is `q`
        users = Profile.objects.filter(contact_email=q).values('user')
        for user in users:
            email_list.append(user['user'])

    return email_list
Example #8
0
def ajax_get_link_audit_code(request):
    """
    Generate a token, and record that token with email in cache, expires in
    one hour, send token to that email address.

    User provide token and email at share link page, if the token and email
    are valid, record that email in session.
    """
    content_type = 'application/json; charset=utf-8'

    token = request.POST.get('token')
    email = request.POST.get('email')
    if not is_valid_email(email):
        return HttpResponse(json.dumps(
            {'error': _('Email address is not valid')}),
                            status=400,
                            content_type=content_type)

    dfs = FileShare.objects.get_valid_file_link_by_token(token)
    ufs = UploadLinkShare.objects.get_valid_upload_link_by_token(token)

    fs = dfs if dfs else ufs
    if fs is None:
        return HttpResponse(json.dumps({'error':
                                        _('Share link is not found')}),
                            status=400,
                            content_type=content_type)

    cache_key = normalize_cache_key(email, 'share_link_audit_')
    timeout = 60 * 60  # one hour
    code = gen_token(max_length=6)
    cache.set(cache_key, code, timeout)

    # send code to user via email
    subject = _("Verification code for visiting share links")
    c = {
        'code': code,
    }
    try:
        send_html_email_with_dj_template(
            email,
            dj_template='share/audit_code_email.html',
            context=c,
            subject=subject,
            priority=MAIL_PRIORITY.now)
        return HttpResponse(json.dumps({'success': True}),
                            status=200,
                            content_type=content_type)
    except Exception as e:
        logger.error('Failed to send audit code via email to %s')
        logger.error(e)
        return HttpResponse(json.dumps({
            "error":
            _("Failed to send a verification code, please try again later.")
        }),
                            status=500,
                            content_type=content_type)
Example #9
0
    def post(self, request):

        itype = request.data.get('type', '').lower()
        if not itype or itype != 'guest':
            return api_error(status.HTTP_400_BAD_REQUEST, 'type invalid.')

        accepters = request.data.getlist('accepter', None)
        if not accepters:
            return api_error(status.HTTP_400_BAD_REQUEST, 'accepters invalid.')

        result = {}
        result['failed'] = []
        result['success'] = []

        for accepter in accepters:

            if not accepter.strip():
                continue

            accepter = accepter.lower()

            if not is_valid_email(accepter):
                result['failed'].append({
                    'email': accepter,
                    'error_msg': _('Email %s invalid.') % accepter
                    })
                continue

            if block_accepter(accepter):
                result['failed'].append({
                    'email': accepter,
                    'error_msg': _('The email address is not allowed to be invited as a guest.')
                    })
                continue

            if Invitation.objects.filter(inviter=request.user.username,
                    accepter=accepter).count() > 0:
                result['failed'].append({
                    'email': accepter,
                    'error_msg': _('%s is already invited.') % accepter
                    })
                continue

            try:
                User.objects.get(accepter)
                result['failed'].append({
                    'email': accepter,
                    'error_msg': _('User %s already exists.') % accepter
                    })
                continue
            except User.DoesNotExist:
                i = Invitation.objects.add(inviter=request.user.username,
                        accepter=accepter)
                i.send_to(email=accepter)
                result['success'].append(i.to_dict())

        return Response(result)
Example #10
0
def ajax_get_link_audit_code(request):
    """
    Generate a token, and record that token with email in cache, expires in
    one hour, send token to that email address.

    User provide token and email at share link page, if the token and email
    are valid, record that email in session.
    """
    content_type = 'application/json; charset=utf-8'

    token = request.POST.get('token')
    email = request.POST.get('email')
    if not is_valid_email(email):
        return HttpResponse(json.dumps({
            'error': _('Email address is not valid')
        }), status=400, content_type=content_type)

    dfs = FileShare.objects.get_valid_file_link_by_token(token)
    ufs = UploadLinkShare.objects.get_valid_upload_link_by_token(token)

    fs = dfs if dfs else ufs
    if fs is None:
        return HttpResponse(json.dumps({
            'error': _('Share link is not found')
        }), status=400, content_type=content_type)

    cache_key = normalize_cache_key(email, 'share_link_audit_')
    timeout = 60 * 60           # one hour
    code = gen_token(max_length=6)
    cache.set(cache_key, code, timeout)

    # send code to user via email
    subject = _("Verification code for visiting share links")
    c = {
        'code': code,
    }
    try:
        send_html_email_with_dj_template(
            email, dj_template='share/audit_code_email.html',
            context=c, subject=subject, priority=MAIL_PRIORITY.now
        )
        return HttpResponse(json.dumps({'success': True}), status=200,
                            content_type=content_type)
    except Exception as e:
        logger.error('Failed to send audit code via email to %s')
        logger.error(e)
        return HttpResponse(json.dumps({
            "error": _("Failed to send a verification code, please try again later.")
        }), status=500, content_type=content_type)
Example #11
0
    def post(self, request, format=None):
        # Send invitation.
        itype = request.data.get('type', '').lower()
        if not itype or itype != 'guest':
            return api_error(status.HTTP_400_BAD_REQUEST, 'type invalid.')

        accepter = request.data.get('accepter', '').lower()
        if not accepter:
            return api_error(status.HTTP_400_BAD_REQUEST, 'accepter invalid.')

        if not is_valid_email(accepter):
            return api_error(status.HTTP_400_BAD_REQUEST,
                             _('Email %s invalid.') % accepter)

        if block_accepter(accepter):
            return api_error(
                status.HTTP_400_BAD_REQUEST,
                _('The email address is not allowed to be invited as a guest.')
            )

        if Invitation.objects.filter(inviter=request.user.username,
                                     accepter=accepter).count() > 0:
            return api_error(status.HTTP_400_BAD_REQUEST,
                             _('%s is already invited.') % accepter)

        try:
            User.objects.get(accepter)
            user_exists = True
        except User.DoesNotExist:
            user_exists = False

        if user_exists:
            return api_error(status.HTTP_400_BAD_REQUEST,
                             _('User %s already exists.') % accepter)

        i = Invitation.objects.add(inviter=request.user.username,
                                   accepter=accepter)
        m = i.send_to(email=accepter)
        if m.status == STATUS.sent:
            return Response(i.to_dict(), status=201)
        else:
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                             _('Internal Server Error'))
Example #12
0
def search_user_with_exact_match(request, q):
    """ Return 10 items at most.
    """

    email_list = []
    username = request.user.username

    current_user = User.objects.get(email=username)
    if is_valid_email(q) and current_user.role.lower() != 'guest':
        # if `q` is a valid email and current is not a guest user
        email_list.append(q)

        # get user whose `contact_email` is `q`
        users = Profile.objects.filter(contact_email=q).values('user')
        for user in users:
            if not is_org_user(user['user']):
                email_list.append(user['user'])

    return email_list
Example #13
0
    def post(self, request, format=None):
        # Send invitation.
        itype = request.data.get('type', '').lower()
        if not itype or itype != 'guest':
            return api_error(status.HTTP_400_BAD_REQUEST, 'type invalid.')

        accepter = request.data.get('accepter', '').lower()
        if not accepter:
            return api_error(status.HTTP_400_BAD_REQUEST, 'accepter invalid.')

        if not is_valid_email(accepter):
            return api_error(status.HTTP_400_BAD_REQUEST,
                             _('Email %s invalid.') % accepter)

        if block_accepter(accepter):
            return api_error(status.HTTP_400_BAD_REQUEST,
                             _('The email address is not allowed to be invited as a guest.'))

        if Invitation.objects.filter(inviter=request.user.username,
                                     accepter=accepter).count() > 0:
            return api_error(status.HTTP_400_BAD_REQUEST,
                             _('%s is already invited.') % accepter)

        try:
            User.objects.get(accepter)
            user_exists = True
        except User.DoesNotExist:
            user_exists = False

        if user_exists:
            return api_error(status.HTTP_400_BAD_REQUEST,
                             _('User %s already exists.') % accepter)

        i = Invitation.objects.add(inviter=request.user.username,
                                   accepter=accepter)
        m = i.send_to(email=accepter)
        if m.status == STATUS.sent:
            return Response(i.to_dict(), status=201)
        else:
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR,
                             _('Internal Server Error'))
Example #14
0
    def format_user_info(user_info_resp):
        logger.info('user info resp: %s' % user_info_resp.text)
        error = False
        user_info = {}
        user_info_json = user_info_resp.json()

        for item, attr in ATTRIBUTE_MAP.items():
            required, user_attr = attr
            value = user_info_json.get(item, '')

            if value:
                # ccnet email
                if user_attr == 'email':
                    user_info[user_attr] = value if is_valid_email(str(value)) else \
                            '%s@%s' % (str(value), PROVIDER_DOMAIN)
                else:
                    user_info[user_attr] = value
            elif required:
                error = True

        return user_info, error
Example #15
0
    def format_user_info(user_info_resp):
        logger.info('user info resp: %s' % user_info_resp.text)
        error = False
        user_info = {}
        user_info_json = user_info_resp.json()

        for item, attr in ATTRIBUTE_MAP.items():
            required, user_attr = attr
            value = user_info_json.get(item, '')

            if value:
                # ccnet email
                if user_attr == 'email':
                    user_info[user_attr] = value if is_valid_email(str(value)) else \
                            '%s@%s' % (str(value), PROVIDER_DOMAIN)
                else:
                    user_info[user_attr] = value
            elif required:
                error = True

        return user_info, error
Example #16
0
    def authenticate(self, remote_user):
        """
        The username passed as ``remote_user`` is considered trusted.  This
        method simply returns the ``User`` object with the given username,
        creating a new ``User`` object if ``create_unknown_user`` is ``True``.

        Returns None if ``create_unknown_user`` is ``False`` and a ``User``
        object with the given username is not found in the database.
        """
        if remote_user:
            if not is_valid_email(remote_user): 
                return None

            username = self.clean_username(remote_user)
            vid = get_virtual_id_by_email(username)
            try:
                user = User.objects.get(email=vid)
                return user
            except User.DoesNotExist:
                user = None
        else:
            user = None
            username = None

        # for readability
        if user:
            return user

        if self.create_unknown_user:
            user = User.objects.create_oauth_user(
                email=username, is_active=self.activate_after_creation)
            if not self.activate_after_creation:
                notify_admins_on_activate_request(username)
            elif settings.NOTIFY_ADMIN_AFTER_REGISTRATION:
                notify_admins_on_register_complete(username)
        else:
            user = None

        return user
Example #17
0
    def authenticate(self, remote_user, nickname):
        """
        The username passed as ``remote_user`` is considered trusted.  This
        method simply returns the ``User`` object with the given username

        """
        if not remote_user or not is_valid_email(remote_user):
            return

        username = self.clean_username(remote_user)
        vid = get_virtual_id_by_email(username)

        try:
            user = User.objects.get(email=vid)
        except User.DoesNotExist:
            user = User.objects.create_saml_user(
                email=username,
                nickname=nickname,
                is_active=self.activate_after_creation)
            if settings.NOTIFY_ADMIN_AFTER_REGISTRATION:
                notify_admins_on_register_complete(username)

        return user
Example #18
0
    def post(self, request):
        """ Create an organization

        Permission checking:
        1. only admin can perform this action.
        """
        if not MULTI_TENANCY:
            error_msg = 'Feature is not enabled.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        if not request.user.admin_permissions.other_permission():
            return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.')

        org_name = request.data.get('org_name', None)
        if not org_name:
            error_msg = 'org_name invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        owner_email = request.data.get('owner_email', None)
        if not owner_email or not is_valid_email(owner_email):
            error_msg = 'email invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        owner_password = request.data.get('owner_password', None)
        if not owner_password:
            error_msg = 'owner_password invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        url_prefix = gen_org_url_prefix(5, 20)
        if ccnet_api.get_org_by_url_prefix(url_prefix):
            error_msg = 'Failed to create organization, please try again later.'
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

        try:
            User.objects.get(email=owner_email)
        except User.DoesNotExist:
            pass
        else:
            error_msg = "User %s already exists." % owner_email
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        try:
            new_user = User.objects.create_user(owner_email,
                                                owner_password,
                                                is_staff=False,
                                                is_active=True)
        except User.DoesNotExist as e:
            logger.error(e)
            error_msg = 'Failed to add user %s.' % owner_email
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

        try:
            org_id = ccnet_api.create_org(org_name, url_prefix,
                                          new_user.username)
        except Exception as e:
            logger.error(e)
            error_msg = 'Internal Server Error'
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

        org = ccnet_api.get_org_by_id(org_id)
        try:
            org_info = get_org_info(org)
        except Exception as e:
            logger.error(e)
            error_msg = 'Internal Server Error'
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

        return Response(org_info)
Example #19
0
def send_shared_upload_link(request):
    """
    Handle ajax post request to send shared upload link.
    """
    if not request.method == 'POST':
        raise Http404

    content_type = 'application/json; charset=utf-8'

    if not IS_EMAIL_CONFIGURED:
        data = json.dumps({
            'error':
            _(u'Sending shared upload link failed. Email service is not properly configured, please contact administrator.'
              )
        })
        return HttpResponse(data, status=500, content_type=content_type)

    from seahub.settings import SITE_NAME

    form = UploadLinkShareForm(request.POST)
    if form.is_valid():
        email = form.cleaned_data['email']
        shared_upload_link = form.cleaned_data['shared_upload_link']
        extra_msg = escape(form.cleaned_data['extra_msg'])

        to_email_list = string2list(email)
        send_success, send_failed = [], []
        for to_email in to_email_list:
            if not is_valid_email(to_email):
                send_failed.append(to_email)
                continue
            # Add email to contacts.
            mail_sended.send(sender=None,
                             user=request.user.username,
                             email=to_email)

            c = {
                'email': request.user.username,
                'to_email': to_email,
                'shared_upload_link': shared_upload_link,
            }

            if extra_msg:
                c['extra_msg'] = extra_msg

            if REPLACE_FROM_EMAIL:
                from_email = request.user.username
            else:
                from_email = None  # use default from email

            if ADD_REPLY_TO_HEADER:
                reply_to = request.user.username
            else:
                reply_to = None

            try:
                send_html_email(_(u'An upload link is shared to you on %s') %
                                SITE_NAME,
                                'shared_upload_link_email.html',
                                c,
                                from_email, [to_email],
                                reply_to=reply_to)

                send_success.append(to_email)
            except Exception:
                send_failed.append(to_email)

        if len(send_success) > 0:
            data = json.dumps({
                "send_success": send_success,
                "send_failed": send_failed
            })
            return HttpResponse(data, status=200, content_type=content_type)
        else:
            data = json.dumps({
                "error":
                _("Internal server error, or please check the email(s) you entered"
                  )
            })
            return HttpResponse(data, status=400, content_type=content_type)
    else:
        return HttpResponseBadRequest(json.dumps(form.errors),
                                      content_type=content_type)
Example #20
0
    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)
Example #21
0
    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)
Example #22
0
def send_shared_upload_link(request):
    """
    Handle ajax post request to send shared upload link.
    """
    if not request.method == 'POST':
        raise Http404

    content_type = 'application/json; charset=utf-8'

    if not IS_EMAIL_CONFIGURED:
        data = json.dumps({'error':_(u'Sending shared upload link failed. Email service is not properly configured, please contact administrator.')})
        return HttpResponse(data, status=500, content_type=content_type)

    from seahub.settings import SITE_NAME

    form = UploadLinkShareForm(request.POST)
    if form.is_valid():
        email = form.cleaned_data['email']
        shared_upload_link = form.cleaned_data['shared_upload_link']
        extra_msg = escape(form.cleaned_data['extra_msg'])

        to_email_list = string2list(email)
        send_success, send_failed = [], []
        for to_email in to_email_list:
            if not is_valid_email(to_email):
                send_failed.append(to_email)
                continue
            # Add email to contacts.
            mail_sended.send(sender=None, user=request.user.username,
                             email=to_email)

            c = {
                'email': request.user.username,
                'to_email': to_email,
                'shared_upload_link': shared_upload_link,
                }

            if extra_msg:
                c['extra_msg'] = extra_msg

            if REPLACE_FROM_EMAIL:
                from_email = request.user.username
            else:
                from_email = None  # use default from email

            if ADD_REPLY_TO_HEADER:
                reply_to = request.user.username
            else:
                reply_to = None

            try:
                send_html_email(_(u'An upload link is shared to you on %s') % SITE_NAME,
                                'shared_upload_link_email.html',
                                c, from_email, [to_email],
                                reply_to=reply_to)

                send_success.append(to_email)
            except Exception:
                send_failed.append(to_email)

        if len(send_success) > 0:
            data = json.dumps({"send_success": send_success, "send_failed": send_failed})
            return HttpResponse(data, status=200, content_type=content_type)
        else:
            data = json.dumps({"error": _("Internal server error, or please check the email(s) you entered")})
            return HttpResponse(data, status=400, content_type=content_type)
    else:
        return HttpResponseBadRequest(json.dumps(form.errors),
                                      content_type=content_type)
Example #23
0
def send_shared_link(request):
    """
    Handle ajax post request to send file shared link.
    """
    if not request.method == 'POST':
        raise Http404

    content_type = 'application/json; charset=utf-8'

    if not IS_EMAIL_CONFIGURED:
        data = json.dumps({
            'error':
            _('Failed to send email, email service is not properly configured, please contact administrator.'
              )
        })
        return HttpResponse(data, status=500, content_type=content_type)

    form = FileLinkShareForm(request.POST)
    if form.is_valid():
        email = form.cleaned_data['email']
        file_shared_link = form.cleaned_data['file_shared_link']
        file_shared_name = form.cleaned_data['file_shared_name']
        file_shared_type = form.cleaned_data['file_shared_type']
        extra_msg = escape(form.cleaned_data['extra_msg'])

        to_email_list = string2list(email)
        send_success, send_failed = [], []
        # use contact_email, if present
        username = Profile.objects.get_contact_email_by_user(
            request.user.username)
        for to_email in to_email_list:
            if not is_valid_email(to_email):
                send_failed.append(to_email)
                continue

            if SHARE_LINK_EMAIL_LANGUAGE:
                activate(SHARE_LINK_EMAIL_LANGUAGE)

            # Add email to contacts.
            mail_sended.send(sender=None,
                             user=request.user.username,
                             email=to_email)

            c = {
                'email': request.user.username,
                'to_email': to_email,
                'file_shared_link': file_shared_link,
                'file_shared_name': file_shared_name,
            }

            if extra_msg:
                c['extra_msg'] = extra_msg

            if REPLACE_FROM_EMAIL:
                from_email = username
            else:
                from_email = None  # use default from email

            if ADD_REPLY_TO_HEADER:
                reply_to = username
            else:
                reply_to = None

            try:
                if file_shared_type == 'f':
                    c['file_shared_type'] = _("file")
                    send_html_email(_('A file is shared to you on %s') %
                                    get_site_name(),
                                    'shared_link_email.html',
                                    c,
                                    from_email, [to_email],
                                    reply_to=reply_to)
                else:
                    c['file_shared_type'] = _("directory")
                    send_html_email(_('A directory is shared to you on %s') %
                                    get_site_name(),
                                    'shared_link_email.html',
                                    c,
                                    from_email, [to_email],
                                    reply_to=reply_to)

                send_success.append(to_email)
            except Exception:
                send_failed.append(to_email)

        if len(send_success) > 0:
            data = json.dumps({
                "send_success": send_success,
                "send_failed": send_failed
            })
            return HttpResponse(data, status=200, content_type=content_type)
        else:
            data = json.dumps({
                "error":
                _("Internal server error, or please check the email(s) you entered"
                  )
            })
            return HttpResponse(data, status=400, content_type=content_type)
    else:
        return HttpResponseBadRequest(json.dumps(form.errors),
                                      content_type=content_type)
Example #24
0
    def post(self, request):

        itype = request.data.get('type', '').lower()
        if not itype or itype != 'guest':
            return api_error(status.HTTP_400_BAD_REQUEST, 'type invalid.')

        accepters = request.data.getlist('accepter', None)
        if not accepters:
            return api_error(status.HTTP_400_BAD_REQUEST, 'accepters invalid.')

        result = {}
        result['failed'] = []
        result['success'] = []

        for accepter in accepters:

            if not accepter.strip():
                continue

            accepter = accepter.lower()

            if not is_valid_email(accepter):
                result['failed'].append({
                    'email': accepter,
                    'error_msg': _('Email %s invalid.') % accepter
                    })
                continue

            if block_accepter(accepter):
                result['failed'].append({
                    'email': accepter,
                    'error_msg': _('The email address is not allowed to be invited as a guest.')
                    })
                continue

            if Invitation.objects.filter(inviter=request.user.username,
                    accepter=accepter).count() > 0:
                result['failed'].append({
                    'email': accepter,
                    'error_msg': _('%s is already invited.') % accepter
                    })
                continue

            try:
                User.objects.get(accepter)
                result['failed'].append({
                    'email': accepter,
                    'error_msg': _('User %s already exists.') % accepter
                    })
                continue
            except User.DoesNotExist:
                i = Invitation.objects.add(inviter=request.user.username,
                        accepter=accepter)
                m = i.send_to(email=accepter)
                if m.status == STATUS.sent:
                    result['success'].append(i.to_dict())
                else:
                    result['failed'].append({
                        'email': accepter,
                        'error_msg': _('Internal Server Error'),
                    })

        return Response(result)
    def post(self, request):

        if not IS_EMAIL_CONFIGURED:
            error_msg = _(u'Sending shared link failed. Email service is not properly configured, please contact administrator.')
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        # check args
        email = request.POST.get('email', None)
        if not email:
            error_msg = 'email invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        token = request.POST.get('token', None)
        if not token:
            error_msg = 'token invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        extra_msg = request.POST.get('extra_msg', '')

        # check if token exists
        try:
            link = UploadLinkShare.objects.get(token=token)
        except UploadLinkShare.DoesNotExist:
            error_msg = 'token %s not found.' % token
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        # check if is upload link owner
        username = request.user.username
        if not link.is_owner(username):
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        result = {}
        result['failed'] = []
        result['success'] = []
        to_email_list = string2list(email)
        # use contact_email, if present
        useremail = Profile.objects.get_contact_email_by_user(request.user.username)
        for to_email in to_email_list:

            failed_info = {}

            if not is_valid_email(to_email):
                failed_info['email'] = to_email
                failed_info['error_msg'] = 'email invalid.'
                result['failed'].append(failed_info)
                continue

            # prepare basic info
            c = {
                'email': username,
                'to_email': to_email,
                'extra_msg': extra_msg,
            }

            if REPLACE_FROM_EMAIL:
                from_email = useremail
            else:
                from_email = None  # use default from email

            if ADD_REPLY_TO_HEADER:
                reply_to = useremail
            else:
                reply_to = None

            c['shared_upload_link'] = gen_shared_upload_link(token)
            title = _(u'An upload link is shared to you on %s') % SITE_NAME
            template = 'shared_upload_link_email.html'

            # send email
            try:
                send_html_email(title, template, c, from_email, [to_email], reply_to=reply_to)
                result['success'].append(to_email)
            except Exception as e:
                logger.error(e)
                failed_info['email'] = to_email
                failed_info['error_msg'] = 'Internal Server Error'
                result['failed'].append(failed_info)

        return Response(result)
Example #26
0
File: logs.py Project: cytec/seahub
    def get(self, request):
        """ Get all share permissions logs.

        Permission checking:
        1. only admin can perform this action.
        """
        try:
            current_page = int(request.GET.get('page', '1'))
            per_page = int(request.GET.get('per_page', '100'))
        except ValueError:
            current_page = 1
            per_page = 100

        user_selected = request.GET.get('email', None)
        if user_selected and not is_valid_email(user_selected):
            error_msg = 'email %s invalid.' % user_selected
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        repo_id_selected = request.GET.get('repo_id', None)
        if repo_id_selected and not is_valid_repo_id_format(repo_id_selected):
            error_msg = 'repo_id %s invalid.' % repo_id_selected
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        start = per_page * (current_page - 1)
        limit = per_page

        # org_id = 0, show all file audit
        events = get_perm_audit_events(user_selected, 0, repo_id_selected,
                                       start, limit) or []

        has_next_page = True if len(events) == per_page else False

        # Use dict to reduce memcache fetch cost in large for-loop.
        from_nickname_dict = {}
        from_contact_email_dict = {}
        to_nickname_dict = {}
        to_contact_email_dict = {}
        repo_dict = {}
        from_user_email_set = set()
        to_user_email_set = set()
        repo_id_set = set()

        for event in events:
            from_user_email_set.add(event.from_user)
            to_user_email_set.add(event.to)
            repo_id_set.add(event.repo_id)

        for e in from_user_email_set:
            if e not in from_nickname_dict:
                from_nickname_dict[e] = email2nickname(e)
            if e not in from_contact_email_dict:
                from_contact_email_dict[e] = email2contact_email(e)
        for e in to_user_email_set:
            if e not in to_nickname_dict:
                to_nickname_dict[e] = email2nickname(e)
            if e not in to_contact_email_dict:
                to_contact_email_dict[e] = email2contact_email(e)
        for e in repo_id_set:
            if e not in repo_dict:
                repo_dict[e] = seafile_api.get_repo(e)

        events_info = []
        for ev in events:
            data = {}
            from_user_email = ev.from_user
            to_user_email = ev.to
            data['from_user_email'] = from_user_email
            data['from_user_name'] = from_nickname_dict.get(
                from_user_email, '')
            data['from_user_contact_email'] = from_contact_email_dict.get(
                from_user_email, '')
            data['to_user_email'] = to_user_email
            data['to_user_name'] = to_nickname_dict.get(to_user_email, '')
            data['to_user_contact_email'] = to_contact_email_dict.get(
                to_user_email, '')

            data['etype'] = ev.etype
            data['permission'] = ev.permission

            repo_id = ev.repo_id
            data['repo_id'] = repo_id
            repo = repo_dict.get(repo_id, None)
            data['repo_name'] = repo.name if repo else ''

            data['folder'] = '/' if ev.file_path == '/' else os.path.basename(
                ev.file_path.rstrip('/'))
            data['date'] = utc_datetime_to_isoformat_timestr(ev.timestamp)
            events_info.append(data)

        resp = {
            'share_permission_log_list': events_info,
            'has_next_page': has_next_page,
        }

        return Response(resp)
Example #27
0
File: logs.py Project: cytec/seahub
    def get(self, request):
        """ Get all file access logs.

        Permission checking:
        1. only admin can perform this action.
        """
        try:
            current_page = int(request.GET.get('page', '1'))
            per_page = int(request.GET.get('per_page', '100'))
        except ValueError:
            current_page = 1
            per_page = 100

        user_selected = request.GET.get('email', None)
        if user_selected and not is_valid_email(user_selected):
            error_msg = 'email %s invalid.' % user_selected
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        repo_id_selected = request.GET.get('repo_id', None)
        if repo_id_selected and not is_valid_repo_id_format(repo_id_selected):
            error_msg = 'repo_id %s invalid.' % repo_id_selected
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        start = per_page * (current_page - 1)
        limit = per_page

        # org_id = 0, show all file audit
        events = get_file_audit_events(user_selected, 0, repo_id_selected,
                                       start, limit) or []

        has_next_page = True if len(events) == per_page else False

        # Use dict to reduce memcache fetch cost in large for-loop.
        nickname_dict = {}
        contact_email_dict = {}
        repo_dict = {}
        user_email_set = set()
        repo_id_set = set()

        for event in events:
            user_email_set.add(event.user)
            repo_id_set.add(event.repo_id)

        for e in user_email_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)
        for e in repo_id_set:
            if e not in repo_dict:
                repo_dict[e] = seafile_api.get_repo(e)

        events_info = []
        for ev in events:
            data = {}
            user_email = ev.user
            data['email'] = user_email
            data['name'] = nickname_dict.get(user_email, '')
            data['contact_email'] = contact_email_dict.get(user_email, '')

            data['ip'] = ev.ip
            data['event_type'], data[
                'device'] = generate_file_audit_event_type(ev)
            data['time'] = utc_datetime_to_isoformat_timestr(ev.timestamp)

            repo_id = ev.repo_id
            data['repo_id'] = repo_id
            repo = repo_dict.get(repo_id, None)
            data['repo_name'] = repo.name if repo else ''

            if ev.file_path.endswith('/'):
                data[
                    'file_or_dir_name'] = '/' if ev.file_path == '/' else os.path.basename(
                        ev.file_path.rstrip('/'))
            else:
                data['file_or_dir_name'] = os.path.basename(ev.file_path)
            events_info.append(data)

        resp = {
            'file_access_log_list': events_info,
            'has_next_page': has_next_page,
        }

        return Response(resp)
Example #28
0
    def get(self, request, format=None):

        if not self._can_use_global_address_book(request):
            return api_error(status.HTTP_403_FORBIDDEN,
                             'Guest user can not use global address book.')

        q = request.GET.get('q', None)

        if not q:
            return api_error(status.HTTP_400_BAD_REQUEST, 'Argument missing.')

        users_from_ccnet = []
        users_from_profile = []
        users_result = []
        username = request.user.username

        if settings.CLOUD_MODE:
            if is_org_context(request):
                url_prefix = request.user.org.url_prefix
                users = seaserv.get_org_users_by_url_prefix(url_prefix, -1, -1)

                # search user from ccnet
                users_from_ccnet = filter(lambda u: q in u.email, users)

                # when search profile, only search users in org
                # 'nickname__icontains' for search by nickname
                # 'contact_email__icontains' for search by contact email
                users_from_profile = Profile.objects.filter(Q(user__in=[u.email for u in users]) &
                        (Q(nickname__icontains=q)) | Q(contact_email__icontains=q)).values('user')

            elif settings.ENABLE_GLOBAL_ADDRESSBOOK:
                users_from_ccnet = search_user_from_ccnet(q)
                users_from_profile = Profile.objects.filter(Q(contact_email__icontains=q) |
                        Q(nickname__icontains=q)).values('user')

            else:
                # in cloud mode, user will be added to Contact when share repo
                users = []
                contacts = Contact.objects.get_contacts_by_user(username)
                for c in contacts:
                    try:
                        user = User.objects.get(email = c.contact_email)
                        c.is_active = user.is_active
                    except User.DoesNotExist:
                        continue

                    c.email = c.contact_email
                    users.append(c)

                users_from_ccnet = filter(lambda u: q in u.email, users)
                if is_valid_email(q):
                    users_from_ccnet += search_user_from_ccnet(q)

                # 'user__in' for only get profile of contacts
                # 'nickname__icontains' for search by nickname
                # 'contact_email__icontains' for search by contact
                users_from_profile = Profile.objects.filter(Q(user__in=[u.email for u in users]) &
                        (Q(nickname__icontains=q)) | Q(contact_email__icontains=q)).values('user')

        else:
            users_from_ccnet = search_user_from_ccnet(q)
            users_from_profile = Profile.objects.filter(Q(contact_email__icontains=q) |
                    Q(nickname__icontains=q)).values('user')

        # remove inactive users and add to result
        for u in users_from_ccnet[:10]:
            if u.is_active:
                users_result.append(u.email)

        for p in users_from_profile[:10]:
            try:
                user = User.objects.get(email = p['user'])
            except User.DoesNotExist:
                continue

            if not user.is_active:
                continue

            users_result.append(p['user'])

        # remove duplicate emails
        users_result = {}.fromkeys(users_result).keys()

        try:
            include_self = int(request.GET.get('include_self', 1))
        except ValueError:
            include_self = 1

        if include_self == 0 and username in users_result:
            # reomve myself
            users_result.remove(username)

        try:
            size = int(request.GET.get('avatar_size', 32))
        except ValueError:
            size = 32

        formated_result = format_searched_user_result(request, users_result, size)[:10]
        return HttpResponse(json.dumps({"users": formated_result}), status=200,
                            content_type='application/json; charset=utf-8')
Example #29
0
    def put(self, request):

        email = request.user.username

        if not ENABLE_UPDATE_USER_INFO:
            error_msg = _(u'Feature disabled.')
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        # argument check for name
        name = request.data.get("name", None)
        if name:
            name = name.strip()
            if len(name) > 64:
                error_msg = _(u'Name is too long (maximum is 64 characters)')
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            if "/" in name:
                error_msg = _(u"Name should not include '/'.")
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        # argument check for contact_email
        contact_email = request.data.get("contact_email", None)
        if contact_email:
            
            if not ENABLE_USER_SET_CONTACT_EMAIL:
                error_msg = _(u'Feature disabled.')
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            profile = Profile.objects.get_profile_by_contact_email(contact_email)
            if profile and profile.user != email:
                # if contact email is used by others, return 403
                error_msg = _('Contact email %s already exists.' % contact_email)
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            # update contact email
            contact_email = 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)

        # agrument check for telephone
        telephone = request.data.get('telephone', None)
        if telephone:
            telephone = telephone.strip()
            if len(telephone) > 100:
                error_msg = _('telephone is too long (maximum is 100 characters).')
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        # 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'):
                error_msg = 'list_in_address_book invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        info_dict = {
            'name': name,
            'contact_email': contact_email,
            'telephone': telephone,
            'list_in_address_book': list_in_address_book,
        }

        # update user profile and user additionnal info
        try:
            self._update_user_info(info_dict, email)
        except Exception as e:
            logger.error(e)
            error_msg = 'Internal Server Error'
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

        # get user info and return
        info = self._get_user_info(email)
        return Response(info)
Example #30
0
    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 request.user.org.is_staff:
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        if request.user.org.org_id != org_id:
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        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)

        info = get_user_info(email)
        info['is_active'] = user.is_active

        return Response(info)
Example #31
0
    def put(self, request, org_id, repo_id):
        """Transfer an organization library
        """
        new_owner = request.data.get('email', None)

        if not new_owner:
            error_msg = 'Email invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        if not is_valid_email(new_owner):
            error_msg = 'Email invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        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)

        # permission checking
        if not org_user_exists(org_id, new_owner):
            error_msg = 'User %s not in org %s.' % (new_owner, org_id)
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        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)

        if not is_org_repo(org_id, repo_id):
            error_msg = 'Library %s not in org %s.' % (repo_id, org_id)
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        repo_owner = seafile_api.get_org_repo_owner(repo_id)

        # get repo shared to user/group list
        shared_users = seafile_api.list_org_repo_shared_to(
            org_id, repo_owner, repo_id)
        shared_groups = seafile_api.list_org_repo_shared_group(
            org_id, repo_owner, repo_id)

        # get all pub repos
        pub_repos = seafile_api.list_org_inner_pub_repos_by_owner(
            org_id, repo_owner)

        seafile_api.set_org_repo_owner(org_id, repo_id, new_owner)

        # reshare repo to user
        for shared_user in shared_users:
            shared_username = shared_user.user

            if new_owner == shared_username:
                continue

            seafile_api.org_share_repo(org_id, repo_id, new_owner,
                                       shared_username, shared_user.perm)

        # reshare repo to group
        for shared_group in shared_groups:
            shared_group_id = shared_group.group_id

            if not ccnet_api.is_group_user(shared_group_id, new_owner):
                continue

            seafile_api.add_org_group_repo(repo_id, org_id, shared_group_id,
                                           new_owner, shared_group.perm)

        # check if current repo is pub-repo
        # if YES, reshare current repo to public
        for pub_repo in pub_repos:
            if repo_id != pub_repo.id:
                continue

            seafile_api.set_org_inner_pub_repo(org_id, repo_id,
                                               pub_repo.permission)

            break

        repo_info = {}
        repo_info['owner_email'] = new_owner
        repo_info['owner_name'] = email2nickname(new_owner)
        repo_info['encrypted'] = repo.encrypted
        repo_info['repo_id'] = repo.repo_id
        repo_info['repo_name'] = repo.name
        repo_info['is_department_repo'] = False
        repo_info['group_id'] = ''

        return Response(repo_info)
    def post(self, request):

        if not IS_EMAIL_CONFIGURED:
            error_msg = _('Sending shared link failed. Email service is not properly configured, please contact administrator.')
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        # check args
        email = request.POST.get('email', None)
        if not email:
            error_msg = 'email invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        token = request.POST.get('token', None)
        if not token:
            error_msg = 'token invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        extra_msg = request.POST.get('extra_msg', '')

        # check if token exists
        try:
            link = FileShare.objects.get(token=token)
        except FileShare.DoesNotExist:
            error_msg = 'token %s not found.' % token
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        # check if is share link owner
        username = request.user.username
        if not link.is_owner(username):
            error_msg = 'Permission denied.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        result = {}
        result['failed'] = []
        result['success'] = []
        to_email_list = string2list(email)
        # use contact_email, if present
        useremail = Profile.objects.get_contact_email_by_user(request.user.username)
        for to_email in to_email_list:

            failed_info = {}

            if not is_valid_email(to_email):
                failed_info['email'] = to_email
                failed_info['error_msg'] = 'email invalid.'
                result['failed'].append(failed_info)
                continue

            # prepare basic info
            c = {
                'email': username,
                'to_email': to_email,
                'extra_msg': extra_msg,
            }

            if REPLACE_FROM_EMAIL:
                from_email = useremail
            else:
                from_email = None  # use default from email

            if ADD_REPLY_TO_HEADER:
                reply_to = useremail
            else:
                reply_to = None

            c['file_shared_link'] = gen_shared_link(token, link.s_type)
            c['file_shared_name'] = os.path.basename(link.path.rstrip('/'))
            template = 'shared_link_email.html'

            if link.s_type == 'f':
                c['file_shared_type'] = _("file")
                title = _('A file is shared to you on %s') % get_site_name()
            else:
                c['file_shared_type'] = _("directory")
                title = _('A directory is shared to you on %s') % get_site_name()

            # send email
            try:
                send_html_email(title, template, c, from_email, [to_email], reply_to=reply_to)
                result['success'].append(to_email)
            except Exception as e:
                logger.error(e)
                failed_info['email'] = to_email
                failed_info['error_msg'] = 'Internal Server Error'
                result['failed'].append(failed_info)

        return Response(result)
Example #33
0
def send_shared_link(request):
    """
    Handle ajax post request to send file shared link.
    """
    if not request.method == 'POST':
        raise Http404

    content_type = 'application/json; charset=utf-8'

    if not IS_EMAIL_CONFIGURED:
        data = json.dumps({'error':_(u'Sending shared link failed. Email service is not properly configured, please contact administrator.')})
        return HttpResponse(data, status=500, content_type=content_type)

    form = FileLinkShareForm(request.POST)
    if form.is_valid():
        email = form.cleaned_data['email']
        file_shared_link = form.cleaned_data['file_shared_link']
        file_shared_name = form.cleaned_data['file_shared_name']
        file_shared_type = form.cleaned_data['file_shared_type']
        extra_msg = escape(form.cleaned_data['extra_msg'])

        to_email_list = string2list(email)
        send_success, send_failed = [], []
        # use contact_email, if present
        username = Profile.objects.get_contact_email_by_user(request.user.username)
        for to_email in to_email_list:
            if not is_valid_email(to_email):
                send_failed.append(to_email)
                continue

            if SHARE_LINK_EMAIL_LANGUAGE:
                activate(SHARE_LINK_EMAIL_LANGUAGE)

            # Add email to contacts.
            mail_sended.send(sender=None, user=request.user.username,
                             email=to_email)

            c = {
                'email': request.user.username,
                'to_email': to_email,
                'file_shared_link': file_shared_link,
                'file_shared_name': file_shared_name,
            }

            if extra_msg:
                c['extra_msg'] = extra_msg

            if REPLACE_FROM_EMAIL:
                from_email = username
            else:
                from_email = None  # use default from email

            if ADD_REPLY_TO_HEADER:
                reply_to = username
            else:
                reply_to = None

            try:
                if file_shared_type == 'f':
                    c['file_shared_type'] = _(u"file")
                    send_html_email(_(u'A file is shared to you on %s') % get_site_name(),
                                    'shared_link_email.html',
                                    c, from_email, [to_email],
                                    reply_to=reply_to
                                    )
                else:
                    c['file_shared_type'] = _(u"directory")
                    send_html_email(_(u'A directory is shared to you on %s') % get_site_name(),
                                    'shared_link_email.html',
                                    c, from_email, [to_email],
                                    reply_to=reply_to)

                send_success.append(to_email)
            except Exception:
                send_failed.append(to_email)

        if len(send_success) > 0:
            data = json.dumps({"send_success": send_success, "send_failed": send_failed})
            return HttpResponse(data, status=200, content_type=content_type)
        else:
            data = json.dumps({"error": _("Internal server error, or please check the email(s) you entered")})
            return HttpResponse(data, status=400, content_type=content_type)
    else:
        return HttpResponseBadRequest(json.dumps(form.errors),
                                      content_type=content_type)
Example #34
0
    def get(self, request, format=None):

        if not self._can_use_global_address_book(request):
            return api_error(status.HTTP_403_FORBIDDEN,
                             'Guest user can not use global address book.')

        q = request.GET.get('q', None)

        if not q:
            return api_error(status.HTTP_400_BAD_REQUEST, 'Argument missing.')

        users_from_ccnet = []
        users_from_profile = []
        users_result = []
        username = request.user.username

        if CLOUD_MODE:
            if is_org_context(request):
                url_prefix = request.user.org.url_prefix
                users = seaserv.get_org_users_by_url_prefix(url_prefix, -1, -1)

                # search user from ccnet
                users_from_ccnet = filter(lambda u: q in u.email, users)

                # when search profile, only search users in org
                # 'nickname__icontains' for search by nickname
                # 'contact_email__icontains' for search by contact email
                users_from_profile = Profile.objects.filter(
                    Q(user__in=[u.email
                                for u in users]) & (Q(nickname__icontains=q))
                    | Q(contact_email__icontains=q)).values('user')

            elif ENABLE_GLOBAL_ADDRESSBOOK:
                users_from_ccnet = search_user_from_ccnet(q)
                users_from_profile = Profile.objects.filter(
                    Q(contact_email__icontains=q)
                    | Q(nickname__icontains=q)).values('user')

            else:
                # in cloud mode, user will be added to Contact when share repo
                users = []
                contacts = Contact.objects.get_contacts_by_user(username)
                for c in contacts:
                    try:
                        user = User.objects.get(email=c.contact_email)
                        c.is_active = user.is_active
                    except User.DoesNotExist:
                        continue

                    c.email = c.contact_email
                    users.append(c)

                users_from_ccnet = filter(lambda u: q in u.email, users)
                if is_valid_email(q):
                    users_from_ccnet += search_user_from_ccnet(q)

                # 'user__in' for only get profile of contacts
                # 'nickname__icontains' for search by nickname
                # 'contact_email__icontains' for search by contact
                users_from_profile = Profile.objects.filter(
                    Q(user__in=[u.email
                                for u in users]) & (Q(nickname__icontains=q))
                    | Q(contact_email__icontains=q)).values('user')

        else:
            users_from_ccnet = search_user_from_ccnet(q)
            users_from_profile = Profile.objects.filter(
                Q(contact_email__icontains=q)
                | Q(nickname__icontains=q)).values('user')

        # remove inactive users and add to result
        for u in users_from_ccnet[:10]:
            if u.is_active:
                users_result.append(u.email)

        for p in users_from_profile[:10]:
            try:
                user = User.objects.get(email=p['user'])
            except User.DoesNotExist:
                continue

            if not user.is_active:
                continue

            users_result.append(p['user'])

        # remove duplicate emails
        users_result = {}.fromkeys(users_result).keys()

        try:
            include_self = int(request.GET.get('include_self', 1))
        except ValueError:
            include_self = 1

        if include_self == 0 and username in users_result:
            # reomve myself
            users_result.remove(username)

        try:
            size = int(request.GET.get('avatar_size', 32))
        except ValueError:
            size = 32

        formated_result = format_searched_user_result(request, users_result,
                                                      size)[:10]
        return HttpResponse(json.dumps({"users": formated_result}),
                            status=200,
                            content_type='application/json; charset=utf-8')
Example #35
0
    def post(self, request, org_id):
        """ Add new user to org.

        Permission checking:
        1. only admin can perform this action.
        """
        # argument check
        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 %d not found.' % org_id
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        email = request.POST.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)

        password = request.POST.get('password', None)
        if not password:
            error_msg = 'password invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        try:
            User.objects.get(email=email)
            user_exists = True
        except User.DoesNotExist:
            user_exists = False

        if user_exists:
            error_msg = 'User %s already exists.' % email
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        # check user number limit by license
        if user_number_over_limit():
            error_msg = 'The number of users exceeds the limit.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        # check user number limit by org member quota
        org_members = len(ccnet_api.get_org_emailusers(org.url_prefix, -1, -1))
        if ORG_MEMBER_QUOTA_ENABLED:
            from seahub_extra.organizations.models import OrgMemberQuota
            org_members_quota = OrgMemberQuota.objects.get_quota(org_id)
            if org_members_quota is not None and org_members >= org_members_quota:
                error_msg = 'Failed. You can only invite %d members.' % org_members_quota
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        # create user
        try:
            user = User.objects.create_user(email,
                                            password,
                                            is_staff=False,
                                            is_active=True)
        except User.DoesNotExist as e:
            logger.error(e)
            error_msg = 'Fail to add user %s.' % email
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

        # add user to org
        # set `is_staff` parameter as `0`
        try:
            ccnet_api.add_org_user(org_id, email, 0)
        except Exception as e:
            logger.error(e)
            error_msg = 'Internal Server Error'
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

        name = request.POST.get('name', None)
        if name:
            Profile.objects.add_or_update(email, name)

        if config.FORCE_PASSWORD_CHANGE:
            UserOptions.objects.set_force_passwd_change(email)

        user_info = get_org_user_info(org_id, user)
        return Response(user_info)
Example #36
0
    def post(self, request, org_id):
        """ Add new user to org.

        Permission checking:
        1. only admin can perform this action.
        """
        # argument check
        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 %d not found.' % org_id
            return api_error(status.HTTP_404_NOT_FOUND, error_msg)

        email = request.POST.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)

        password = request.POST.get('password', None)
        if not password:
            error_msg = 'password invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        active = request.POST.get('active', 'true')
        active = active.lower()
        if active not in ('true', 'false'):
            error_msg = 'active invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        is_active = active == 'true'

        try:
            User.objects.get(email=email)
            user_exists = True
        except User.DoesNotExist:
            user_exists = False

        if user_exists:
            error_msg = 'User %s already exists.' % email
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        # check user number limit by license
        if user_number_over_limit():
            error_msg = 'The number of users exceeds the limit.'
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        # check user number limit by org member quota
        org_members = len(ccnet_api.get_org_emailusers(org.url_prefix, -1, -1))
        if ORG_MEMBER_QUOTA_ENABLED:
            from seahub_extra.organizations.models import OrgMemberQuota
            org_members_quota = OrgMemberQuota.objects.get_quota(org_id)
            if org_members_quota is not None and org_members >= org_members_quota:
                error_msg = 'Failed. You can only invite %d members.' % org_members_quota
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        # create user
        try:
            User.objects.create_user(email, password, is_staff=False,
                    is_active=is_active)
        except User.DoesNotExist as e:
            logger.error(e)
            error_msg = 'Fail to add user %s.' % email
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

        # add user to org
        # set `is_staff` parameter as `0`
        try:
            ccnet_api.add_org_user(org_id, email, 0)
        except Exception as e:
            logger.error(e)
            error_msg = 'Internal Server Error'
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

        name = request.POST.get('name', None)
        if name:
            Profile.objects.add_or_update(email, name)

        if config.FORCE_PASSWORD_CHANGE:
            UserOptions.objects.set_force_passwd_change(email)

        user_info = get_org_user_info(org_id, email)
        user_info['active'] = is_active
        return Response(user_info)
Example #37
0
    def get(self, request):
        """ Get all file update logs.

        Permission checking:
        1. only admin can perform this action.
        """

        if not request.user.admin_permissions.can_view_user_log():
            return api_error(status.HTTP_403_FORBIDDEN, 'Permission denied.')

        try:
            current_page = int(request.GET.get('page', '1'))
            per_page = int(request.GET.get('per_page', '100'))
        except ValueError:
            current_page = 1
            per_page = 100

        user_selected = request.GET.get('email', None)
        if user_selected and not is_valid_email(user_selected):
            error_msg = 'email %s invalid.' % user_selected
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        repo_id_selected = request.GET.get('repo_id', None)
        if repo_id_selected and not is_valid_repo_id_format(repo_id_selected):
            error_msg = 'repo_id %s invalid.' % repo_id_selected
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        start = per_page * (current_page - 1)
        limit = per_page

        # org_id = 0, show all file audit
        events = get_file_update_events(user_selected, 0, repo_id_selected,
                                        start, limit) or []

        has_next_page = True if len(events) == per_page else False

        # Use dict to reduce memcache fetch cost in large for-loop.
        nickname_dict = {}
        contact_email_dict = {}
        repo_dict = {}
        user_email_set = set()
        repo_id_set = set()

        for event in events:
            user_email_set.add(event.user)
            repo_id_set.add(event.repo_id)

        for e in user_email_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)
        for e in repo_id_set:
            if e not in repo_dict:
                repo_dict[e] = seafile_api.get_repo(e)

        events_info = []
        for ev in events:
            data = {}
            user_email = ev.user
            data['email'] = user_email
            data['name'] = nickname_dict.get(user_email, '')
            data['contact_email'] = contact_email_dict.get(user_email, '')
            data['time'] = utc_datetime_to_isoformat_timestr(ev.timestamp)

            repo_id = ev.repo_id
            data['repo_id'] = repo_id
            repo = repo_dict.get(repo_id, None)
            data['repo_name'] = repo.name if repo else ''
            data['repo_encrypted'] = repo.encrypted if repo else None

            data['file_operation'] = ev.file_oper
            data['commit_id'] = ev.commit_id
            events_info.append(data)

        resp = {
            'file_update_log_list': events_info,
            'has_next_page': has_next_page,
        }

        return Response(resp)
Example #38
0
    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)
Example #39
0
    def put(self, request, repo_id, format=None):
        """ update a library status, transfer a library, rename a library

        Permission checking:
        1. only admin can perform this action.
        """
        # argument check
        new_status = request.data.get('status', None)
        if new_status:
            if new_status not in ('normal', 'read-only'):
                error_msg = 'status invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        new_repo_name = request.data.get('name', None)
        if new_repo_name:
            if not is_valid_dirent_name(new_repo_name):
                error_msg = 'name invalid.'
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        new_owner = request.data.get('owner', None)
        if new_owner:
            if not is_valid_email(new_owner):
                error_msg = 'owner invalid.'
                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)

        if new_status:
            try:
                seafile_api.set_repo_status(repo_id, normalize_repo_status_str(new_status))
            except Exception as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

        if new_repo_name:
            try:
                res = seafile_api.edit_repo(repo_id, new_repo_name, '', None)
            except Exception as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

            if res == -1:
                e = 'Admin rename failed: ID of library is %s, edit_repo api called failed.' % \
                        repo_id
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

        if new_owner:
            try:
                new_owner_obj = User.objects.get(email=new_owner)
            except User.DoesNotExist:
                error_msg = 'User %s not found.' % new_owner
                return api_error(status.HTTP_404_NOT_FOUND, error_msg)

            if not new_owner_obj.permissions.can_add_repo():
                error_msg = _('Transfer failed: role of %s is %s, can not add library.') % \
                        (new_owner, new_owner_obj.role)
                return api_error(status.HTTP_403_FORBIDDEN, error_msg)

            if MULTI_TENANCY:
                try:
                    if seafile_api.get_org_id_by_repo_id(repo_id) > 0:
                        error_msg = 'Can not transfer organization library.'
                        return api_error(status.HTTP_403_FORBIDDEN, error_msg)

                    if ccnet_api.get_orgs_by_user(new_owner):
                        error_msg = 'Can not transfer library to organization user %s' % new_owner
                        return api_error(status.HTTP_403_FORBIDDEN, error_msg)
                except Exception as e:
                    logger.error(e)
                    error_msg = 'Internal Server Error'
                    return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

            repo_owner = seafile_api.get_repo_owner(repo_id)

            if new_owner == repo_owner:
                error_msg = _("Library can not be transferred to owner.")
                return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

            # get repo shared to user/group list
            shared_users = seafile_api.list_repo_shared_to(
                    repo_owner, repo_id)
            shared_groups = seafile_api.list_repo_shared_group_by_user(
                    repo_owner, repo_id)

            # get all pub repos
            pub_repos = []
            if not request.cloud_mode:
                pub_repos = seafile_api.list_inner_pub_repos_by_owner(repo_owner)

            # transfer repo
            seafile_api.set_repo_owner(repo_id, new_owner)

            # reshare repo to user
            for shared_user in shared_users:
                shared_username = shared_user.user

                if new_owner == shared_username:
                    continue

                seafile_api.share_repo(repo_id, new_owner,
                        shared_username, shared_user.perm)

            # reshare repo to group
            for shared_group in shared_groups:
                shared_group_id = shared_group.group_id

                if not is_group_member(shared_group_id, new_owner):
                    continue

                seafile_api.set_group_repo(repo_id, shared_group_id,
                        new_owner, shared_group.perm)

            # reshare repo to links
            try:
                UploadLinkShare.objects.filter(username=repo_owner, repo_id=repo_id).update(username=new_owner)
                FileShare.objects.filter(username=repo_owner, repo_id=repo_id).update(username=new_owner)
            except Exception as e:
                logger.error(e)
                error_msg = 'Internal Server Error'
                return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

            # check if current repo is pub-repo
            # if YES, reshare current repo to public
            for pub_repo in pub_repos:
                if repo_id != pub_repo.id:
                    continue

                seafile_api.add_inner_pub_repo(repo_id, pub_repo.permission)

                break

            # send admin operation log signal
            admin_op_detail = {
                "id": repo_id,
                "name": repo.name,
                "from": repo_owner,
                "to": new_owner,
            }
            admin_operation.send(sender=None, admin_name=request.user.username,
                    operation=REPO_TRANSFER, detail=admin_op_detail)

        repo = seafile_api.get_repo(repo_id)
        repo_info = get_repo_info(repo)

        return Response(repo_info)
Example #40
0
    def post(self, request, org_id):
        """Added an organization user, check member quota before adding.
        """
        # 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)

        # check plan
        url_prefix = request.user.org.url_prefix
        org_members = len(
            ccnet_api.get_org_users_by_url_prefix(url_prefix, -1, -1))

        if ORG_MEMBER_QUOTA_ENABLED:
            from seahub_extra.organizations.models import OrgMemberQuota
            org_members_quota = OrgMemberQuota.objects.get_quota(
                request.user.org.org_id)
            if org_members_quota is not None and org_members >= org_members_quota:
                err_msg = 'Failed. You can only invite %d members.' % org_members_quota
                return api_error(status.HTTP_403_FORBIDDEN, err_msg)

        if user_number_over_limit():
            return api_error(status.HTTP_403_FORBIDDEN,
                             'The number of users exceeds the limit')

        email = request.data.get('email', '')
        name = request.data.get('name', '')
        password = request.data.get('password', '')

        if not email or not is_valid_email(email):
            return api_error(status.HTTP_400_BAD_REQUEST, 'Email invalid.')

        if not password:
            return api_error(status.HTTP_400_BAD_REQUEST, 'Password invalid.')

        name = name.strip()
        if not name:
            return api_error(status.HTTP_400_BAD_REQUEST, 'Name invalid.')

        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:
            user = User.objects.get(email=email)
            error_msg = 'User %s already exists.' % email
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
        except User.DoesNotExist:
            pass

        try:
            user = User.objects.create_user(email,
                                            password,
                                            is_staff=False,
                                            is_active=True)
        except User.DoesNotExist as e:
            logger.error(e)
            error_msg = 'Fail to add user %s.' % email
            return api_error(status.HTTP_403_FORBIDDEN, error_msg)

        if user and name:
            Profile.objects.add_or_update(username=user.username,
                                          nickname=name)

        set_org_user(org_id, user.username)

        if IS_EMAIL_CONFIGURED:
            if SEND_EMAIL_ON_ADDING_SYSTEM_MEMBER:
                try:
                    send_user_add_mail(request, email, password)
                except Exception, e:
                    logger.error(str(e))
Example #41
0
    def post(self, request):
        """ Create an 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_name = request.data.get('org_name', None)
        if not org_name:
            error_msg = 'org_name invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        admin_email = request.data.get('admin_email', None)
        if not admin_email or not is_valid_email(admin_email):
            error_msg = 'admin_email invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        admin_name = request.data.get('admin_name')

        password = request.data.get('password', None)
        if not password:
            error_msg = 'password invalid.'
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        url_prefix = gen_org_url_prefix(5, 20)
        if ccnet_api.get_org_by_url_prefix(url_prefix):
            error_msg = 'Failed to create organization, please try again later.'
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

        try:
            User.objects.get(email=admin_email)
        except User.DoesNotExist:
            pass
        else:
            error_msg = "User %s already exists." % admin_email
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        # check profile
        if Profile.objects.filter(contact_email=admin_email).exists():
            error_msg = "User %s already exists." % admin_email
            return api_error(status.HTTP_400_BAD_REQUEST, error_msg)

        try:
            new_user = User.objects.create_user(admin_email, password,
                                                is_staff=False, is_active=True)
        except User.DoesNotExist as e:
            logger.error(e)
            error_msg = 'Failed to add user %s.' % admin_email
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
        
        # update profile nickname
        if admin_name:
            Profile.objects.add_or_update(new_user.username, nickname=admin_name)

        try:
            org_id = ccnet_api.create_org(org_name, url_prefix, new_user.username)
        except Exception as e:
            logger.error(e)
            error_msg = 'Internal Server Error'
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

        org = ccnet_api.get_org_by_id(org_id)
        OrgSettings.objects.add_or_update(org, ORG_DEFAULT)
        try:
            org_info = get_org_info(org)
        except Exception as e:
            logger.error(e)
            error_msg = 'Internal Server Error'
            return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)

        return Response(org_info)
Example #42
0
    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)