Beispiel #1
0
def update_mailbox(data):
    """
    Updates a mailbox.

    Field ``domain``, if given, can be ID (int), name (str) or
    an instance of a Domain.

    Data fields:
    ``id``:     Required. ID of mailbox to update
    ``editor``: Required. ID of Principal
    ``mtime``:  Required

    :param data: Dict with data fields
    :returns: Instance of updated mailbox
    """
    # If 'domain' is set, it may be ID, name or instance of a domain.
    if 'domain' in data:
        if not isinstance(data['domain'], Domain):
            data['domain'] = Domain.find_one(data['domain'])
        data['domain_id'] = data['domain'].id
        del data['domain']
    # Make sure the password is encrypted
    if 'pwd' in data and not data['pwd'].startswith('{'):
        data['pwd'] = pysite.security.pwd_context(data['pwd'],
            PASSWORD_SCHEME)

    sess = DbSession()
    mb = sess.query(Mailbox).filter(Mailbox.id==data['id']).one()
    for k, v in data.items():
        setattr(mb, k, v)
    sess.flush()
    return mb
Beispiel #2
0
 def xhr_list_domains(self):
     sess = DbSession()
     qry = sess.query(Domain.id, Domain.name).order_by(
         Domain.name)
     opts = "\n".join(['<option value="{0}">{1}</option>'.format(
         markupsafe.escape(x[0]), markupsafe.escape(x[1])) for x in qry])
     return "<select>\n" + opts + "\n</select>"
Beispiel #3
0
 def xhr_create_rolemember(self):
     log = pysite.lib.JsonResp()
     principal_ids = [int(x) for x in self.request.POST.getall(
         'principal_ids[]') if int(x) != 0]
     if not principal_ids:
         log.error('No principals selected')
         return log.resp
     role_ids = [int(x) for x in self.request.POST.getall(
         'role_ids[]') if int(x) != 0]
     if not role_ids:
         log.error('No roles selected')
         return log.resp
     sess = DbSession()
     try:
         for rid in role_ids:
             for pid in principal_ids:
                 # XXX This is not atomic!
                 if not sess.query(RoleMember.id).filter(
                         sa.and_(RoleMember.principal_id == pid,
                             RoleMember.role_id == rid)).all():
                     manager.create_rolemember(dict(
                         owner=self.request.user.uid,
                         principal_id=pid,
                         role_id=rid
                     ))
     except (StatementError) as exc:
         log.fatal(str(exc))
         return log.resp
     else:
         log.ok("{0} principals added to {1} roles"
             .format(len(principal_ids), len(role_ids)))
         return log.resp
Beispiel #4
0
def update_domain(data):
    """
    Updates a domain.

    Field ``tenant``, if given, can be ID (int), principal (str) or
    an instance of a Principal.

    Data fields:
    ``id``:     Required. ID of domain to update
    ``editor``: Required. ID of Principal
    ``mtime``:  Required

    :param data: Dict with data fields
    :returns: Instance of updated domain
    """
    # If 'tenant' is set, it may be ID, name or instance of a principal.
    if 'tenant' in data:
        if not isinstance(data['tenant'], Principal):
            data['tenant'] = Principal.find_one(data['tenant'])
        data['tenant_id'] = data['tenant'].id
        del data['tenant']
    sess = DbSession()
    dom = sess.query(Domain).filter(Domain.id==data['id']).one()
    for k, v in data.items():
        setattr(dom, k, v)
    sess.flush()
    return dom
Beispiel #5
0
def update_alias(data):
    """
    Updates an existing alias.

    Field ``domain``, if given, can be ID (int), name (str) or
    an instance of a Domain.

    Data fields:
    ``id``:     Required. ID of alias to update
    ``editor``: Required. ID of Principal
    ``mtime``:  Required

    :param data: Dict with data fields
    :returns: Instance of updated alias
    """
    if 'domain' in data:
        if not isinstance(data['domain'], Domain):
            data['domain'] = Domain.find_one(data['domain'])
        data['domain_id'] = data['domain'].id
        del data['domain']
    sess = DbSession()
    al = sess.query(Alias).filter(Alias.id==data['id']).one()
    for k, v in data.items():
        setattr(al, k, v)
    sess.flush()
    return al
