Exemple #1
0
    def delete(self, key, confirm='yes'):
        c = self.collection
        c.user.authorize('delete', c)

        if confirm == 'no':
            record = locate(c, key)
            if record:
                c.user.authorize('delete', record)

                self.before_delete(record)

                c.store.delete(record)

                c.search_engine(c).delete(
                    record._id,
                )

                self.after_delete(record)

                msg = '%s deleted %s %s' % (
                    c.user.link,
                    c.link,
                    record.name
                )

                logger = logging.getLogger(__name__)
                logger.info(msg)
                log_activity(msg)
                return redirect_to(c.url)
Exemple #2
0
    def edit(self, key, **data):
        """Display an edit form for a record"""
        c = self.collection
        user = c.user

        user.authorize('update', c)

        record = locate(c, key)
        if record:
            user.authorize('read', record)
            user.authorize('update', record)

            c.fields.initialize(record)
            c.fields.update(data)
            form = form_for(c.fields, ButtonField('Save', cancel=record.url))

            if c.verbose:
                msg = '%s edited %s %s' % (
                    user.link,
                    c.link,
                    record.link,
                )
                log_activity(msg)

            return page(form, title=c.item_title)
        else:
            return page('%s missing' % key)
Exemple #3
0
    def create_button(self, *args, **data):
        """Create a record"""

        collection = self.collection
        user = collection.user

        if collection.fields.validate(data):

            record = collection.model(
                collection.fields,
            )

            record.pop('key', None)
            try:
                key = record.key
            except AttributeError:
                key = None

            if key and locate(collection, record.key) is not None:
                error('That {} already exists'.format(collection.item_name))
            else:

                try:
                    # convert property to data attribute
                    # so it gets stored as data
                    record.key = record.key
                except AttributeError:
                    # can happen when key depends on database
                    # auto-increment value.
                    pass

                record.update(dict(
                    created=now(),
                    updated=now(),
                    owner_id=user._id,
                    created_by=user._id,
                    updated_by=user._id,
                ))

                self.before_insert(record)

                collection.store.put(record)

                collection.search_engine(collection).add(
                    record._id,
                    collection.fields.as_searchable(),
                )

                self.after_insert(record)

                msg = '%s added %s %s' % (
                    user.link,
                    collection.link,
                    record.link
                )
                logger = logging.getLogger(__name__)
                logger.info(msg)
                log_activity(msg)

                return redirect_to(collection.url)
Exemple #4
0
    def add_image(self, *_, **kwargs):
        """accept uploaded images and attach them to the record"""

        dummy = zoom.Record(
            filename='dummy.png',
            file=io.StringIO('test'),
        )

        # put the uploaded image data in a bucket
        path = os.path.join(zoom.system.site.data_path, 'buckets')
        bucket = Bucket(path)
        f = kwargs.get('file', dummy)
        name = f.filename
        data = f.file.read()
        item_id = bucket.put(data)

        # create an image record
        image = Image(
            image_id=item_id,
            image_size=len(data),
            image_name=name,
            draft=True,
        )
        images = zoom.store.store_of(Image)
        images.put(image)

        log_activity('%s uploaded image %s' %
                     (zoom.system.user.link, image.access_link))

        return item_id
Exemple #5
0
    def save_button(self, key, *a, **data):
        """Save a record"""
        collection = self.collection
        user = collection.user

        user.authorize('update', collection)

        if collection.fields.validate(data):
            record = locate(collection, key)
            if record:
                user.authorize('update', record)
                record.update(collection.fields)
                record.pop('key', None)
                if record.key != key and locate(collection, record.key):
                    # record key should always be a str, even if the actual
                    # record.id is being used as the key.
                    error('That {} already exists'.format(collection.item_name))
                else:
                    record.updated = now()
                    record.updated_by = user._id

                    # convert property to data attribute
                    # so it gets stored as data
                    record.key = record.key

                    self.before_update(record)

                    collection.store.put(record)

                    collection.search_engine(collection).update(
                        record._id,
                        collection.fields.as_searchable(),
                    )

                    self.after_update(record)

                    msg = '%s updated %s %s' % (
                        user.link,
                        collection.link,
                        record.link
                    )
                    logger = logging.getLogger(__name__)
                    logger.info(msg)
                    log_activity(msg)
                    if record.key != key:
                        log_activity(
                            '%s changed %s %s to %s' % (
                                user.link,
                                collection.link,
                                key,
                                record.key
                            )
                        )
                    return redirect_to(record.url)
