Exemplo n.º 1
0
    def get_default_where_clauses(self,
                                  container: IContainer) -> typing.List[str]:
        users = []
        roles = []
        principal = get_authenticated_user()
        if principal is None:
            # assume anonymous then
            principal = AnonymousUser()
        policy = get_security_policy(principal)

        users.append(principal.id)
        users.extend(principal.groups)
        roles_dict = policy.global_principal_roles(principal.id,
                                                   principal.groups)
        roles.extend([key for key, value in roles_dict.items() if value])

        clauses = [
            "json->'access_users' ?| array['{}']".format("','".join(
                [sqlq(u) for u in users])),
            "json->'access_roles' ?| array['{}']".format("','".join(
                [sqlq(r) for r in roles])),
        ]
        sql_wheres = ["({})".format(" OR ".join(clauses))]
        sql_wheres.append(
            f"""json->>'container_id' = '{sqlq(container.id)}'""")
        sql_wheres.append("""type != 'Container'""")
        sql_wheres.append(f"""parent_id != '{sqlq(TRASHED_ID)}'""")
        return sql_wheres
Exemplo n.º 2
0
    def get_default_where_clauses(
            self,
            context: IBaseObject,
            unrestricted: bool = False) -> typing.List[str]:
        clauses = []
        sql_wheres = []
        if unrestricted is False:
            users = []
            principal = get_authenticated_user()
            if principal is None:
                # assume anonymous then
                principal = AnonymousUser()

            users.append(principal.id)
            users.extend(principal.groups)
            roles = get_roles_principal(context)

            clauses.extend([
                "json->'access_users' ?| array['{}']".format("','".join(
                    [sqlq(u) for u in users])),
                "json->'access_roles' ?| array['{}']".format("','".join(
                    [sqlq(r) for r in roles])),
            ])
            sql_wheres.append("({})".format(" OR ".join(clauses)))
        container = find_container(context)
        if container is None:
            raise ContainerNotFound()

        sql_wheres.append(
            f"""json->>'container_id' = '{sqlq(container.id)}'""")
        sql_wheres.append("""type != 'Container'""")
        sql_wheres.append(f"""parent_id != '{sqlq(TRASHED_ID)}'""")
        return sql_wheres
Exemplo n.º 3
0
def get_security_policy(user: Optional[IPrincipal] = None) -> ISecurityPolicy:
    if user is None:
        user = get_authenticated_user()
        if user is None:
            from guillotina.auth.users import AnonymousUser
            user = AnonymousUser()
    security_policies = task_vars.security_policies.get()
    if security_policies is None:
        security_policies = {}
        task_vars.security_policies.set(security_policies)
    if user.id not in security_policies:
        security_policies[user.id] = get_adapter(user, ISecurityPolicy)
    return security_policies[user.id]
Exemplo n.º 4
0
def get_roles_principal(obj):
    """ Return the roles that has access to the content that are global roles"""
    if obj is None:
        return []

    authenticated = get_authenticated_user()
    if authenticated is None:
        from guillotina.auth.users import AnonymousUser

        authenticated = AnonymousUser()
    policy = get_security_policy(authenticated)
    roles = policy.cached_principal_roles(obj, authenticated.id,
                                          authenticated.groups, "o")
    return [role for role, value in roles.items() if value]
Exemplo n.º 5
0
    async def real_resolve(self, request: IRequest) -> Optional[MatchInfo]:
        """Main function to resolve a request."""
        if request.method not in app_settings['http_methods']:
            raise HTTPMethodNotAllowed(
                method=request.method,
                allowed_methods=[
                    k for k in app_settings['http_methods'].keys()
                ])
        method = app_settings['http_methods'][request.method]

        try:
            resource, tail = await self.traverse(request)
        except ConflictError:
            # can also happen from connection errors so we bubble this...
            raise
        except Exception as _exc:
            logger.error('Unhandled exception occurred', exc_info=True)
            request.resource = request.tail = None
            request.exc = _exc
            data = {
                'success': False,
                'exception_message': str(_exc),
                'exception_type': getattr(type(_exc), '__name__',
                                          str(type(_exc))),  # noqa
            }
            if app_settings.get('debug'):
                data['traceback'] = traceback.format_exc()
            raise HTTPBadRequest(content={'reason': data})

        request.record('traversed')

        await notify(ObjectLoadedEvent(resource))
        request.resource = resource
        request.tail = tail

        if request.resource is None:
            await notify(TraversalResourceMissEvent(request, tail))
            raise HTTPNotFound(content={"reason": 'Resource not found'})

        if tail and len(tail) > 0:
            # convert match lookups
            view_name = routes.path_to_view_name(tail)
        elif not tail:
            view_name = ''

        request.record('beforeauthentication')
        authenticated = await authenticate_request(request)
        # Add anonymous participation
        if authenticated is None:
            authenticated = AnonymousUser()
            set_authenticated_user(authenticated)
        request.record('authentication')

        policy = get_security_policy(authenticated)

        for language in get_acceptable_languages(request):
            translator = query_adapter((resource, request),
                                       ILanguage,
                                       name=language)
            if translator is not None:
                resource = translator.translate()
                break

        # container registry lookup
        try:
            view = query_multi_adapter((resource, request),
                                       method,
                                       name=view_name)
        except AttributeError:
            view = None

        if view is None and method == IOPTIONS:
            view = DefaultOPTIONS(resource, request)

        # Check security on context to AccessContent unless
        # is view allows explicit or its OPTIONS
        permission = get_utility(IPermission, name='guillotina.AccessContent')
        if not policy.check_permission(permission.id, resource):
            # Check if its a CORS call:
            if IOPTIONS != method:
                # Check if the view has permissions explicit
                if view is None or not view.__allow_access__:
                    logger.info(
                        "No access content {content} with {auth}".format(
                            content=resource, auth=authenticated.id),
                        request=request)
                    raise HTTPUnauthorized(
                        content={
                            "reason":
                            "You are not authorized to access content",
                            "content": str(resource),
                            "auth": authenticated.id
                        })

        if not view and len(tail) > 0:
            # we should have a view in this case because we are matching routes
            await notify(TraversalViewMissEvent(request, tail))
            return None

        request.found_view = view
        request.view_name = view_name
        request.record('viewfound')

        ViewClass = view.__class__
        view_permission = get_view_permission(ViewClass)
        if view_permission is None:
            # use default view permission
            view_permission = app_settings['default_permission']
        if not policy.check_permission(view_permission, view):
            if IOPTIONS != method:
                raise HTTPUnauthorized(
                    content={
                        "reason": "You are not authorized to view",
                        "content": str(resource),
                        "auth": authenticated.id
                    })

        try:
            view.__route__.matches(request, tail or [])
        except (KeyError, IndexError):
            await notify(TraversalRouteMissEvent(request, tail))
            return None
        except AttributeError:
            pass

        if hasattr(view, 'prepare'):
            view = (await view.prepare()) or view

        request.record('authorization')

        return MatchInfo(resource, request, view)
Exemplo n.º 6
0
 def __init__(self, request):
     self.principal = AnonymousUser(request)
     self.principal._roles['guillotina.Anonymous'] = Allow
     self.interaction = None