Beispiel #6
0
def create_domain(data):
    """
    Creates a new domain record.

    Field ``tenant`` can be ID (int), principal (str) or
    an instance of a Principal.

    Data fields:
    - ``owner``: Required
    - ``tenant``: Principal

    :param data: Dict with data fields
    :returns: Instance of created domain
    """
    # If 'tenant' is set, it may be ID, name or instance of a principal.
    if 'tenant' in data:
        if not isinstance(data['tenant'], Principal):
            data['tenant'] = Principal.find_one(data['tenant'])
        data['tenant_id'] = data['tenant'].id
        del data['tenant']
    # Set defaults
    if not 'max_mailboxes' in data:
        data['max_mailboxes'] = MAX_MAILBOXES
    if not 'max_aliases' in data:
        data['max_aliases'] = MAX_ALIASES
    if not 'quota' in data:
        data['quota'] = QUOTA
    
    sess = DbSession()
    dom = Domain()
    for k, v in data.items():
        setattr(dom, k, v)
    sess.add(dom)
    sess.flush() # to get ID of domain
    return dom
Beispiel #7
0
def create_alias(data):
    """
    Creates a new alias record.

    Field ``domain`` can be ID (int), name (str) or
    an instance of a Domain.

    Data fields:
    - ``owner``: Required
    - ``domain``: Domain

    :param data: Dict with data fields
    :returns: Instance of created alias
    """
    if 'domain' in data:
        if not isinstance(data['domain'], Domain):
            data['domain'] = Domain.find_one(data['domain'])
        data['domain_id'] = data['domain'].id
        del data['domain']
    sess = DbSession()
    al = Alias()
    for k, v in data.items():
        setattr(al, k, v)
    sess.add(al)
    sess.flush() # to get ID of alias
    return al
Beispiel #8
0
def update_principal(data):
    """
    Updates a principal.

    Data fields:
    ``id``:     Required. ID of principal to update
    ``editor``: Required
    ``mtime``:  Required

    :param data: Dict with data fields
    :returns: Instance of updated principal
    """
    # Make sure the password is encrypted
    if 'pwd' in data:
        if not data['pwd'].startswith(('{', '$')):
            data['pwd'] = pysite.security.pwd_context.encrypt(data['pwd'],
                PASSWORD_SCHEME)
    # Allow only lowercase principals
    if 'principal' in data:
        data['principal'] = data['principal'].lower()
    # Ditto email
    if 'email' in data:
        data['email'] = data['email'].lower()
    sess = DbSession()
    p = sess.query(Principal).filter(Principal.id == data['id']).one()
    for k, v in data.items():
        setattr(p, k, v)
    # If display_name is emptied, use principal
    if not p.display_name:
        p.display_name = p.principal
    sess.flush()
    return p
Beispiel #9
0
 def xhr_list_tenants(self):
     sess = DbSession()
     qry = sess.query(Principal.id, Principal.display_name).order_by(
         Principal.display_name)
     opts = "\n".join(['<option value="{0}">{1}</option>'.format(
         markupsafe.escape(x[0]), markupsafe.escape(x[1])) for x in qry])
     return "<select>\n" + opts + "\n</select>"
Beispiel #10
0
def delete_domain(id_or_name):
    """
    Deletes a domain.

    :param id: ID of domain to delete
    """
    sess = DbSession()
    dom = Domain.find_one(id_or_name)
    sess.delete(dom)
    sess.flush()
Beispiel #11
0
def delete_alias(id_or_name):
    """
    Deletes an alias.

    :param id: ID of alias to delete
    """
    sess = DbSession()
    al = Alias.find_one(id_or_name)
    sess.delete(al)
    sess.flush()
