Beispiel #1
0
    def fetch_forward_info(self):
        """
        Fetch forward info for all users with both AD and exchange spread.
        """
        # from Cerebrum.modules.Email import EmailDomain
        from Cerebrum.modules.Email import EmailTarget
        from Cerebrum.modules.Email import EmailForward
        etarget = EmailTarget(self.db)
        # rewrite = EmailDomain(self.db).rewrite_special_domains
        eforward = EmailForward(self.db)

        # We need a email target -> entity_id mapping
        target_id2target_entity_id = {}
        for row in etarget.list_email_targets_ext():
            if row['target_entity_id']:
                te_id = int(row['target_entity_id'])
                target_id2target_entity_id[int(row['target_id'])] = te_id

        # Check all email forwards
        for row in eforward.list_email_forwards():
            te_id = target_id2target_entity_id.get(int(row['target_id']))
            acc = self.get_account(account_id=te_id)
            # We're only interested in those with AD and exchange spread
            if acc.to_exchange:
                acc.add_forward(row['forward_to'])
def get_entities_with_primary_addr(db):
    """ Get the target entity_id of primary email addresses. """
    et = EmailTarget(db)
    for r in et.list_email_target_primary_addresses():
        if r['target_entity_id'] is None:
            # Some targets don't have a target entity (sympa, rt, pipes, ...)
            continue
        yield int(r['target_entity_id'])
def get_accounts(db, spread, include_expired=False, exclude_groups=None):
    """Fetch a list of all accounts with a entity_person owner and IMAP-spread.

    @param spread_name: Name of spread to filter user search by.
    @type  spread_name: String

    @param expired: If True, include expired accounts. Defaults to False.
    @type  expired: bool

    @param exclude: List of group name strings to exclude. Accounts that are
                    members of this group are excluded from the report.
                    Defaults to None.
    @type  exclude: List of strings

    @return List of account names that is missing a primary email address.
    """
    # Database-setup
    co = Factory.get('Constants')(db)
    ac = Factory.get('Account')(db)
    et = EmailTarget(db)

    search_args = {'owner_type': co.entity_person}
    if include_expired:
        search_args['expire_start'] = None

    logger.debug('looking up excluded groups...')
    excluded = ExcludeLookup(db, exclude_groups)

    logger.debug('caching accounts spreads...')
    account_spreads = SpreadLookup(db, co.entity_account)

    # for account in accounts:
    for account in ac.search(**search_args):

        if account['account_id'] not in account_spreads:
            # is_deleted() or is_reserved()
            continue

        if int(spread) in account_spreads[account['account_id']]:
            continue

        if account['account_id'] in excluded:
            logger.debug('Ignoring %s (%d), member of excluded group',
                         account['name'])
            continue

        # Find EmailTarget for account
        et.clear()
        try:
            et.find_by_target_entity(account['account_id'])
        except Errors.NotFoundError:
            logger.info('No email targets for account with id %d',
                        account['account_id'])
            continue

        if et.email_target_type == co.email_target_account:
            yield account['name']
def handle_person(database, source_system, affiliations, send_notifications,
                  email_config, data):
    pe = Factory.get('Person')(database)
    ac = Factory.get('Account')(database)
    et = EmailTarget(database)
    ef = EmailForward(database)
    ed = EmailDomain(database)

    if (data.get('resourceType') == 'persons' and
            'affiliation' in data.get(
                'urn:ietf:params:event:SCIM:modify', {}).get(
                    'attributes', [])):
        ident = int(data.get('sub').split('/')[-1])

        if not pe.list_affiliations(
                person_id=ident,
                source_system=source_system,
                affiliation=affiliations):
            return

        pe.clear()
        pe.find(ident)

        removed_forwards = defaultdict(list)
        for account_id in map(lambda x: x['account_id'],
                              pe.get_accounts(
                                  filter_expired=False)):
            try:
                et.clear()
                et.find_by_target_entity(account_id)
            except Errors.NotFoundError:
                continue
            ef.clear()
            ef.find(et.entity_id)
            for forward in map(lambda x: x['forward_to'],
                               ef.get_forward()):
                try:
                    ed.clear()
                    ed.find_by_domain(forward.split('@')[-1])
                except Errors.NotFoundError:
                    ac.clear()
                    ac.find(account_id)
                    ef.delete_forward(forward)
                    removed_forwards[ac.get_primary_mailaddress()
                                     ].append(forward)
                    logger.info(
                        'Deleted forward {} from {}'.format(
                            forward, ac.account_name))
        if send_notifications:
            for k, v in removed_forwards.items():
                sendmail(
                    toaddr=k,
                    fromaddr=email_config.sender,
                    subject=email_config.subject,
                    body=email_config.body_template.format('\n'.join(v)))
    database.commit()
