コード例 #1
0
    def perform_move(self):
        parent_canonical_url = self._read_parent_canonical_url()
        from_tree = parse_url(self.from_path, self.schema.root)

        aggregate_query, from_spec, is_aggregate = from_tree.aggregation(None)

        aggregate_query.extend([
            {"$project": {
                "_parent_type": self.parent_spec_name,
                "_parent_id": self.parent_id,
                "_parent_field_name": self.parent_field_name,
                "_parent_canonical_url": parent_canonical_url or "/",
                "_canonical_url": {
                    "$concat": [parent_canonical_url, "/", self.parent_field_name, "/ID", {"$toString": "$_id"}],
                }
            }},
            {"$merge": {
                "into": "resource_%s" % from_tree.spec.name,
                "on": "_id",
                "whenMatched": "merge",
                "whenNotMatched": "discard",
            }},
        ])

        from_tree.root_collection().aggregate(aggregate_query)
コード例 #2
0
ファイル: api.py プロジェクト: gomyar/metaphor
    def get_spec_for(self, path, user=None):
        path = path.strip().strip('/')
        tree = parse_url(path, self.schema.root)

        aggregate_query, spec, is_aggregate = tree.aggregation(None, user)
        return (
            spec,
            is_aggregate,
            type(tree) in (CollectionResourceRef, RootResourceRef),
            type(tree) in (LinkCollectionResourceRef, ),
        )
コード例 #3
0
    def affected_ids(self):
        from_tree = parse_url(self.from_path, self.schema.root)
        from_agg, from_spec, _ = self.from_path_agg()

        affected_ids = set()
        for calc_spec_name, calc_field_name, aggregation in self.affected_aggs():
            affected_aggregation = from_agg + aggregation
            affected_aggregation.append({"$project": {"_id": True}})
            cursor = from_tree.root_collection().aggregate(
                affected_aggregation)
            found = set((calc_spec_name, calc_field_name, r['_id']) for r in cursor)
            affected_ids.update(found)
        return affected_ids
コード例 #4
0
    def affected_aggs_to_path(self):
        to_tree = parse_url(self.to_path, self.schema.root)
        to_agg, to_spec, _ = to_tree.aggregation(None)

        aggs = []
        for (calc_spec_name, calc_field_name), calc_tree in self.schema.calc_trees.items():
            if to_tree.get_resource_dependencies().intersection(calc_tree.get_resource_dependencies()):
                aggregations = ReverseAggregator(self.schema).get_for_resource(calc_tree, to_spec.name, None, calc_spec_name, calc_field_name)

                for aggregation in aggregations:
                    if aggregation:
                        aggs.append((calc_spec_name, calc_field_name, aggregation))
        return aggs
コード例 #5
0
ファイル: move_link.py プロジェクト: gomyar/metaphor
    def execute(self):
        from_tree = parse_url(self.from_path, self.schema.root)

        aggregate_query, spec, is_aggregate = from_tree.aggregation(None)
        update_ids = [r['_id'] for r in from_tree.root_collection().aggregate(aggregate_query)]

        # add to new linkcollection

        # remove from original linkcollection

        # TODO: perform updates for create / delete


        return None
コード例 #6
0
    def execute(self):
        # collect ids
        affected_ids = self.affected_ids()

        # perform update
        self.perform_move()

        affected_ids_to_path = self.affected_ids_to_path()
        affected_ids.update(affected_ids_to_path)

        # perform update
        from_tree = parse_url(self.from_path, self.schema.root)
        spec = from_tree.spec
        for calc_spec_name, calc_field_name, affected_id in affected_ids:
            affected_id = self.schema.encodeid(affected_id)
            self.updater.update_calc(calc_spec_name, calc_field_name, affected_id)
            self.updater._recalc_for_field_update(spec, calc_spec_name, calc_field_name, affected_id)

        return None
