Ejemplo n.º 1
0
 def from_csv(self, user, row):
     if len(row) < 4:
         raise AdminError(_("Invalid line"))
     self.name = row[1].strip()
     try:
         self.quota = int(row[2].strip())
     except ValueError:
         raise AdminError(
             _("Invalid quota value for domain '%s'" % self.name))
     self.enabled = (row[3].strip() == 'True')
     self.save(creator=user)
Ejemplo n.º 2
0
def remove_permission(request):
    domid = request.GET.get("domid", None)
    daid = request.GET.get("daid", None)
    if domid is None or daid is None:
        raise AdminError(_("Invalid request"))
    try:
        account = User.objects.get(pk=daid)
        domain = Domain.objects.get(pk=domid)
    except (User.DoesNotExist, Domain.DoesNotExist):
        raise AdminError(_("Invalid request"))
    if not request.user.can_access(account) or not request.user.can_access(
            domain):
        raise PermDeniedException
    domain.remove_admin(account)
    return ajax_simple_response({"status": "ok"})
Ejemplo n.º 3
0
def _validate_alias(request,
                    form,
                    successmsg,
                    tplname,
                    commonctx,
                    callback=None):
    """Alias validation

    Common function shared between creation and modification actions.
    """
    error = None
    if form.is_valid():
        form.set_recipients()
        try:
            alias = form.save()
        except IntegrityError:
            raise AdminError(_("Alias with this name already exists"))
        if callback:
            callback(request.user, alias)
        return ajax_simple_response({"status": "ok", "respmsg": successmsg})

    if "targets" in request.POST:
        targets = request.POST.getlist("targets")
        commonctx["targets"] = targets[:-1]

    commonctx["form"] = form
    commonctx["error"] = error
    return ajax_response(request, status="ko", template=tplname, **commonctx)
Ejemplo n.º 4
0
def list_quotas(request, tplname="admin/quotas.html"):
    from modoboa.lib.dbutils import db_type

    sort_order, sort_dir = get_sort_order(request.GET, "address")
    mboxes = Mailbox.objects.get_for_admin(
        request.user, request.GET.get("searchquery", None))
    mboxes = mboxes.exclude(quota=0)
    if sort_order in ["address", "quota", "quota_value__bytes"]:
        mboxes = mboxes.order_by("%s%s" % (sort_dir, sort_order))
    elif sort_order == "quota_usage":
        if db_type() == "postgres":
            select = '(admin_quota.bytes::float / (CAST(admin_mailbox.quota AS BIGINT) * 1048576)) * 100'
        else:
            select = 'admin_quota.bytes / (admin_mailbox.quota * 1048576) * 100'
        mboxes = mboxes.extra(select={'quota_usage': select},
                              where=["admin_quota.mbox_id=admin_mailbox.id"],
                              tables=["admin_quota"],
                              order_by=["%s%s" % (sort_dir, sort_order)])
    else:
        raise AdminError(_("Invalid request"))
    page = get_listing_page(mboxes, request.GET.get("page", 1))
    return ajax_simple_response({
        "status":
        "ok",
        "page":
        page.number,
        "paginbar":
        pagination_bar(page),
        "table":
        _render_to_string(request, tplname, {"mboxes": page})
    })
Ejemplo n.º 5
0
    def mail_home(self):
        """Retrieve the home directory of this mailbox.
 
        The home directory refers to the place on the file system
        where the mailbox data is stored.

        We ask dovecot to give us this information because there are
        several patterns to understand and we don't want to implement
        them.        
        """
        hm = parameters.get_admin("HANDLE_MAILBOXES", raise_error=False)
        if hm is None or hm == "no":
            return None
        if self.__mail_home is None:
            curuser = pwd.getpwuid(os.getuid()).pw_name
            mbowner = parameters.get_admin("MAILBOXES_OWNER")
            options = {}
            if curuser != mbowner:
                options['sudo_user'] = mbowner
            code, output = exec_cmd(
                "doveadm user %s -f home" % self.full_address, **options)
            if code:
                raise AdminError(
                    _("Failed to retrieve mailbox location (%s)" % output))
            self.__mail_home = output.strip()
        return self.__mail_home
