Esempio n. 1
0
    def add(self, name=None, cls=None, read_groups=None, write_groups=None):
        auth = request.identity

        if 'a' not in auth.access(self):
            return drink.unauthorized("Not authorized")

        name = name or request.params.get('name').decode('utf-8')

        if name in self:
            return drink.unauthorized("%r is already defined!"%name)

        if None == cls:
            cls = request.params.get('class')
        if not cls:
            return drink.unauthorized("%r incorrect request!"%name)

        with self._lock():
            o = self._add(name, cls, auth.user.default_read_groups, auth.user.default_write_groups)
        if o is None:
            return drink.unauthorized("You can't create %r objects!"%name)

        if request.is_ajax:
            return o.struct()
        else:
            return drink.rdr(o.quoted_path+'edit')
Esempio n. 2
0
def get_object(current, objpath, no_raise=False):
    """ Fetch an object from database, looking at permissions to approve

    :arg current: root object to browse for childrens
    :type current: :class:`drink.Page`
    :arg objpath: path to the children
    :type objpath: str
    :arg no_raise: (optional) don't raise exceptions
    :type no_raise: `bool`
    """
    path_list = [drink.omni(p) for p in objpath.split("/") if p]
    last_idx = len(path_list) - 1
    pending_path = False
    for i, elt in enumerate(path_list):
        if elt[0] in "._" and elt != "_static":
            return drink.unauthorized("Not authorized (forbidden character)")
        if False != pending_path:
            pending_path.append(elt)
        elif i == last_idx:
            # getting
            try:
                current = current[elt]
                if "r" not in drink.request.identity.access(current):
                    if not no_raise:
                        return drink.unauthorized("Not authorized")
                    return
            except (KeyError, AttributeError, TypeError):
                try:
                    current = getattr(current, elt)
                except AttributeError:
                    if callable(current):
                        pending_path = [elt]
                    else:
                        if not no_raise:
                            raise AttributeError(elt)
                    return
            break  # found a matching object
        else:
            # traversal
            try:
                current = current[elt]
                if "t" not in drink.request.identity.access(current):
                    if not no_raise:
                        return drink.unauthorized("Not authorized")
                    return
            except (KeyError, AttributeError):
                if hasattr(current, elt) and callable(getattr(current, elt)):
                    current = getattr(current, elt)
                    pending_path = []
                else:
                    if no_raise:
                        return
                    raise AttributeError(elt)
    request.pending_path = pending_path
    return current
Esempio n. 3
0
 def borrow(self, item=None):
     """ Borrow an external item """
     if not item:
         item = drink.get_object(drink.db.db, request.POST['item'])
     if item.id in self:
         return drink.unauthorized("An object with the same id stands here!")
     if self.path in item.path:
         return drink.unauthorized("Can't move an object to one if it's children!")
     try:
         parent = drink.get_object(drink.db.db, item.rootpath)
     except Exception, e:
         return drink.unauthorized("Unhandled error: %r"%e)
