def register_user(self, login, password, email=None, **kwargs): with self.internal_session() as session: # for consistency, keep same error as unique check hook (although not required) errmsg = session._('the value "%s" is already used, use another one') if (session.execute('CWUser X WHERE X login %(login)s', {'login': login}, build_descr=False) or session.execute('CWUser X WHERE X use_email C, C address %(login)s', {'login': login}, build_descr=False)): qname = role_name('login', 'subject') raise ValidationError(None, {qname: errmsg % login}) # we have to create the user user = self.vreg['etypes'].etype_class('CWUser')(session) if isinstance(password, unicode): # password should *always* be utf8 encoded password = password.encode('UTF8') kwargs['login'] = login kwargs['upassword'] = password self.glob_add_entity(session, EditedEntity(user, **kwargs)) ################################### # Monkeypatch register user to create the user in the "guests" group # for security reason (just read ability) session.execute('SET X in_group G WHERE X eid %(x)s, G name "guests"', {'x': user.eid}) ################################### if email or '@' in login: d = {'login': login, 'email': email or login} if session.execute('EmailAddress X WHERE X address %(email)s', d, build_descr=False): qname = role_name('address', 'subject') raise ValidationError(None, {qname: errmsg % d['email']}) session.execute('INSERT EmailAddress X: X address %(email)s, ' 'U primary_email X, U use_email X ' 'WHERE U login %(login)s', d, build_descr=False) session.commit() return True
def check_urls(self, source_entity): """Check URL of source entity: `urls` is a string that may contain one URL per line), and return a list of at least one validated URL. """ urls = source_entity.url if source_entity.url else '' urls = [url.strip() for url in urls.splitlines() if url.strip()] if not urls: msg = _('specifying an URL is mandatory') raise ValidationError(source_entity.eid, {role_name('url', 'subject'): msg}) return urls
def _check_config_dict(self, eid, confdict, raise_on_error=True): """Check configuration of source entity and return config dict properly typed with defaults set. If `raise_on_error` is True (the default), a ValidationError will be raised if some error is encountered, else the problem will be ignored. """ processed = {} for optname, optdict in self.options: value = confdict.pop(optname, optdict.get('default')) if value is configuration.REQUIRED: if not raise_on_error: continue msg = _('specifying %s is mandatory') msgargs = optname raise ValidationError(eid, {role_name('config', 'subject'): msg}, msgargs) elif value is not None: # type check try: value = configuration._validate(value, optdict, optname) except Exception as ex: if not raise_on_error: continue msg = str(ex) raise ValidationError(eid, {role_name('config', 'subject'): msg}) processed[optname] = value # cw < 3.10 bw compat try: processed['adapter'] = confdict['adapter'] except KeyError: pass # check for unknown options if confdict and tuple(confdict) != ('adapter',): if raise_on_error: msg = _('unknown options %s') msgargs = ', '.join(confdict) raise ValidationError(eid, {role_name('config', 'subject'): msg}, msgargs) else: self.warning('unknown options %s', ', '.join(confdict)) # add options to processed, they may be necessary during migration processed.update(confdict) return processed
def check_inlined_allowed(self): """check inlining is possible, raise ValidationError if not possible """ # don't use the persistent schema, we may miss cardinality changes # in the same transaction for rdef in self.reverse_relation_type: card = rdef.cardinality[0] if not card in '?1': qname = role_name('inlined', 'subject') rtype = self.name stype = rdef.stype otype = rdef.otype msg = self._cw._("can't set inlined=True, " "%(stype)s %(rtype)s %(otype)s " "has cardinality=%(card)s") raise ValidationError(self.eid, {qname: msg % locals()})
def new_fs_path(self, entity, attr): # We try to get some hint about how to name the file using attribute's # name metadata, so we use the real file name and extension when # available. Keeping the extension is useful for example in the case of # PIL processing that use filename extension to detect content-type, as # well as providing more understandable file names on the fs. basename = [str(entity.eid), attr] name = entity.cw_attr_metadata(attr, 'name') if name is not None: basename.append(name) fd, fspath = uniquify_path(self.default_directory, '_'.join(basename)) if fspath is None: msg = entity._cw._('failed to uniquify path (%s, %s)') % ( self.default_directory, '_'.join(basename)) raise ValidationError(entity.eid, {role_name(attr, 'subject'): msg}) assert isinstance(fspath, str) return fd, fspath
def role_name(self): """return <field.name>-<field.role> if role is specified, else field.name""" assert self.name, 'field without a name (give it to constructor for explicitly built fields)' if self.role is not None: return role_name(self.name, self.role) return self.name