Beispiel #12
0
def delete_mailbox(id_or_name):
    """
    Deletes a mailbox.

    :param id: ID of mailbox to delete
    """
    sess = DbSession()
    mb = Mailbox.find_one(id_or_name)
    sess.delete(mb)
    sess.flush()
Beispiel #13
0
def load_by_principal(principal):
    """
    Loads a princpal instance by principal.
    """
    sess = DbSession()
    try:
        p = sess.query(Principal).filter(
            Principal.principal == principal).one()
    except NoResultFound:
        raise AuthError('Principal not found')
    return p
Beispiel #14
0
 def _build_browse_queries(self, request, grid):
     sess = DbSession()
     vw_browse = pysite.vmailmgr.models.get_vw_alias_browse()
     # Build query for count and apply filter
     qry_total = sess.query(sa.func.count(vw_browse.c.id))
     qry_total = grid.apply_filter(qry_total)
     qry = sess.query(vw_browse)
     # Setup field names for initial order and primary key
     if not grid.order_field:
         grid.order_field = 'id'
     # Apply filter, order and limit from grid to qry.
     # Grid must have been initialised with order_field for this.
     qry = grid.apply_filter(qry)
     qry = grid.apply_order(qry)
     qry = grid.apply_limit(qry)
     return (qry, qry_total, )
Beispiel #15
0
def create_role(data):
    """
    Creates a new role record.

    Data fields:
    - ``owner``: Required
    :param data: Dict with data fields
    :returns: Instance of created role
    """
    sess = DbSession()
    r = Role()
    for k, v in data.items():
        setattr(r, k, v)
    sess.add(r)
    sess.flush()
    return r
Beispiel #16
0
def create_rolemember(data):
    """
    Creates a new rolemember record.

    Data fields:
    - ``owner``:        Required
    - ``principal_id``: Required
    - ``role_id``:      Required
    :param data: Dict with data fields
    :returns: Instance of created rolemember
    """
    sess = DbSession()
    rm = RoleMember()
    for k, v in data.items():
        setattr(rm, k, v)
    sess.add(rm)
    sess.flush()
    return rm
Beispiel #17
0
def update_role(data):
    """
    Updates a role.

    Data fields:
    ``id``:     Required. ID of role to update
    ``editor``: Required
    ``mtime``:  Required

    :param data: Dict with data fields
    :returns: Instance of updated role
    """
    sess = DbSession()
    r = sess.query(Role).filter(Role.id == data['id']).one()
    for k, v in data.items():
        setattr(r, k, v)
    sess.flush()
    return r
Beispiel #18
0
def _login(filter, pwd):
    """
    Performs login.

    Called by the ``login_by...`` functions which initialise the filter.
    """
    filter.append(Principal.is_enabled == True)
    filter.append(Principal.is_blocked == False)
    sess = DbSession()
    try:
        p = sess.query(Principal).filter(and_(*filter)).one()
    except NoResultFound:
        raise AuthError('Principal not found')
    if not pysite.security.pwd_context.verify(pwd, p.pwd):
        raise AuthError('Wrong credentials')
    p.prev_login_time = p.login_time
    p.login_time = datetime.datetime.now()
    sess.flush()
    return p
Beispiel #19
0
def delete_rolemember(id):
    """
    Deletes a rolemember.

    :param id: ID of rolemember to delete
    """
    sess = DbSession()
    rm = sess.query(RoleMember).filter(RoleMember.id == id).one()
    sess.delete(rm)
    sess.flush()
Beispiel #20
0
def delete_role(id):
    """
    Deletes a role.

    :param id: ID of role to delete
    """
    sess = DbSession()
    r = sess.query(Role).filter(Role.id == id).one()
    sess.delete(r)
    sess.flush()
Beispiel #21
0
def delete_principal(id):
    """
    Deletes a principal.

    :param id: ID of principal to delete
    """
    sess = DbSession()
    p = sess.query(Principal).filter(Principal.id == id).one()
    sess.delete(p)
    sess.flush()