Beispiel #5
0
    def init_account_mail(self, use_mail_module):
        u""" Cache account mail addresses.

        This method adds to the general to fill the primary email attribute
        This is done to prepare for changing the normal email attribute

        :param bool use_mail_module:
            If True, Cerebrum.modules.Email will be used to populate this
            cache; otherwise the `self.account_mail` dict will be None.
        """
        super(OrgLDIFUiOMixin, self).init_account_mail(use_mail_module)
        if use_mail_module:
            timer = make_timer(
                self.logger,
                "Doing UiO specific changes to account e-mail addresses...")
            self.account_primary_mail = self.account_mail.copy()
            # We don't want to import this if mod_email isn't present.
            from Cerebrum.modules.Email import EmailTarget
            targets = EmailTarget(self.db).list_email_target_addresses
            mail = {}
            for row in targets(target_type=self.const.email_target_account,
                               domain='uio.no',
                               uname_local=True):
                # Can only return [email protected] so no need for any checks
                mail[int(row['target_entity_id'])] = "@".join(
                    (row['local_part'], row['domain']))
            self.account_mail.update(mail)
            timer("...UiO specfic account e-mail addresses done.")
Beispiel #6
0
    def init_account_mail(self, use_mail_module):
        u""" Cache account mail addresses.

        This method builds a dict cache that maps account_id -> primary email
        address, and assigns the `dict.get` method to `self.account_mail`.

        NOTE: The LDAP_PERSON['mail_target_types'] setting decides which email
        target types are considered.

        :param bool use_mail_module:
            If True, Cerebrum.modules.Email will be used to populate this
            cache; otherwise the `self.account_mail` method will be None (not
            implemented).

        """
        # Set self.account_mail = None if not use_mail_module, otherwise
        #                         function: account_id -> ('address' or None).
        if use_mail_module:
            timer = make_timer(self.logger,
                               "Fetching account e-mail addresses...")

            # Get target types from config
            mail_target_types = []
            for value in ldapconf('PERSON', 'mail_target_types', []):
                code = self.const.human2constant(value, self.const.EmailTarget)
                if code is None:
                    self.logger.warn("Unknown EmailTarget %r in setting %s",
                                     value, "LDAP_PERSON['mail_target_types']")
                else:
                    mail_target_types.append(code)

            # We don't want to import this if mod_email isn't present.
            from Cerebrum.modules.Email import EmailDomain, EmailTarget
            targets = EmailTarget(self.db).list_email_target_primary_addresses
            rewrite = EmailDomain(self.db).rewrite_special_domains

            # Look up target addrs. Note that the reversed order causes the
            # lesser prioritized target types to be overwritten by targets with
            # higher priority.
            mail = {}
            for code in reversed(mail_target_types):
                target_timer = make_timer(self.logger)
                for row in targets(target_type=code):
                    try:
                        mail[int(row['target_entity_id'])] = "@".join(
                            (row['local_part'], rewrite(row['domain'])))
                    except TypeError:
                        continue
                target_timer("...target_type '{!s}' done".format(code))
            self.account_mail = mail.get
            timer("...account e-mail addresses done.")
        else:
            self.account_mail = None
Beispiel #7
0
    def _fetch_primary_mail_addresses(self, user_dict):
        """
        Fetch primary email addresses for users in user_dict.
        Add key, value pair 'mail', <primary address> if found.

        @param user_dict: account_id -> account info mapping
        @type user_dict: dict
        """
        from Cerebrum.modules.Email import EmailDomain, EmailTarget
        etarget = EmailTarget(self.db)
        rewrite = EmailDomain(self.db).rewrite_special_domains

        for row in etarget.list_email_target_primary_addresses(
                target_type=self.co.email_target_account):
            v = user_dict.get(int(row['target_entity_id']))
            if not v:
                continue
            try:
                v['mail'] = "@".join(
                    (row['local_part'], rewrite(row['domain'])))
            except TypeError:
                pass  # Silently ignore
Beispiel #8
0
    def _fetch_primary_mail_addresses(self, user_dict):
        """
        Fetch primary email addresses for users in user_dict.
        Add key, value pair 'mail', <primary address> if found.

        @param user_dict: account_id -> account info mapping
        @type user_dict: dict
        """
        from Cerebrum.modules.Email import EmailDomain, EmailTarget
        etarget = EmailTarget(self.db)
        rewrite = EmailDomain(self.db).rewrite_special_domains

        for row in etarget.list_email_target_primary_addresses(
                target_type=self.co.email_target_account):
            v = user_dict.get(int(row['target_entity_id']))
            if not v:
                continue
            try:
                v['mail'] = "@".join(
                    (row['local_part'], rewrite(row['domain'])))
            except TypeError:
                pass  # Silently ignore