Ejemplo n.º 6
0
def import_account_mailbox(user, account, row):
    account.email = row[0].strip()
    if account.email != "":
        account.save()
        mailbox, domname = split_mailbox(account.email)
        try:
            domain = Domain.objects.get(name=domname)
        except Domain.DoesNotExist:
            raise AdminError(
                _("Account import failed (%s): domain does not exist" %
                  account.username))
        if not user.can_access(domain):
            raise PermDeniedException
        mb = Mailbox(address=mailbox,
                     domain=domain,
                     user=account,
                     use_domain_quota=True)
        mb.set_quota(override_rules=user.has_perm("admin.change_domain"))
        mb.save(creator=user)
    if account.group == "DomainAdmins":
        for domname in row[1:]:
            try:
                dom = Domain.objects.get(name=domname.strip())
            except Domain.DoesNotExist:
                continue
            dom.add_admin(account)
Ejemplo n.º 7
0
    def save(self, user, domain):
        if self.cleaned_data["create_dom_admin"] == "no":
            return
        username = "******" % (self.cleaned_data["dom_admin_username"],
                              domain.name)
        try:
            da = User.objects.get(username=username)
        except User.DoesNotExist:
            pass
        else:
            raise AdminError(_("User '%s' already exists" % username))
        da = User(username=username, email=username, is_active=True)
        da.set_password("password")
        da.save()
        da.set_role("DomainAdmins")
        da.post_create(user)
        mb = Mailbox(address=self.cleaned_data["dom_admin_username"],
                     domain=domain,
                     user=da,
                     use_domain_quota=True)
        mb.set_quota(override_rules=user.has_perm("admin.change_domain"))
        mb.save(creator=user)

        if self.cleaned_data["create_aliases"] == "yes":
            al = Alias(address="postmaster", domain=domain, enabled=True)
            al.save(int_rcpts=[mb], creator=user)

        domain.add_admin(da)
Ejemplo n.º 8
0
    def set_recipients(self):
        """Recipients dispatching

        We make a difference between 'local' recipients (the ones hosted
        by Modoboa) and 'external' recipients.
        """
        self.ext_rcpts = []
        self.int_rcpts = []
        total = 0

        for k, v in self.cleaned_data.items():
            if not k.startswith("recipients"):
                continue
            if v == "":
                continue
            local_part, domname = split_mailbox(v)
            if domname is None:
                raise AdminError("%s %s" % (_("Invalid mailbox"), v))
            try:
                domain = Domain.objects.get(name=domname)
            except Domain.DoesNotExist:
                domain = None
            if domain is not None:
                try:
                    rcpt = Alias.objects.get(domain=domain, address=local_part)
                    if rcpt.full_address == self.cleaned_data["email"]:
                        rcpt = None
                except Alias.DoesNotExist:
                    rcpt = None
                if rcpt is None:
                    try:
                        rcpt = Mailbox.objects.get(domain=domain, address=local_part)
                    except Mailbox.DoesNotExist:
                        raise AdminError(_("Local recipient %s not found" % v))
                if rcpt in self.int_rcpts:
                    raise AdminError(_("Recipient %s already present" % v))
                self.int_rcpts += [rcpt]
                total += 1
                continue

            if v in self.ext_rcpts:
                raise AdminError(_("Recipient %s already present" % v))
            self.ext_rcpts += [v]
            total += 1

        if total == 0:
            raise AdminError(_("No recipient defined"))
Ejemplo n.º 9
0
    def from_csv(self, user, row):
        """Create a domain alias from a CSV row

        Expected format: ["domainalias", domain alias name, targeted domain, enabled]

        :param user: a ``User`` object
        :param row: a list containing the alias definition
        """
        if len(row) < 4:
            raise AdminError(_("Invalid line"))
        self.name = row[1].strip()
        domname = row[2].strip()
        try:
            self.target = Domain.objects.get(name=domname)
        except Domain.DoesNotExist:
            raise AdminError(_("Unknown domain %s" % domname))
        self.enabled = row[3].strip() == 'True'
        self.save(creator=user)
