def group_invite_user(self, inviter, group, email, timeout=3): """ This method sets up an event that will allow a user to join a group. @type inviter: self.account_class @param inviter: The account that is setting up the invitation @type group: self.group_class @param group_name: The group that should be joined @type email: str @param : The email adrress of the user that is invited @type timeout: int @param timeout: The number of days until the confirmation key expires. @rtype: dict @return: A dictionary with the following keys: 'confirmation_key': <str> The code that is used to confirm the invitation 'match_user': <str> A username, if a user exists with that email-address 'match_user_email': An e-mailaddress. Not sure why? """ ac = self.account_class(self.db) assert hasattr(inviter, 'entity_id') assert hasattr(group, 'entity_id') timeout = DateTimeDelta(int(timeout)) if timeout.day < 1: raise CerebrumError('Timeout too short (%d)' % timeout.day) if (timeout > cereconf.MAX_INVITE_PERIOD): raise CerebrumError("Timeout too long (%d)" % timeout.day) ret = {'confirmation_key': self.vhutils.setup_event_request( group.entity_id, self.co.va_group_invitation, params={'inviter_id': inviter.entity_id, 'group_id': group.entity_id, 'invitee_mail': email, 'timeout': timeout.day,}, change_by=inviter.entity_id)} # check if e-mail matches a valid username try: ac.find_by_name(email) ret['match_user'] = ac.account_name if ac.np_type in (self.co.fedaccount_type, self.co.virtaccount_type): ret['match_user_email'] = ac.get_email_address() except NotFoundError: pass return ret
def group_create(self, group_name, description, creator, owner, url=None, forward=None): """ This method creates a new VirtHome group. NOTE: Some group name formats are reserved for specific applications! This method WILL allow creation of reserved group names. @type group_name: str @param group_name: The name of the new group @type description: str @param description: The group description @type creator: self.account_class @param creator: The account object of the creator of this group. @type owner: self.account_class @param owner: The account object of the owner of this group. @type url: str @param url: A url resource associated with the group @type forward: str @param forward: A url resource to an external app that uses this group """ gr = self.group_class(self.db) if self.vhutils.group_exists(group_name): raise CerebrumError("Group name '%s' already exists" % group_name) # TBD: Verify owner.np_type is FEDaccount? Must it be? try: gr.populate(creator.entity_id, group_name, description) gr.write_db() gr.set_group_resource(url) except (ValueError, AssertionError): raise CerebrumError(str(sys.exc_info()[1])) forward = self.vhutils.whitelist_url(forward) if forward: gr.populate_trait(self.co.trait_group_forward, strval=forward) for spread in getattr(cereconf, "BOFHD_NEW_GROUP_SPREADS", ()): gr.add_spread(self.co.human2constant(spread, self.co.Spread)) gr.write_db() roles = GroupRoles(self.db) roles.add_admin_to_group(owner.entity_id, gr.entity_id) return gr
def wrapper(self, *args, **kwargs): if not getattr(self, 'operator_id', None): if hasattr(self, 'log'): self.log.debug('Method (%s) requires operator_id', method.__name__) raise CerebrumError('%s requires login' % method.__name__) return method(self, *args, **kwargs)
def get_const(self, const_str, const_type): """ Wrap h2c with caching, and raise error if not found. """ if not hasattr(self, '_co_cache'): self._co_cache = dict() if (const_str, const_type) in self._co_cache: return self._co_cache[(const_str, const_type)] const = self.co.human2constant(const_str, const_type) if const: return self._co_cache.setdefault((const_str, const_type), const) raise CerebrumError("No constant '%s' of type '%s'" % (const_str, const_type))
def __get_const(self, const_type, value): u""" A human2constant that accepts Constants as input. :raises CerebrumError: If the constant doesn't exist. """ if isinstance(value, const_type): const = value else: const = self.co.human2constant(value, const_type=const_type) if const is None: raise CerebrumError('No {!r} code {!r}'.format(const_type, value)) return const
def set_auth_data(self, auth_method, auth_data): """Register new auth data of the specified type. If the entity had an entry for that auth type, it's silently overwritten with auth_data. If auth_data is None, the corresponding entry (i.e. the proper auth_method's row for self) will be removed. IOW this method can be used to delete authentication data. """ binds = { "entity_id": self.entity_id, "auth_method": int(auth_method), "auth_data": auth_data } if not self.validate_auth_data(auth_method, auth_data): raise CerebrumError( "Invalid auth_data '%s' for auth_method %s" % (auth_data, str(self.const.EntityAuthentication(auth_method)))) if auth_data is None: self.execute( """ DELETE FROM [:table schema=cererbum name=entity_authentication_info] WHERE entity_id = :entity_id AND auth_method = :auth_method """, binds) return auth_in_db = self.get_auth_data(auth_method) if not auth_in_db: self.execute( """ INSERT INTO [:table schema=cererbum name=entity_authentication_info] VALUES (:entity_id, :auth_method, :auth_data) """, binds) elif auth_in_db != auth_data: self.execute( """ UPDATE [:table schema=cererbum name=entity_authentication_info] SET auth_data = :auth_data WHERE entity_id = :entity_id AND auth_method = :auth_method """, binds)
def create_account(self, account_type, account_name, email, expire_date, human_first_name, human_last_name, with_confirmation=True): """Create an account of the specified type. This is a convenience function to avoid duplicating some of the work. @type account_type: subclass of BaseVirtHomeAccount @param account_type: The account class type to use. @type account_name: str @param account_name: Account name to give the new account @type email: str @param email: The email address of the account owner @type expire_date: mx.DateTime.DateTime @param expire_date: The expire date for the account @type human_first_name: str @param human_first_name: The first name(s) of the account owner @type human_last_name: str @param human_last_name: The last name(s) of the account owner @type with_confirmation: bool @param with_confirmation: Controls whether a confirmation request should be issued for this account. In some situations it makes no sense to confirm anything. NOTE: The caller must dispatch any confirmation mail. This controls whether a confirmation event/code should be created and returned. @rtype: list [ BaseVirtHomeAccount, str ] @return: The newly created account, and the confirmation key needed to confirm the given email address. NOTE: If with_confirmation was False, the confirmation key will be empty. """ assert issubclass(account_type, BaseVirtHomeAccount) # Creation can still fail later, but hopefully this captures most # situations and produces a sensible account_name. if self.account_exists(account_name): raise CerebrumError("Account '%s' already exists" % account_name) account = account_type(self.db) account.populate(email, account_name, human_first_name, human_last_name, expire_date) account.write_db() account.populate_trait(self.co.trait_user_retained, numval=0) # Never exported to ldap account.write_db() self.assign_default_user_spreads(account) magic_key = "" if with_confirmation: magic_key = self.setup_event_request(account.entity_id, self.co.va_pending_create) return account, magic_key
def test_error(self): raise CerebrumError('test')
def write_mail_dns(): """ Gather data and dump to ldif. """ logger = Factory.get_logger('cronjob') hosts, cnames, lower2host, hosts_only_mx = get_hosts_and_cnames() # email domains (lowercase -> domain), in alphabetical order domains = OrderedDict((d.lower(), d) for d in sorted(get_email_domains())) domain_wo_mx = set() for domain in domains: # Verify that domains have an MX-record. for arg in cereconf.LDAP_MAIL_DNS['dig_args']: zone = arg[0] if domain.endswith(zone) and not (domain in hosts_only_mx or domain in hosts): logger.error("email domain without MX defined: %s" % domain) domain_wo_mx.add(domain.lower()) # Valid email domains only requires MX if domain in hosts_only_mx: hosts_only_mx.remove(domain) for host in hosts_only_mx: logger.warn( "MX defined but no A/AAAA record or valid email domain: %s" % host) if domain_wo_mx: cause = "{0:d} email domains without mx".format(len(domain_wo_mx)) logger.error("{0}, this must be rectified manually!".format(cause)) raise CerebrumError(cause) def handle_domain_host(entry, host): entry["host"] = (lower2host[host], ) for cname in hosts[host]: if cname not in domains: entry["cn"].add(lower2host[cname]) del cnames[cname] del hosts[host] lw = LDIFutils.LDIFWriter('MAIL_DNS', filename=None) dn_suffix = lw.getconf('dn') lw.write_container() for domain, output in domains.items(): dn = "cn=%s,%s" % (output, dn_suffix) entry = {"cn": set((output, )), "objectClass": ("uioHost", )} try: if domain in cnames: # This fails `if domain not in hosts` entry["cn"].add(lower2host[cnames[domain]]) handle_domain_host(entry, cnames[domain]) elif domain in hosts: handle_domain_host(entry, domain) except Exception: logger.error( "domain=%r, cnames[domain]=%r, " "in hosts=%r, in cnames=%r", domain, cnames.get(domain), domain in hosts, domain in cnames) raise lw.write_entry(dn, entry) for host in sorted(hosts.keys()): l2h = lower2host[host] names = set(lower2host[cname] for cname in hosts[host]) names.add(l2h) lw.write_entry("host=%s,%s" % (l2h, dn_suffix), { "host": (l2h, ), "cn": names, "objectClass": ("uioHost", ) }) lw.close()