def get_accounts(db, spread, include_expired=False, exclude_groups=None):
    """Fetch a list of all accounts with a entity_person owner and IMAP-spread.

    @param spread_name: Name of spread to filter user search by.
    @type  spread_name: String

    @param expired: If True, include expired accounts. Defaults to False.
    @type  expired: bool

    @param exclude: List of group name strings to exclude. Accounts that are
                    members of this group are excluded from the report.
                    Defaults to None.
    @type  exclude: List of strings

    @return List of account names that is missing a primary email address.
    """
    # Database-setup
    co = Factory.get('Constants')(db)
    ac = Factory.get('Account')(db)
    et = EmailTarget(db)

    search_args = {'owner_type': co.entity_person}
    if include_expired:
        search_args['expire_start'] = None

    logger.debug('looking up excluded groups...')
    excluded = ExcludeLookup(db, exclude_groups)

    logger.debug('caching accounts spreads...')
    account_spreads = SpreadLookup(db, co.entity_account)

    # for account in accounts:
    for account in ac.search(**search_args):

        if account['account_id'] not in account_spreads:
            # is_deleted() or is_reserved()
            continue

        if int(spread) in account_spreads[account['account_id']]:
            continue

        if account['account_id'] in excluded:
            logger.debug('Ignoring %s (%d), member of excluded group',
                         account['name'])
            continue

        # Find EmailTarget for account
        et.clear()
        try:
            et.find_by_target_entity(account['account_id'])
        except Errors.NotFoundError:
            logger.info('No email targets for account with id %d',
                        account['account_id'])
            continue

        if et.email_target_type == co.email_target_account:
            yield account['name']
def handle_person(database, source_system, affiliations, send_notifications,
                  email_config, data):
    pe = Factory.get('Person')(database)
    ac = Factory.get('Account')(database)
    et = EmailTarget(database)
    ef = EmailForward(database)
    ed = EmailDomain(database)

    if (data.get('resourceType') == 'persons' and 'affiliation' in data.get(
            'urn:ietf:params:event:SCIM:modify', {}).get('attributes', [])):
        ident = int(data.get('sub').split('/')[-1])

        if not pe.list_affiliations(person_id=ident,
                                    source_system=source_system,
                                    affiliation=affiliations):
            return

        pe.clear()
        pe.find(ident)

        removed_forwards = defaultdict(list)
        for account_id in map(lambda x: x['account_id'],
                              pe.get_accounts(filter_expired=False)):
            try:
                et.clear()
                et.find_by_target_entity(account_id)
            except Errors.NotFoundError:
                continue
            ef.clear()
            ef.find(et.entity_id)
            for forward in map(lambda x: x['forward_to'], ef.get_forward()):
                try:
                    ed.clear()
                    ed.find_by_domain(forward.split('@')[-1])
                except Errors.NotFoundError:
                    ac.clear()
                    ac.find(account_id)
                    ef.delete_forward(forward)
                    removed_forwards[ac.get_primary_mailaddress()].append(
                        forward)
                    logger.info('Deleted forward {} from {}'.format(
                        forward, ac.account_name))
        if send_notifications:
            for k, v in removed_forwards.items():
                sendmail(toaddr=k,
                         fromaddr=email_config.sender,
                         subject=email_config.subject,
                         body=email_config.body_template.format('\n'.join(v)))
    database.commit()
def get_accs_with_missing_mail_spread(logger, spread_name, expired, exclude):
    """Fetch a list of all accounts with a entity_person owner and IMAP-spread.

    @param logger:  Logger to use.
    @type  logger:  CerebrumLogger

    @param spread_name: Name of spread to filter user search by.
    @type  spread_name: String

    @param expired: If True, include expired accounts. Defaults to False.
    @type  expired: bool

    @param exclude: List of group name strings to exclude. Accounts that are
                    members of this group are excluded from the report.
                    Defaults to None.
    @type  exclude: List of strings

    @return List of account names that is missing a primary email address.
    """

    # Database-setup
    db = Factory.get('Database')()
    co = Factory.get('Constants')(db)
    ac = Factory.get('Account')(db)
    gr = Factory.get('Group')(db)
    et = EmailTarget(db)

    try:
        spread = getattr(co, spread_name)
    except AttributeError:
        logger.error('Spread not found, exiting..')
        sys.exit(2)

    users_wo_mail_spread = []   # List to contain results

    group_ids = group_names_to_gids(logger, gr, exclude)

    # Fetch account list
    if expired:
        accounts = ac.search(owner_type=co.entity_person,
                             expire_start=None)
    else:
        accounts = ac.search(owner_type=co.entity_person)

    for account in accounts:
        ac.clear()
        try:
            ac.find(account['account_id'])
        except Errors.NotFoundError, e:
            logger.error('Can\'t find account with id \'%d\'' %
                         account['account_id'])
            continue

        # Ignore if account is deleted or reserved
        if ac.is_deleted() or ac.is_reserved():
            continue

        # Ignore if account has imap spread
        if spread in [row['spread'] for row in ac.get_spread()]:
            continue

        # Check for group membership
        gr.clear()
        is_member = False
        for group_id in group_ids:
            try:
                gr.find(group_id)
                if gr.has_member(ac.entity_id):
                    is_member = True
                    logger.debug('Ignoring %(account)s, member of %(group)s' %
                                 {"account":ac.account_name,
                                  "group":gr.group_name})
                    break
            except Errors.NotFoundError, e:
                logger.error('Can\'t find group with id %d' % group_id)
                continue