コード例 #7
0
ファイル: api.py プロジェクト: gomyar/metaphor
    def get(self, path, args=None, user=None):
        args = args or {}
        expand = args.get('expand')
        page = int(args.get('page', 0))
        page_size = int(args.get('page_size', 10))

        expand_dict = create_expand_dict(expand)

        path = path.strip().strip('/')
        if not path:
            return self._get_root()

        try:
            tree = parse_url(path, self.schema.root)
        except SyntaxError as te:
            return None

        aggregate_query, spec, is_aggregate = tree.aggregation(None)

        if path.split('/')[0] == 'ego':

            aggregate_query = [{
                "$match": {
                    "username": user.username
                }
            }] + aggregate_query

        if is_aggregate:

            page_agg = self.create_pagination_aggregations(page, page_size)

            if expand:
                if user and self._check_expand_ego_grants(
                        path, expand_dict, user.read_grants):
                    expand_agg = self.create_field_expansion_aggregations(
                        spec, expand_dict)
                else:
                    expand_agg = self.create_field_expansion_aggregations(
                        spec, expand_dict, user)
                page_agg['$facet']["results"].extend(expand_agg)

            aggregate_query.append(page_agg)

            # run mongo query from from root_resource collection
            cursor = tree.root_collection().aggregate(aggregate_query)

            page_results = next(cursor)

            results = list(page_results['results'])
            count = page_results['count'][0]['total'] if page_results[
                'count'] else 0

            if user and count:
                # TODO: also need to check read access to target if link
                # checking for /ego paths first, then all other paths
                self._check_grants(path, results[0]['_canonical_url'],
                                   user.read_grants)

            return {
                "results": [
                    self.encode_resource(spec, row, expand_dict)
                    for row in results
                ],
                "count":
                count,
                "next":
                self._next_link(path, args, count, page, page_size),
                "previous":
                self._previous_link(path, args, count, page, page_size),
                '_meta': {
                    'spec': {
                        'name': spec.name,
                    },
                    'is_collection':
                    True,
                    'can_create':
                    type(tree)
                    in (CollectionResourceRef, OrderedCollectionResourceRef,
                        RootResourceRef),
                    'can_link':
                    type(tree) in (LinkCollectionResourceRef, ),
                }
            }

        else:
            if expand:
                if user and self._check_expand_ego_grants(
                        path, expand_dict, user.read_grants):
                    expand_agg = self.create_field_expansion_aggregations(
                        spec, expand_dict)
                else:
                    expand_agg = self.create_field_expansion_aggregations(
                        spec, expand_dict, user)
                aggregate_query.extend(expand_agg)

            # run mongo query from from root_resource collection
            cursor = tree.root_collection().aggregate(aggregate_query)
            result = next(cursor, None)

            if user and result:
                # TODO: also need to check read access to target if link
                # checking for /ego paths first, then all other paths
                self._check_grants(path, result['_canonical_url'],
                                   user.read_grants)

            if result:
                return self.encode_resource(spec, result, expand_dict)
            else:
                return None
コード例 #8
0
ファイル: api.py プロジェクト: gomyar/metaphor
    def put(self, path, data, user=None):
        path = path.strip().strip('/')
        from_path = data['_from'].strip('/') if data.get('_from') else None
        at_index = data.get('_at')

        if '/' in path:
            parent_path, field_name = path.rsplit('/', 1)
            try:
                tree = parse_canonical_url(parent_path, self.schema.root)
            except SyntaxError as te:
                raise HTTPError('', 404, "Not Found", None, None)

            aggregate_query, spec, is_aggregate = tree.aggregation(None)

            field_spec = spec.fields[field_name]

            if path.split('/')[0] == 'ego':
                aggregate_query = [{
                    "$match": {
                        "username": user.username
                    }
                }] + aggregate_query

            # if we're using a simplified parser we can probably just pull the id off the path
            cursor = tree.root_collection().aggregate(aggregate_query)
            parent_resource = next(cursor)

            # check permissions
            if user:
                self._check_grants(
                    path,
                    os.path.join(parent_resource['_canonical_url'],
                                 field_name), user.put_grants)
                self._check_grants(from_path, from_path, user.read_grants)
                self._check_grants(from_path, from_path, user.delete_grants)

            # do put update
            try:
                parse_url(from_path, self.schema.root)
            except SyntaxError as te:
                raise HTTPError('', 400, from_path, None, None)

            if field_spec.field_type == 'collection':
                return self.updater.move_resource(parent_resource['_id'],
                                                  spec.name, field_name, path,
                                                  from_path)
            else:
                raise HTTPError('', 400, from_path, None, None)

        else:
            if path not in self.schema.root.fields:
                raise HTTPError('', 404, "Not Found", None, None)

            root_field_spec = self.schema.root.fields[path]
            root_spec = self.schema.specs[root_field_spec.target_spec_name]

            # check permissions
            if user:
                self._check_grants(path, path, user.put_grants)
                self._check_grants(from_path, from_path, user.read_grants)
                self._check_grants(from_path, from_path, user.delete_grants)

            if root_field_spec.target_spec_name == 'user':
                data['password'] = generate_password_hash(data['password'])

            # do put update
            try:
                if from_path:
                    parse_url(from_path, self.schema.root)
            except SyntaxError as te:
                raise HTTPError('', 400, from_path, None, None)

            return self.updater.move_resource(None, 'root', path, path,
                                              from_path)
コード例 #9
0
 def to_path_agg(self):
     to_tree = parse_url(self.to_path, self.schema.root)
     aggregate_query, to_spec, is_aggregate = to_tree.aggregation(None)
     return aggregate_query, to_spec, is_aggregate
コード例 #10
0
 def from_path_agg(self):
     from_tree = parse_url(self.from_path, self.schema.root)
     aggregate_query, from_spec, is_aggregate = from_tree.aggregation(None)
     return aggregate_query, from_spec, is_aggregate