Ejemplo n.º 10
0
 def save(self, commit=True):
     account = super(AccountFormGeneral, self).save(commit=False)
     if self.user == account and not self.cleaned_data["is_active"]:
         raise AdminError(_("You can't disable your own account"))
     if commit:
         if "password1" in self.cleaned_data \
            and self.cleaned_data["password1"] != "":
             account.set_password(self.cleaned_data["password1"])
         account.save()
         account.set_role(self.cleaned_data["role"])
     return account
Ejemplo n.º 11
0
    def from_csv(self, user, row, expected_elements=5):
        """Create a new alias from a CSV file entry

        """
        if len(row) < expected_elements:
            raise AdminError(_("Invalid line: %s" % row))
        localpart, domname = split_mailbox(row[1].strip())
        try:
            domain = Domain.objects.get(name=domname)
        except Domain.DoesNotExist:
            raise AdminError(_("Domain '%s' does not exist" % domname))
        if not user.can_access(domain):
            raise PermDeniedException
        self.address = localpart
        self.domain = domain
        self.enabled = (row[2].strip() == 'True')
        int_rcpts = []
        ext_rcpts = []
        for rcpt in row[3:]:
            rcpt = rcpt.strip()
            localpart, domname = split_mailbox(rcpt)
            try:
                Domain.objects.get(name=domname)
            except Domain.DoesNotExist:
                ext_rcpts += [rcpt]
                continue
            try:
                target = Alias.objects.get(domain__name=domname,
                                           address=localpart)
                if target.full_address == self.full_address:
                    target = None
            except Alias.DoesNotExist:
                target = None
            if target is None:
                try:
                    target = Mailbox.objects.get(address=localpart,
                                                 domain__name=domname)
                except Mailbox.DoesNotExist:
                    raise AdminError(_("Local recipient %s not found" % rcpt))
            int_rcpts += [target]
        self.save(int_rcpts=int_rcpts, ext_rcpts=ext_rcpts, creator=user)
Ejemplo n.º 12
0
    def set_quota(self, value=None, override_rules=False):
        """Set or update quota's value for this mailbox.

        A value equal to 0 means the mailbox won't have any quota. The
        following cases allow people to define such behaviour:
        * The domain has no quota
        * :keyword:`override_rules` is True

        :param integer value: the quota's value
        :param bool override_rules: allow to override defined quota rules
        """
        if value is None:
            if self.use_domain_quota:
                self.quota = self.domain.quota
            else:
                self.quota = 0
        elif int(value) > self.domain.quota and not override_rules:
            raise AdminError(
                _("Quota is greater than the allowed domain's limit (%dM)" %
                  self.domain.quota))
        else:
            self.quota = value
        if not self.quota and self.domain.quota and not override_rules:
            raise AdminError(_("A quota is required"))