Esempio n. 4
0
    def html(self):
        if 'r' not in request.identity.access(self):
            return drink.unauthorized()

        drink.response.content_type = "text/html; charset=utf-8"
        if self.content:
            return u'''
Esempio n. 5
0
    def html(self):
        if 'r' not in request.identity.access(self):
            return drink.unauthorized()

        drink.response.content_type = "text/html; charset=utf-8"
        r = []
        if self.content:
            mime = self.mimetype
            try:
                sz = os.stat(self.content.filename).st_size
            except Exception, e:
                log.error(repr(e))
                sz = 0
            # TODO: handle factory here
            if not sz:
                r.append(u'<h1>No content :(</h1>')
            else:
                r.append(u'<h1 title="%s">%s<a href="raw"><img src="/static/actions/download.png" title="Click here to download (%sB)"/></a></h1>'%(self.description, self.content_name, drink.bytes2human(sz)))
                r.append(u'<div class="contents">')
                if mime.startswith('image/'):
                    r.append(u'<img src="raw" style="width: 80%; margin-left: 10%; margin-right: 10%;"/>')
                elif mime in ('application/xml', ) or mime.startswith('text/'):
                    f = self.content.open('r')
                    r.append(u'<pre>')
                    r.append(unicode(f.read(), 'utf-8'))
                    r.append(u'</pre>')
                r.append(u"</div>")
Esempio n. 6
0
    def serialize(self, recurse=False):
        if 'o' not in request.identity.access(self):
            return drink.unauthorized("You must be the owner to do that")

        d = Page.serialize(self, recurse=False)
        d['drink__filename'].self.content.filename
        return d
Esempio n. 7
0
    def upload(self):
        if 'w' not in request.identity.access(self):
            return drink.unauthorized()

        try:
            filename = request.GET.get('qqfile', '').decode('utf-8')
        except UnicodeError:
            filename = request.GET['qqfile'].decode('latin1')
        if not filename:
            return {'error': True, 'code': 400, 'message': 'Incorrect parameters. Action aborted.'}

        factory = self.upload_map.get(filename.rsplit('.')[-1], 'WebFile')

        with self._lock():

            o = self._add(filename, factory,
                request.identity.user.default_read_groups,
                request.identity.user.default_write_groups)
            o.mimetype = get_type(filename)

            fake_post_obj = _Mock()

            fake_post_obj.file = request.body
            fake_post_obj.filename = filename

            o._upload(fake_post_obj)

            data = o.struct()
            data['success'] = True

        return data
Esempio n. 8
0
    def _edit(self):
        """ Implementation of public :meth:`~drink.Page.edit` method,
        only looks at http environment for now (no useable parameter).

        .. note::  Use :meth:`.set_field` to set some editable field value.

        Use :

        .. rubric:: HTTP parameters (other that the properties' names)

        :_dk_fields: Field names to edit, separated by a slash ``/``
        :embedded: Just transmits this parameter to next page
        :_recurse: Special mode applying permissions (only) in a recursive way

        """

        if 'w' not in request.identity.access(self):
            return drink.unauthorized()

        items = self.editable_fields.items()
        if request.identity.id == self.owner.id or request.identity.admin:
            items += self.owner_fields.items()

        if request.identity.admin:
            items += self.admin_fields.items()

        forms = request.forms
        embedded = bool(request.params.get('embedded', ''))
        recursive = bool(request.params.get('_recurse', ''))

        if forms:
            if '_dk_fields' in forms:
                editable = forms.get('_dk_fields').split('/')
            else:
                editable = forms.keys()

            files = request.files.keys()

            for attr, caster in items:
                if attr in files:
                    caster.set(self, attr, request.files.get(attr))
                elif attr in editable:
                    v = forms.get(attr)
                    caster.set(self, attr, v.decode('utf-8') if v else u'')

            self._update_lookup_engine()

            if recursive:
                # apply permissions recursively
                childs = list(self.values())
                for child in childs:
                    try:
                        child.read_groups = self.read_groups
                        child.write_groups = self.write_groups
                    except Exception, e:
                        log.warning('error applying permissionson %r : %r', child, e)
                    else:
                        childs.extend(child.values())
            return {'redirect': "%s?embedded=%s"%(self.quoted_path, '1' if embedded else '' )}
Esempio n. 9
0
 def raw(self):
     if 'r' not in request.identity.access(self):
         return drink.unauthorized()
     try:
         if self.content:
             root, fname = os.path.split(self.content.filename)
             return drink.static_file(fname, root, mimetype=self.mimetype, download=self.content_name)
     except Exception, e:
         log.error('Error while handling %r', self.path)
Esempio n. 10
0
    def move(self):
        if 'w' not in request.identity.access(self):
            return drink.unauthorized()

        if request.is_ajax:
            self.forced_order = unquote(request.params.get('set')).decode('utf-8').split('/')
        else:
            html = '<input type="text" class="completable" complete_type="objpath" value="/pages/"></input>'
            return self.view(html=html)
Esempio n. 11
0
def default_view(self, page='main.html', obj=None, css=None, js=None, html=None, embed=None, classes=None, no_auth=None, **kw):
    """ Renders the :class:`~drink.Page` as HTML using a template

    :arg self: the object to render, should contain the following properties:

        :css: either a list of css http paths (str) or css block
        :js: either a list of javascript files (str) or javascript code
        :html: any html <body> content
        :classes: in case the `classes` parameter is not given

        .. note:: Additional properties may be required, depending on the template used (default is "main.html")

    :type self: any `object`

    :arg page: (defaults to "main.html") template to use for rendering
    :type page: a :func:`bottle.template` compatible template

    :arg obj: (optional) overrides `self` for `obj` template parameter. The access checking & so will use `self`.

    The following `self` attributes may be overriden:

    :arg css: The list of css files to use (http relative path) or the content itself
    :type css: `list` of `str` or `str` with newline(s)
    :arg js: The list of js files to use (http relative path) or the content itself
    :type js: `list` of `str` or `str` with newline(s)
    :arg html: HTML content of the `<body>` element
    :type html: `unicode`
    :arg classes: A mapping of ``{'Object name': Drink_Page_class}`` usable objects
    :type classes: `dict` of `str` : :class:`drink.Page`

    """
    if not no_auth and 'r' not in request.identity.access(self):
        return drink.unauthorized()

    drink.response.content_type = "text/html; charset=utf-8"

    if request.is_ajax:
        return {'html': html or self.html,
            'js': js or self.js,
            'css': css or self.css,
            }

    return bottle.template(page,
            template_adapter=bottle.Jinja2Template,
            obj=obj or self,
            css=css or self.css,
            js=js or self.js,
            html=html or self.html,
            embed=bool(request.params.get('embedded', False)) if embed is None else embed,
            classes=self.classes if classes is None else classes,
            isattr=lambda x, name: hasattr(x, name),
            isstring=lambda x: isinstance(x, basestring),
            req=request,
            authenticated=request.identity,
            **kw
        )
Esempio n. 12
0
    def set_field(self, name, val):
        """ Set the field *name* to value *val*

        :arg name: name of the :data:`~drink.Page.editable_fields` to set
        :type name: str

        :arg val: value of the field
        :type val: depends on the :mod:`~drink.types`
        """
        if name in self.editable_fields:
            if 'w' in request.identity.access(self):
                self.editable_fields[name].set(self, name, val)
            else:
                return drink.unauthorized("You can't edit %r, ask for more permissions."%name)
        elif name in self.owner_fields:
            if 'o' in request.identity.access(self):
                self.owner_fields[name].set(self, name, val)
            else:
                return drink.unauthorized("You can't edit %r, ask for more permissions."%name)
        else:
            return drink.unauthorized("%r is not editable."%name)
Esempio n. 13
0
    def reset_items(self):
        if 'o' not in request.identity.access(self):
            return drink.unauthorized("You must be the owner to do that")

        orig_order = []
        k = set(Page.keys(self))

        for item in self.forced_order:
            if item not in orig_order and item in k:
                orig_order.append(item)
        unlisted = k.difference(orig_order)
        orig_order.extend(unlisted)
        self.forced_order = orig_order
        return {'success': True}
Esempio n. 14
0
    def rm(self):
        # TODO: ajaxify
        name = drink.omni(request.GET.get('name'))
        if not ('a' in request.identity.access(self) and 'w' in request.identity.access(self[name])):
            return drink.unauthorized("Not authorized")
        try:
            parent_path = self.quoted_path
        except AttributeError: # XXX: unclean
            parent_path = '.'

        with self._lock():
            old_obj = self[name]
            del self[name]
            old_obj._update_lookup_engine(remove=True)
            drink.transaction.commit()

        return drink.rdr(parent_path)
Esempio n. 15
0
    def match(self, pattern=None):
        if 'r' not in request.identity.access(self):
            return drink.unauthorized()

        return self._match(pattern or request.params.get('pattern').decode('utf-8') )