Пример #1
0
    def entry_form(self):
        '''
        create an entry form for manager use
        '''
        if not hasattr(self, 'form'):
            class_name = 'ContentEntryForm'
            class_parents = (Form,)
            attributes = {}

            form = type(class_name, (Form,), {})

            title_field = TextField('Title', [Required('Title is required')])
            title_field.bind(form, 'content_entry_title')
            setattr(form, 'content_entry_title', title_field)
            slug_field = TextField('Slug', [Required('Slug is required')])
            slug_field.bind(form, 'content_entry_slug')
            setattr(form, 'content_entry_slug', slug_field)

            tag_field = TextField('Tags')
            tag_field.bind(form, 'content_entry_tag')
            setattr(form, 'content_entry_tag', tag_field)

            status_field = SelectField('Status', choices=self.status_options)
            status_field.bind(form, 'content_entry_status')
            setattr(form, 'content_entry_status', status_field)

            save_field = SubmitField('Save')
            save_field.bind(form, 'content_entry_save')
            setattr(form, 'content_entry_save', save_field)

            delete_field = SubmitField('Delete')
            delete_field.bind(form, 'content_entry_delete')
            setattr(form, 'content_entry_delete', delete_field)

            field_groups = []
            for group in self.field_groups:
                if group.fields:
                    field_group = {'uuid': group.uuid,
                                   'name': group.name,
                                   'fields': []}
                    for field in group.fields:
                        form_field = field.field(field.name)
                        form_field.bind(form, field.name)
                        setattr(form, field.name, form_field)

                        field_group['fields'].append(field.name)
                    field_groups.append(field_group)
            attributes['_field_groups'] = field_groups
            self.form = form
            self.form._field_groups = field_groups
        return self.form
Пример #2
0
class HoneyPotField(Field):
    """
    The HoneyPotField
    """
    widget = widgets.HoneyPotWidget()

    def __init__(self, *args, **kwargs):
        try:
            self.private_key = current_app.config['WTF_HONEY_POT_PRIVATE_KEY']
        except KeyError:
            raise RuntimeError("No WTF_HONEY_POT_PRIVATE_KEY config set")

        self.timeout = current_app.config.get('WTF_HONEY_POT_TIMEOUT', 300)
        self.unbound_field = TextField(self.random())
        self.entrie_count = randint(1, 5)
        super(HoneyPotField, self).__init__(*args, **kwargs)

    def random(self):
        return ''.join(choice(string.ascii_lowercase + string.digits) for _ in range(randint(5,12)))

    @property
    def short_name(self):
        return self.random()

    @short_name.setter
    def short_name(self, value):
        pass

    @property
    def style(self):
        return choice(RANDOM_STYLES)

    def process(self, formdata, data=_unset_value):
        self.entries = []

        if formdata:
            indices = sorted(set(self._extract_indices(HONEY_POT_PREFIX, formdata)))
            for name in indices:
                try:
                    obj_data = formdata[name]
                except StopIteration:
                    obj_data = u''

                self._add_entry(formdata, obj_data, name=name)

        else:
            self.reset_honeypot(formdata)

    def validate(self, form, extra_validators=tuple()):
        success = True
        try:
            control_field = self._get_control_field()
        except ValueError:
            return False

        if not self.data or not control_field.data:
            success = False

        for entrie in self.entries:
            if entrie.data and not entrie.name.startswith(self.get_control_prefix()):
                success = False
                # No need to continue the trap is caught
                break

        current_time = int(control_field.name[9:])
        success = success and self.validate_time(current_time)
        success = success and control_field.data == self.hash_entries(current_time)

        # If the honey_pot caught a bot or a bear resetting the trap
        if not success:
            self.reset_honeypot(None)

        return success

    def hash_entries(self, current_time):
        names = [str(current_time), self.private_key]
        for entrie in self.entries:
            if not entrie.name.startswith(self.get_control_prefix()):
                names.append(entrie.name)

        name_values = u''.join(sorted(names))

        return unicode(sha256(name_values).hexdigest())

    def validate_time(self, epoch):
        now = datetime.now()
        try:
            then = datetime.fromtimestamp(epoch)
        except Exception:
            return False
        else:
            window = timedelta(seconds=self.timeout)
            if (then + window) < now:
                return False
        return True

    def reset_honeypot(self, formdata):
        self.entries = []
        while len(self.entries) < self.entrie_count:
            self._add_entry(formdata, None)
        # Adding control form element
        self._add_control_field(formdata)

    @classmethod
    def get_control_prefix(self):
        return '{0}_{1}_'.format(HONEY_POT_PREFIX, 'check')

    def _get_epoch(self):
        """
        Function to help unittest
        """
        return datetime.now().strftime('%s')

    def _add_control_field(self, formdata):
        """
        Create control field to validate honeypot
        """
        current_time = self._get_epoch()
        value = self.hash_entries(current_time)
        self._add_entry(formdata=formdata, data=value, name="{0}{1}".format(self.get_control_prefix(), current_time))

    def _get_control_field(self):
        control_fields = [entrie for entrie in self.entries if entrie.name.startswith(self.get_control_prefix())]
        if len(control_fields) != 1:
            raise ValueError('Must one control_field')
        return control_fields[0]

    def _extract_indices(self, prefix, formdata):
        """
        Yield all the names given the honey pot prefix.

        This will yeild all the fields example hp_vazzg or hp_2gpkdef3ch
        """
        for k in formdata:
            if k.startswith(prefix):
                yield k

    def _add_entry(self, formdata=None, data=_unset_value, name=None, identifier=None):
        name = name if name else 'hp_' + self.random()
        identifier = identifier if identifier else self.random()

        field = self.unbound_field.bind(form=None, name=name, id=identifier)
        field.process(formdata, data)
        self.entries.append(field)
        return field

    def __iter__(self):
        return iter(self.entries)

    def __len__(self):
        return len(self.entries)

    def __getitem__(self, index):
        return self.entries[index]

    @property
    def data(self):
        return [f.data for f in self.entries]