Beispiel #22
0
def create_principal(data):
    """
    Creates a new principal record.

    Data fields:
    - ``owner``: Required
    - ``roles``: Optional list of role names. Role 'users' is always
                 automatically set.
                 If we provide a value for roles that evaluates to False,
                 this account is not member of any role.

    :param data: Dict with data fields
    :returns: Instance of created principal
    """
    # Determine roles this principal will be member of.
    # Always at least 'users'.
    if 'roles' in data:
        if data['roles']:
            roles = set(data['roles'] + ['users'])
        else:
            roles = set()
        del data['roles']
    else:
        roles = ['users']
    # Make sure the password is encrypted
    if 'pwd' in data:
        if not data['pwd'].startswith(('{', '$')):
            data['pwd'] = pysite.security.pwd_context.encrypt(data['pwd'],
                PASSWORD_SCHEME)
    # If display_name is not explicitly set, use principal, thus
    # preserving its case (real principal will be stored lower case).
    if not 'display_name' in data:
        data['display_name'] = data['principal']
    # Allow only lowercase principals
    data['principal'] = data['principal'].lower()
    # Ditto email
    data['email'] = data['email'].lower()

    sess = DbSession()
    # Create principal
    p = Principal()
    for k, v in data.items():
        setattr(p, k, v)
    sess.add(p)
    sess.flush()  # to get ID of principal
    # Load/create the roles and memberships
    for name in roles:
        try:
            r = sess.query(Role).filter(Role.name == name).one()
        except NoResultFound:
            r = Role(name=name, owner=data['owner'])
            sess.add(r)
            sess.flush()
        rm = RoleMember(principal_id=p.id, role_id=r.id, owner=p.owner)
        sess.add(rm)
    sess.flush()
    return p
Beispiel #23
0
def create_mailbox(data):
    """
    Creates a new mailbox record.

    Field ``domain`` can be ID (int), name (str) or
    an instance of a Domain.

    Data fields:
    - ``name``: Required. Str
    - ``owner``: Required. ID of Principal.
    - ``domain``: Required. Domain.
    - ``pwd``: Required. Password.

    :param data: Dict with data fields
    :returns: Instance of created mailbox
    """
    dom = None
    # If 'domain' is set, it may be ID, name or instance of a domain.
    # Load the appropriate domain and set 'domain_id'.
    if 'domain' in data:
        if not isinstance(data['domain'], Domain):
            data['domain'] = Domain.find_one(data['domain'])
        data['domain_id'] = data['domain'].id
        dom = data['domain']
        del data['domain']
    # 'domain' was not set, so load domain by its ID from 'domain_id'
    if not dom:
        dom = Domain.find_one(data['domain_id'])
    # Check that we are in limits
    if len(dom.mailboxes) >= dom.max_mailboxes:
        raise PySiteError("Maximum number of mailboxes reached.")
    # Make sure the password is encrypted
    if not data['pwd'].startswith('{'):
        data['pwd'] = pysite.security.pwd_context.encrypt(data['pwd'],
            PASSWORD_SCHEME)
    # Set defaults
    if not 'uid' in data:
        data['uid'] = UID
    if not 'gid' in data:
        data['gid'] = GID
    if not 'quota' in data:
        data['quota'] = dom.quota  # Default from domain!
    # Make sure, 'home_dir' is absolute path 
    d = data['home_dir'] if 'home_dir' in data else HOME_DIR
    d = d.format(root=ROOT_DIR, domain=dom.name, user=data['name'])
    if not d.startswith(os.path.sep):
        d = os.path.join(ROOT_DIR, d)
    data['home_dir'] = d
    # Make sure, 'mail_dir' is absolute path 
    d = data['mail_dir'] if 'mail_dir' in data else MAIL_DIR
    d = d.format(root=ROOT_DIR, domain=dom.name, user=data['name'])
    if not d.startswith(os.path.sep):
        d = os.path.join(ROOT_DIR, d)
    data['mail_dir'] = d

    sess = DbSession()
    mb = Mailbox()
    for k, v in data.items():
        setattr(mb, k, v)
    sess.add(mb)
    sess.flush() # to get ID of mailbox
    return mb