Exemple #6
0
    def show(self, key):
        """Show a record"""
        def action_for(record, name):
            return name, '/'.join([record.url, id_for(name)])

        c = self.collection
        user = c.user
        record = locate(c, key)
        if record:
            user.authorize('read', record)

            actions = []
            if user.can('delete', record):
                actions.append(action_for(record, 'Delete'))
            if user.can('update', record):
                actions.append(action_for(record, 'Edit'))
            if user.can('create', record):
                actions.append(action_for(record, 'New'))
            c.fields.initialize(c.model(record))

            if 'updated' in record and 'updated_by' in record:
                memo = (
                    '<div class="meta" style="float:right">'
                    'updated %(when)s by %(who)s'
                    '</div>'
                    '<div style="clear:both"></div>'
                ) % dict(
                    when=zoom.helpers.when(record['updated']),
                    who=zoom.helpers.who(record['updated_by'])
                )
            else:
                memo = ''

            if c.verbose:
                msg = '%s viewed %s %s' % (
                    user.link,
                    c.link,
                    record.link,
                )
                log_activity(msg)

            return page(
                c.fields.show() + memo,
                title=c.item_title,
                actions=actions
            )
Exemple #7
0
    def delete(self, *route, **req_data):
        """Handle a file delete."""
        # Read the file ID from the request, with safety.
        try:
            file_id = UUID(req_data['file_id']).hex
        except ValueError:
            return Response(status='400 Bad Request')

        # Retrieve and delete the file.
        stored_files = StoredFile.collection()
        to_delete = stored_files.first(id=file_id)

        log_activity('%s deleted file %s' %
                     (context.user.link, to_delete.filename))

        stored_files.delete(to_delete)
        get_bucket().delete(to_delete.data_id)

        return Response(status='200 OK')
Exemple #8
0
    def index(self, q='', *args, **kwargs):
        """collection landing page"""
        def matches(item, search_text):
            """match a search by field values"""
            terms = search_text and search_text.split()
            fields.update(item)
            v = repr(fields.display_value()).lower()
            return terms and not any(t.lower() not in v for t in terms)

        c = self.collection
        user = c.user
        fields = c.fields

        if c.request.route[-1:] == ['index']:
            return redirect_to('/' + '/'.join(c.request.route[:-1]), **kwargs)

        actions = user.can('create', c) and ['New'] or []

        authorized = (i for i in c.store if user.can('read', i))
        matching = (i for i in authorized if not q or matches(i, q))
        filtered = c.filter and filter(c.filter, matching) or matching
        items = sorted(filtered, key=c.order)

        if q:
            msg = '%s searched %s with %r (%d found)' % (user.link, c.link, q,
                                                         len(items))
            log_activity(msg)

        if len(items) != 1:
            footer_name = c.title
        else:
            footer_name = c.item_name
        footer = '%s %s' % (len(items), footer_name.lower())

        content = browse([c.model(i) for i in items],
                         labels=c.labels,
                         columns=c.columns,
                         fields=c.fields,
                         footer=footer)

        return page(content, title=c.title, actions=actions, search=q)
Exemple #9
0
    def remove_image(self, *_, **kwargs):
        """remove a dropzone image"""
        # k contains item_id and filename for file to be removed
        item_id = kwargs.get('id', None)

        # detach the image from the record
        if item_id:
            images = zoom.store.store_of(Image)
            key = images.first(image_id=item_id)
            log_activity('%s deleted image %s' %
                         (zoom.system.user.link, key.image_name))
            if key:
                images.delete(key)

            # delete the bucket
            path = os.path.join(zoom.system.site.data_path, 'buckets')
            bucket = Bucket(path)
            if item_id in bucket.keys():
                bucket.delete(item_id)
                return 'ok'
            return 'empty'
Exemple #10
0
    def upload(self, *route, **req_data):
        """Handle a file upload."""
        # Read the FieldStorage.
        file_desc = req_data['file']
        file_mimetype = req_data['mimetype']
        if not isinstance(file_desc, FieldStorage):
            # Python is dangerous when the type is incorrectly assumed.
            return Response(b'invalid request body', status='400 Bad Request')

        # Persist the file.
        data_id = get_bucket().put(file_desc.value)
        to_store = StoredFile(id=uuid4().hex,
                              data_id=data_id,
                              mimetype=file_mimetype,
                              content_length=len(file_desc.value),
                              original_name=file_desc.filename)
        StoredFile.collection().put(to_store)

        log_activity('%s uploaded file %s' %
                     (context.user.link, to_store.access_link))

        # Respond.
        return Response(bytes(to_store.access_url, 'utf-8'),
                        status='201 Created')