Ejemplo n.º 13
0
def newaccount(request, tplname='common/wizard_forms.html'):
    def create_account(steps):
        """Account creation callback

        Called when all creation steps have been validated.

        :param steps: the steps data
        """
        genform = steps[0]["form"]
        genform.is_valid()
        account = genform.save()
        account.post_create(request.user)

        mailform = steps[1]["form"]
        try:
            mailform.save(request.user, account)
        except AdminError:
            # A bit uggly: transaction management doesn't work very
            # well with nested functions. Need to wait for django 1.6
            # and atomicity.
            account.delete(request.user, False)
            raise

    ctx = dict(title=_("New account"),
               action=reverse(newaccount),
               formid="newaccount_form",
               submit_label=_("Create"))
    cwizard = CreationWizard(create_account)
    cwizard.add_step(AccountFormGeneral,
                     _("General"),
                     [dict(classes="btn-inverse next", label=_("Next"))],
                     new_args=[request.user])
    cwizard.add_step(AccountFormMail,
                     _("Mail"), [
                         dict(classes="btn-primary submit", label=_("Create")),
                         dict(classes="btn-inverse prev", label=_("Previous"))
                     ],
                     formtpl="admin/mailform.html")

    if request.method == "POST":
        retcode, data = cwizard.validate_step(request)
        if retcode == -1:
            raise AdminError(data)
        if retcode == 1:
            return ajax_simple_response(
                dict(status="ok",
                     title=cwizard.get_title(data + 1),
                     stepid=data))
        if retcode == 2:
            return ajax_simple_response(
                dict(status="ok", respmsg=_("Account created")))

        from modoboa.lib.templatetags.lib_tags import render_form
        return ajax_simple_response(
            dict(status="ko",
                 stepid=data,
                 form=render_form(cwizard.steps[data]["form"])))

    cwizard.create_forms()
    ctx.update(steps=cwizard.steps)
    ctx.update(subtitle="1. %s" % cwizard.steps[0]['title'])
    return render(request, tplname, ctx)
Ejemplo n.º 14
0
    def save(self, user, account):
        if self.cleaned_data["email"] == "":
            return None

        if self.cleaned_data["quota_act"]:
            self.cleaned_data["quota"] = None

        if not hasattr(self, "mb") or self.mb is None:
            locpart, domname = split_mailbox(self.cleaned_data["email"])
            try:
                domain = Domain.objects.get(name=domname)
            except Domain.DoesNotExist:
                raise AdminError(_("Domain does not exist"))
            if not user.can_access(domain):
                raise PermDeniedException
            try:
                Mailbox.objects.get(address=locpart, domain=domain)
            except Mailbox.DoesNotExist:
                pass
            else:
                raise AdminError(
                    _("Mailbox %s already exists" %
                      self.cleaned_data["email"]))
            events.raiseEvent("CanCreate", user, "mailboxes")
            self.mb = Mailbox(address=locpart,
                              domain=domain,
                              user=account,
                              use_domain_quota=self.cleaned_data["quota_act"])
            self.mb.set_quota(self.cleaned_data["quota"],
                              user.has_perm("admin.add_domain"))
            self.mb.save(creator=user)
        else:
            newaddress = None
            if self.cleaned_data["email"] != self.mb.full_address:
                newaddress = self.cleaned_data["email"]
            elif account.group == "SimpleUsers" and account.username != self.mb.full_address:
                newaddress = account.username
            if newaddress is not None:
                local_part, domname = split_mailbox(newaddress)
                try:
                    domain = Domain.objects.get(name=domname)
                except Domain.DoesNotExist:
                    raise AdminError(_("Domain does not exist"))
                if not user.can_access(domain):
                    raise PermDeniedException
                self.mb.rename(local_part, domain)

            self.mb.use_domain_quota = self.cleaned_data["quota_act"]
            override_rules = True \
                if not self.mb.quota or user.has_perm("admin.add_domain") \
                else False
            self.mb.set_quota(self.cleaned_data["quota"], override_rules)
            self.mb.save()

        account.email = self.cleaned_data["email"]
        account.save()

        for name, value in self.cleaned_data.iteritems():
            if not name.startswith("aliases"):
                continue
            if value == "":
                continue
            local_part, domname = split_mailbox(value)
            try:
                self.mb.alias_set.get(address=local_part, domain__name=domname)
            except Alias.DoesNotExist:
                pass
            else:
                continue
            events.raiseEvent("CanCreate", user, "mailbox_aliases")
            al = Alias(address=local_part, enabled=account.is_active)
            al.domain = Domain.objects.get(name=domname)
            al.save(int_rcpts=[self.mb], creator=user)

        for alias in self.mb.alias_set.all():
            if len(alias.get_recipients()) >= 2:
                continue
            if not len(
                    filter(
                        lambda name: self.cleaned_data[name] == alias.
                        full_address, self.cleaned_data.keys())):
                alias.delete()

        return self.mb