Exemple #11
0
    def index(self, q='', *args, **kwargs):
        """collection landing page"""

        def get_recent(number):
            cmd = """
                select row_id, max(value) as newest
                from attributes
                where kind = %s and attribute in ("created", "updated")
                group by row_id
                order by newest desc
                limit %s
            """
            ids = [id for id, _ in c.store.db(cmd, c.store.kind, number)]
            return c.store.get(ids)

        c = self.collection
        user = c.user

        if c.request.route[-1:] == ['index']:
            return redirect_to('/'+'/'.join(c.request.route[:-1]), **kwargs)

        actions = user.can('create', c) and ['New'] or []

        logger = logging.getLogger(__name__)
        if q:
            title = 'Selected ' + c.title
            records = c.search_engine(c).search(q)
        else:
            many_records = bool(len(c.store) > 50)
            logger.debug('many records: %r', many_records)
            if many_records and not kwargs.get('all'):
                title = 'Most Recently Updated ' + c.title
                records = get_recent(15)
                actions.append(('Show All', 'clients?all=1'))
            else:
                title = c.title
                records = c.store

        authorized = (i for i in records if user.can('read', i))
        filtered = c.filter and filter(c.filter, authorized) or authorized
        items = sorted(filtered, key=c.order)
        num_items = len(items)

        if num_items != 1:
            footer_name = c.title.lower()
        else:
            footer_name = c.item_title.lower()

        if q:
            msg = '%s searched %s with %r (%d found)' % (
                user.link, c.link, q, num_items
            )
            log_activity(msg)
            footer = '{:,} {} found in search of {:,} {}'.format(
                num_items,
                footer_name,
                len(c.store),
                c.title.lower(),
            )
        else:
            if many_records:
                footer = '{:,} {} shown of {:,} {}'.format(
                    num_items,
                    footer_name,
                    len(c.store),
                    c.title.lower(),
                )
            else:
                footer = '%s %s' % (len(items), footer_name)

        content = browse(
            [c.model(i) for i in items],
            labels=c.get_labels(),
            columns=c.get_columns(),
            fields=c.fields,
            footer=footer
        )

        return page(content, title=title, actions=actions, search=q)
Exemple #12
0
    def index(self, q='', *args, **kwargs):
        """collection landing page"""

        c = self.collection
        user = c.user

        if c.request.route[-1:] == ['index']:
            return redirect_to('/' + '/'.join(c.request.route[:-1]), **kwargs)

        actions = user.can('create', c) and ['New'] or []

        logger = logging.getLogger(__name__)
        if q:
            title = 'Selected ' + c.title
            records = c.search(q)
        else:
            has_many_records = c.has_many_records
            logger.debug('has many records: %r', has_many_records)
            if has_many_records and not kwargs.get('all'):
                title = 'Most Recently Updated ' + c.title
                records = self._get_recent(15)
                actions.append(('Show All', c.url + '?all=1'))
            else:
                title = c.title
                records = c.store

        authorized = (i for i in records if user.can('read', i))
        filtered = c.filter and filter(c.filter, authorized) or authorized
        items = sorted(filtered, key=c.order)
        items = c.sorter and c.sorter(items) or items
        num_items = len(items)

        if num_items != 1:
            footer_name = c.title.lower()
        else:
            footer_name = c.item_title.lower()

        if q:
            msg = '%s searched %s with %r (%d found)' % (user.link, c.link, q,
                                                         num_items)
            log_activity(msg)
            footer = '{:,} {} found in search of {:,} {}'.format(
                num_items,
                footer_name,
                len(c.store),
                c.title.lower(),
            )
        else:
            if has_many_records:
                footer = '{:,} {} shown of {:,} {}'.format(
                    num_items,
                    footer_name,
                    len(c.store),
                    c.title.lower(),
                )
            else:
                footer = '%s %s' % (len(items), footer_name)

        content = browse([c.model(i) for i in items],
                         labels=c.get_labels(),
                         columns=c.get_columns(),
                         fields=c.fields,
                         footer=footer)

        return page(content, title=title, actions=actions, search=q)