Exemple #1
0
    def deleteListItem(repo_id, code, item_id):
        try:
            repo_id = int(repo_id)
        except TypeError:
            raise DbError(message="Invalid repo_id provided",
                          context="List.deleteListItem",
                          dberror="")
        try:
            result = db.run(
                "MATCH (r:Repository)--(l:List {code: {code}})-[x]-(i:ListItem) WHERE ID(r) = {repo_id} AND ID(i) = {item_id} DELETE i,x",
                {
                    "repo_id": int(repo_id),
                    "item_id": int(item_id),
                    "code": code
                })

            if result is not None:
                return True
            else:
                raise FindError(message="Could not find list item",
                                context="List.deleteListItem",
                                dberror="")
        except Exception as e:
            raise DbError(message="Could not delete list item",
                          context="List.deleteListItem",
                          dberror=e.message)
    def getRecordCountForDataType(repo_id, type):
        repo_id = int(repo_id)

        try:
            type_id = int(type)
        except Exception:
            type_id = str(type)

        # TODO: check that repository is owned by current user
        try:
            if isinstance(type_id, int):
                count_obj = db.run(
                    "MATCH (r:Repository)--(t:SchemaType)--(d:Data) WHERE ID(t) = {type_id} AND ID(r) = {repo_id} RETURN COUNT(d) as data_count",
                    {
                        "type_id": type_id,
                        "repo_id": repo_id
                    }).peek()
            else:
                count_obj = db.run(
                    "MATCH (r:Repository)--(t:SchemaType)--(d:Data) WHERE t.code = {type_id} AND ID(r) = {repo_id} RETURN COUNT(d) as data_count",
                    {
                        "type_id": type_id,
                        "repo_id": repo_id
                    }).peek()

            return count_obj['data_count']
        except Exception as e:
            raise DbError(message="Could not get data count for Data Type",
                          context="Schema.getRecordCountForDataType",
                          dberror=e.message)
    def deleteType(repo_id, type_id):
        # TODO validate params

        # TODO: check that repository is owned by current user

        try:
            result = db.run(
                "MATCH (t:SchemaType)-[x]-(r:Repository) WHERE ID(r) = {repo_id} AND ID(t) = {type_id} OPTIONAL MATCH (f:SchemaField)-[y]-(t) OPTIONAL MATCH (d:Data)-[z]-(t) DELETE x,y,t,f,z,d",
                {
                    "type_id": int(type_id),
                    "repo_id": int(repo_id)
                })
            print "type=" + type_id
            print "repo=" + repo_id
            if result is not None:
                SchemaManager.resetTypeInfoCache()
                return {"type_id": type_id}
            else:
                raise FindError(message="Could not find type",
                                context="Schema.deleteType",
                                dberror="")
        except Exception as e:
            raise DbError(message="Could not delete type",
                          context="Schema.deleteType",
                          dberror=e.message)
    def getTypes(repo_id):
        # TODO validate params

        # TODO: check that repository is owned by current user
        try:
            result = db.run(
                "MATCH (t:SchemaType)--(r:Repository) WHERE ID(r) = {repo_id}  RETURN ID(t) as id, t.name as name, t.code as code, t.description as description",
                {"repo_id": int(repo_id)})

            if result:
                typelist = []
                for r in result:
                    t = {
                        'id': str(r['id']),
                        'name': r['name'],
                        'code': r['code'],
                        'description': r['description']
                    }

                    # get fields
                    i = SchemaManager.getInfoForType(repo_id, r['id'])
                    t["fields"] = i["fields"]
                    t["data_count"] = i["data_count"]
                    typelist.append(t)
                return typelist
        except Exception as e:
            raise DbError(message="Could not get types",
                          context="Schema.getTypes",
                          dberror=e.message)
    def checkFieldForData(repo_id, type_id, field_code):
        try:
            type_id = int(type)
        except Exception:
            type_id = str(type)

        try:
            if isinstance(type_id, int):
                result = db.run(
                    "MATCH (r:Repository)--(s:SchemaType)--(d:Data) WHERE ID(r) = {repo_id} AND ID(s) = {type_id} AND d."
                    + field_code + " <> '' return count(d) as data_count", {
                        "repo_id": repo_id,
                        "type_id": type_id
                    }).peek()
            else:
                result = db.run(
                    "MATCH (r:Repository)--(s:SchemaType)--(d:Data) WHERE ID(r) = {repo_id} AND s.code = {type_id} AND d."
                    + field_code + " <> '' return count(d) as data_count", {
                        "repo_id": repo_id,
                        "type_id": type_id
                    }).peek()
            if result is not None:
                data_count = result['data_count']
                ret = {"data": False, "total": data_count}
                if data_count > 0:
                    ret['data'] = True
                return ret
        except Exception as e:
            raise DbError(message="Could not get data count: " + e.message,
                          context="Schema.checkFieldForData",
                          dberror=e.message)
Exemple #6
0
    def add(repo_id, type_code, data, import_uuid=None, fields_created=None):
        # TODO: does user have access to this repo?
        data_proc, type_info = DataManager._validateData(
            repo_id, type_code, data, fields_created)
        try:
            q = "MATCH (t:SchemaType) WHERE ID(t) = {type_id} CREATE (n:Data " + makeDataMapForCypher(
                data_proc) + ")-[:IS]->(t) RETURN ID(n) AS id"

            data_proc["type_id"] = type_info[
                "type_id"]  # add type_id to data before insert
            res = db.run(q, data_proc).peek()
            data_id = res["id"]

            if import_uuid is not None:
                db.run(
                    "MATCH (e:ImportEvent { uuid: {import_uuid}}), (n:Data) WHERE ID(n) = {data_id} CREATE (e)<-[x:IMPORTED_IN]-(n) RETURN ID(x) AS id",
                    {
                        "import_uuid": import_uuid,
                        "data_id": data_id
                    })

            #DataManager.logChange("I", data_proc)
            return data_id
        except Exception as e:
            raise DbError(message="Could not create data (" +
                          e.__class__.__name__ + ") " + e.message,
                          context="DataManager.add",
                          dberror=e.message)
    def deleteField(repo_id, typecode, field_id):
        # TODO validate params

        # TODO: check that repository is owned by current user
        SchemaManager.resetTypeInfoCache()

        try:
            result = db.run(
                "MATCH (r:Repository)--(t:SchemaType {code: {typecode}})-[x]-(f:SchemaField) WHERE ID(r) = {repo_id} AND ID(f) = {field_id} DELETE f,x",
                {
                    "repo_id": int(repo_id),
                    "field_id": int(field_id),
                    "typecode": typecode
                })

            if result is not None:
                return True
            else:
                raise FindError(message="Could not find field",
                                context="Schema.deleteField",
                                dberror="")
        except Exception as e:
            raise DbError(message="Could not delete field",
                          context="Schema.deleteField",
                          dberror=e.message)
Exemple #8
0
    def deletePerson(person_id):
        try:
            result = db.run(
                "MATCH (n:Person) WHERE ID(n)={person_id} OPTIONAL MATCH (n)-[r]-() DELETE r,n",
                {"person_id": person_id})
        except Exception as e:
            raise DbError(message="Could not delete person",
                          context="People.deletePerson",
                          dberror=e.message)

            # Check that we deleted something
        summary = result.consume()
        if summary.counters.nodes_deleted >= 1:
            return True

        raise FindError(message="Could not find person",
                        context="People.deletePerson")
Exemple #9
0
 def addRelationship(start_node, end_node, type_id="RELATED", data=None):
     # TODO: does user have access to these nodes?
     try:
         type_id = re.sub(r'[^A-Za-z0-9_]+', '_', type_id)
         # NOTE: type_id is substituted directly into the string as the Bolt Neo4j driver doesn't allow placeholders for relationship types (yet)
         res = db.run(
             "MATCH (d1:Data), (d2:Data) WHERE ID(d1) = {start_node} AND ID(d2) = {end_node} CREATE(d1)-[r:"
             + type_id + "]->(d2) RETURN ID(r) AS id", {
                 "start_node": start_node,
                 "end_node": end_node,
                 "type_id": type_id
             }).peek()
         return res["id"]
     except Exception as e:
         raise DbError(message="Could not create relationship",
                       context="DataManager.addRelationship",
                       dberror=e.message)
Exemple #10
0
    def update(node_id, data, import_uuid=None):
        # TODO: does user have access to this repo?
        try:
            id = int(node_id)
        except:
            id = node_id

        try:
            if isinstance(id, (int)):
                res = db.run(
                    "MATCH (r:Repository)--(t:SchemaType)--(d:Data) WHERE ID(d) = {node_id} RETURN ID(r) as repo_id, ID(t) as type_id",
                    {
                        "node_id": id
                    }).peek()
            else:
                res = db.run(
                    "MATCH (r:Repository)--(t:SchemaType)--(d:Data) WHERE d.uuid = {uuid} RETURN ID(r) as repo_id, ID(t) as type_id",
                    {
                        "uuid": id
                    }).peek()
            if res is None:
                return None

            data_proc, type_info = DataManager._validateData(
                int(res['repo_id']), int(res['type_id']), data)

            if isinstance(id, (int)):
                data_proc["node_id"] = id
                db.run(
                    "MATCH (d:Data) WHERE ID(d) = {node_id} SET " +
                    makeDataMapForCypher(data=data_proc, mode="U",
                                         prefix="d."), data_proc)
            else:
                data_proc["uuid"] = id
                db.run(
                    "MATCH (d:Data) WHERE d.uuid = {uuid} SET " +
                    makeDataMapForCypher(data=data_proc, mode="U",
                                         prefix="d."), data_proc)

            #DataManager.logChange("U", data_proc)
            return True
        except Exception as e:
            raise DbError(message="Could not update data",
                          context="DataManager.update",
                          dberror=e.message)
Exemple #11
0
    def deleteList(repo_id, list_id):
        try:
            result = db.run(
                "MATCH (l:List)-[x]-(r:Repository) WHERE ID(r) = {repo_id} AND ID(l) = {list_id} OPTIONAL MATCH (i:ListItem)-[y]-(l) DELETE x,y,l,i",
                {
                    "list_id": int(list_id),
                    "repo_id": int(repo_id)
                })

            if result is not None:
                return {"list_id": list_id}
            else:
                raise FindError(message="Could not find list",
                                context="Schema.deleteList",
                                dberror="")
        except Exception as e:
            raise DbError(message="Could not delete list",
                          context="Schema.deleteList",
                          dberror=e.message)
Exemple #12
0
    def deleteRelationship(start_node=None,
                           end_node=None,
                           type_id=None,
                           rel_id=None):
        # TODO: does user have access to relationship?
        try:
            if type_id is not None:
                type_str = "r:" + re.sub(r'[^A-Za-z0-9_]+', '_', type_id)
            else:
                type_str = "r"

            # NOTE: type_id is substituted directly into the string as the Bolt Neo4j driver doesn't allow placeholders for relationship types (yet)

            if end_node is None:
                if rel_id is None:
                    rel_id = start_node  # if rel_id is not set assume first positional parameter (start_node) is the rel_id
                if rel_id is None:
                    return None

                # delete by rel_id
                db.run(
                    "MATCH (d1:Data)-[" + type_str +
                    "]-(d2:Data) WHERE ID(r) = {rel_id} DELETE r",
                    {"rel_id": rel_id})
            elif start_node is not None and end_node is not None:
                # delete by endpoints
                db.run(
                    "MATCH (d1:Data)-[" + type_str +
                    "]-(d2:Data) WHERE ID(d1) = {start_node} AND ID(d2) = {end_node} DELETE r",
                    {
                        "start_node": start_node,
                        "end_node": end_node
                    })
            else:
                raise ParameterError(
                    message="No relationship id or node id pair is set",
                    context="DataManager.deleteRelationship")
            return True
        except Exception as e:
            raise DbError(message="Could not delete relationship",
                          context="DataManager.deleteRelationship",
                          dberror=e.message)
Exemple #13
0
    def getCountForType(repo_id, type_id):
        repo_id = int(repo_id)
        type_id = int(type_id)
        try:
            q_count = db.run(
                "MATCH (r:Repository)--(t:SchemaType)--(d:Data) WHERE ID(r)={repo_id} AND ID(t)={type_id} RETURN count(d) as data_count",
                {
                    "repo_id": repo_id,
                    "type_id": type_id
                }).peek()

            return {
                "repo_id": repo_id,
                "type_id": type_id,
                "data_count": q_count['data_count']
            }
        except exception as e:
            raise DbError(message="Could get type Count",
                          context="DataManager.getCountForType",
                          dberror=e.message)
Exemple #14
0
    def delete(node_id, import_uuid=None):
        # TODO: does user have access to this repo?
        try:
            id = int(node_id)
        except:
            id = node_id

        try:
            if isinstance(id, (int)):
                db.run("MATCH (d:Data) WHERE ID(d) = {node_id} DELETE d",
                       {"node_id": id})
            else:
                db.run("MATCH (d:Data) WHERE d.uuid = {uuid} DELETE d",
                       {"uuid": id})

            # TODO: return false is no node is deleted?
            return True
        except Exception as e:
            raise DbError(message="Could not delete data",
                          context="DataManager.delete",
                          dberror=e.message)
Exemple #15
0
    def deleteDataFromRepo(repo_id, type_codes=None):
        # TODO: does user have access to this repo?

        type_str = ""
        if type_codes is not None:
            if all(isinstance(c, (int)) for c in type_codes):
                type_str = " AND ID(t) IN [" + ",".join(type_codes) + "] "
            else:
                type_codes = map(
                    lambda x: '"' + re.sub(r'[^A-Za-z0-9_]+', '_', x) + '"',
                    type_codes)
                type_str = " AND t.code IN [" + ",".join(type_codes) + "] "
        try:
            db.run(
                "MATCH (r:Repository)--(t:SchemaType)--(d:Data) WHERE ID(r) = {repo_id} "
                + type_str + " DETACH DELETE d", {"repo_id": repo_id})
            return True
        except Exception as e:
            raise DbError(message="Could not delete data from repository",
                          context="DataManager.deleteDataFromRepo",
                          dberror=e.message)
    def getType(repo_id, schema_id):
        # TODO validate params

        # TODO: check that repository is owned by current user

        try:
            res = db.run(
                "MATCH (r:Repository)--(t:SchemaType) WHERE ID(r) = {repo_id} AND ID(t) = {schema_id}  RETURN ID(t) as id, t.name as name, t.code as code, t.description as description",
                {
                    "repo_id": int(repo_id),
                    "schema_id": int(schema_id)
                }).peek()
            if res:
                t = {
                    'id': str(res['id']),
                    'name': res['name'],
                    'code': res['code'],
                    'description': res['description']
                }

                count_res = db.run(
                    "MATCH (t:SchemaType)--(d:Data) WHERE ID(t) = {schema_id} RETURN count(d) as data_count",
                    {
                        "schema_id": int(schema_id)
                    }).peek()
                if count_res:
                    t['data_count'] = count_res['data_count']
                else:
                    t['data_count'] = 0

                # get fields
                i = SchemaManager.getInfoForType(repo_id, res['id'])
                t["fields"] = i["fields"]
                return t
        except Exception as e:
            raise DbError(message="Could not get types",
                          context="Schema.getType",
                          dberror=e.message)
Exemple #17
0
 def getListsForRepo(repo_id):
     repo_id = int(repo_id)
     ret = {'lists': []}
     try:
         lists_res = db.run(
             "MATCH (r:Repository)--(l:List) WHERE ID(r) = {repo_id} RETURN ID(l) as id, l.name as name, l.code as code, l.description as description, l.merge_allowed as merge_allowed",
             {"repo_id": repo_id})
         if lists_res:
             for i_list in lists_res:
                 list_ret = {
                     'id': i_list['id'],
                     'name': i_list['name'],
                     'code': i_list['code'],
                     'description': i_list['description'],
                     'merge_allowed': i_list['merge_allowed']
                 }
                 ret['lists'].append(list_ret)
             return ret
         else:
             return None
     except Exception as e:
         raise DbError(message="Could not get lists for repo",
                       context="List.getListsForRepo",
                       dberror=e.message)
    def addField(repo_id, typecode, name, code, fieldtype, description,
                 settings):
        # TODO validate params
        if typecode is None or len(typecode) == 0:
            raise ValidationError(message="Type code is required",
                                  context="Schema.addField")

        type_info = SchemaManager.getInfoForType(repo_id, typecode)
        SchemaManager.resetTypeInfoCache()

        if type_info is None:
            raise ValidationError(message="Type code is invalid",
                                  context="Schema.addField")
        typecode = type_info["code"]  # always use code

        if code is None or len(code) == 0:
            raise ValidationError(message="Field code is required",
                                  context="Schema.addField")

        if name is None or len(name) == 0:
            raise ValidationError(message="Field name is required",
                                  context="Schema.addField")

        # Check field type
        if fieldtype not in SchemaManager.getDataTypes():
            raise ValidationError(message="Invalid field type",
                                  context="Schema.addField")

        ret = {}
        ft = SchemaManager.getDataTypeInstance(fieldtype)
        if ft is None:
            raise ValidationError(message="Invalid field type",
                                  context="Schema.addField")

        sv = ft.validateSettings(settings)
        if sv is not True:
            raise SettingsValidationError(message="Invalid field type",
                                          errors={code: sv},
                                          context="Schema.addField")

        # TODO: check that repository is owned by current user

        result = db.run(
            "MATCH (f:SchemaField {code: {code}})--(t:SchemaType {code: {typecode}})--(r:Repository) WHERE ID(r) = {repo_id}  RETURN f.name as name, ID(f) as id",
            {
                "typecode": typecode,
                "code": code,
                "repo_id": int(repo_id)
            }).peek()
        if result is not None:
            ret['exists'] = True
            ret['field_id'] = result['id']
            ret['name'] = result['name']
            return ret
        else:
            flds = [
                "name: {name}", "code: {code}", "description: {description}",
                "type: {fieldtype}"
            ]
            params = {
                "repo_id": int(repo_id),
                "name": name,
                "code": code,
                "description": description,
                "typecode": typecode,
                "fieldtype": fieldtype
            }
            for s in settings:
                flds.append("settings_" + s + ": {settings_" + s + "}")
                params["settings_" + s] = settings[s]

            result = db.run(
                "MATCH (r:Repository)--(t:SchemaType {code: {typecode}}) WHERE ID(r) = {repo_id} CREATE (f:SchemaField { "
                + ", ".join(flds) +
                " })-[:PART_OF]->(t) RETURN ID(f) as id, f.name as name, f.code as code",
                params)

            r = result.peek()
            # TODO: check query result
            if r:
                ret['exists'] = False
                ret['field_id'] = r['id']
                ret['name'] = r['name']
                ret['code'] = r['code']
                return ret
            else:
                raise DbError(message="Could not add field",
                              context="Schema.addField",
                              dberror="")
Exemple #19
0
    def editListItem(repo_id,
                     code,
                     item_id,
                     display,
                     item_code,
                     description=None):
        try:
            repo_id = int(repo_id)
        except TypeError:
            raise DbError(message="Invalid repo_id provided",
                          context="List.editListItem",
                          dberror="")
        if code is None or len(code) == 0:
            raise ValidationError(message="List code is required",
                                  context="List.editListItem")

        if item_code is None or len(item_code) == 0:
            raise ValidationError(message="List item code is required",
                                  context="List.editListItem")

        if display is None or len(display) == 0:
            raise ValidationError(message="List Item display is required",
                                  context="List.editListItem")

        ret = {}
        result = db.run(
            "MATCH (i:ListItem {code: {item_code}})--(l:List {code: {code}})--(r:Repository) WHERE ID(r) = {repo_id} AND ID(i) <> {item_id}  RETURN ID(i) as id, i.display as display",
            {
                "item_code": item_code,
                "code": code,
                "repo_id": int(repo_id),
                "item_id": int(item_id)
            }).peek()
        if result is not None:
            ret['msg'] = "List Item already exists"
            ret['item_id'] = result['id']
            ret['display'] = result['display']
            return ret
        else:
            flds = [
                "i.display = {display}", "i.code = {item_code}",
                "i.description = {description}"
            ]
            params = {
                "code": code,
                "repo_id": int(repo_id),
                "display": display,
                "item_code": item_code,
                "description": description,
                "item_id": int(item_id)
            }
            result = db.run(
                "MATCH (r:Repository)--(l:List {code: {code}})--(i:ListItem) WHERE ID(r) = {repo_id} AND ID(i) = {item_id} SET "
                + ", ".join(flds) +
                " RETURN ID(i) as id, i.display as display", params)
            r = result.peek()

            # TODO: check query result

            if r:
                ret['item_id'] = r['id']
                ret['display'] = r['display']
                return ret
            else:
                raise DbError(message="Could not edit list item",
                              context="List.editListItem",
                              dberror="")
    def getInfoForType(repo_id, type):
        repo_id = int(repo_id)

        # TODO validate params

        try:
            type_id = int(type)
        except Exception:
            type_id = str(type)

        # TODO: check that repository is owned by current user
        try:
            if isinstance(type_id, int):
                tres = db.run(
                    "MATCH (r:Repository)--(t:SchemaType) WHERE ID(t) = {type_id} AND ID(r) = {repo_id} RETURN ID(t) as id, t.name as name, t.code as code, t.description as description",
                    {
                        "type_id": type_id,
                        "repo_id": repo_id
                    }).peek()

                if tres is None:
                    return None

                result = db.run(
                    "MATCH (f:SchemaField)--(t:SchemaType)--(r:Repository) WHERE ID(t) = {type_id} AND ID(r) = {repo_id} RETURN ID(f) as id, f.name as name, f.code as code, f.type as type, f.description as description, properties(f) as props",
                    {
                        "type_id": int(type_id),
                        "repo_id": repo_id
                    })
            else:
                tres = db.run(
                    "MATCH (r:Repository)--(t:SchemaType) WHERE t.code = {code} AND ID(r) = {repo_id} RETURN ID(t) as id, t.name as name, t.code as code, t.description as description",
                    {
                        "code": type_id,
                        "repo_id": repo_id
                    }).peek()
                if tres is None:
                    return None

                result = db.run(
                    "MATCH (f:SchemaField)--(t:SchemaType)--(r:Repository) WHERE t.code = {code} AND ID(r) = {repo_id}  RETURN ID(f) as id, f.name as name, f.code as code, f.type as type, f.description as description, properties(f) as props",
                    {
                        "code": type_id,
                        "repo_id": repo_id
                    })

            info = {
                "type_id": tres['id'],
                "name": tres['name'],
                "code": tres['code'],
                "description": tres['description']
            }

            fieldlist = []
            if result:
                for r in result:
                    ft = SchemaManager.getDataTypeInstance(r['type'])
                    if ft is None:
                        #raise ValidationError(message="Invalid field type", context="Schema.getFieldsForType")
                        continue

                    t = {
                        'id': str(r['id']),
                        'name': r['name'],
                        'code': r['code'],
                        'description': r['description'],
                        'type': r['type'],
                        'settings': {}
                    }

                    dc = SchemaManager.checkFieldForData(
                        repo_id, type_id, r['code'])
                    t['has_data'] = dc['data']

                    for s in ft.getSettingsList():
                        if "settings_" + s in r['props']:
                            t["settings_" + s] = r['props']["settings_" + s]
                            t["settings"][s] = r["props"]["settings_" + s]
                    fieldlist.append(t)
            info["fields"] = fieldlist

            data_count = SchemaManager.getRecordCountForDataType(
                repo_id, type_id)
            info["data_count"] = data_count
            return info
        except Exception as e:
            raise DbError(message="Could not get fields for types",
                          context="Schema.getFieldsForType",
                          dberror=e.message)
    def addType(repo_id, name, code, description, fields):
        # TODO validate params

        # TODO: check that repository is owned by current user
        ret = {"exists": False}
        try:
            result = db.run(
                "MATCH (t:SchemaType{code: {code}})--(r:Repository) WHERE ID(r) = {repo_id}  RETURN ID(t) as id, t.name as name, t.code as code, t.description as description",
                {
                    "code": code,
                    "repo_id": int(repo_id)
                })
            if result is not None and len(list(result)):
                ret = {"exists": True}
                for r in result:
                    ret['type'] = {
                        "id": r['id'],
                        "name": r['name'],
                        "code": r['code'],
                        "description": r['description']
                    }

                return ret
            else:
                result = db.run(
                    "MATCH (r:Repository) WHERE ID(r) = {repo_id} CREATE (t:SchemaType { name: {name}, code: {code}, description: {description}, storage: 'Graph'})-[:PART_OF]->(r) RETURN ID(t) as id",
                    {
                        "repo_id": int(repo_id),
                        "name": name,
                        "code": code,
                        "description": description
                    })

            SchemaManager.resetTypeInfoCache()
        except Exception as e:
            raise DbError(message="Could not add type: " + e.message,
                          context="Schema.addType",
                          dberror=e.message)

        # add/edit fields
        field_status = {}
        settings = {
            f.replace("settings_", ""): v
            for f, v in fields.iteritems() if 'settings_' in f
        }

        for k in fields:

            # add field
            fret = SchemaManager.addField(repo_id, code, k['name'], k['code'],
                                          k['type'], k['description'],
                                          settings)

            if 'field_id' in fret:
                field_status[k['code']] = {
                    'status_code': 200,
                    'field_id': fret['field_id'],
                    'msg': 'Created new field'
                }
            else:
                field_status[k['code']] = {
                    'status_code': 200,
                    'field_id': None,
                    'msg': 'Could not create new field'
                }

        if result:
            for r in result:
                ret['type'] = {
                    "id": r['id'],
                    "name": name,
                    "code": code,
                    "description": description,
                    "field_status": field_status
                }
                break
        else:
            raise DbError(message="Could not add type",
                          context="Schema.addType",
                          dberror="")

        return ret
Exemple #22
0
    def addListItem(repo_id, code, display, item_code, description=None):
        try:
            repo_id = int(repo_id)
        except TypeError:
            raise DbError(message="Invalid repo_id provided",
                          context="List.addListItem",
                          dberror="")
        ret = {}
        try:
            if code is None or len(code) == 0:
                raise ValidationError(message="List code is required",
                                      context="List.addListItem")
            list_info = ListManager.getInfoForList(repo_id, code)
            if list_info is None:
                raise ValidationError(message="List code is invalid",
                                      context="List.addListItem")

            if display is None:
                raise ValidationError(message="Display value is required",
                                      context="List.addListItem")

            if item_code is None:
                raise ValidationError(message="List Item Code is required",
                                      context="List.addListItem")
            if isinstance(code, int):
                item_result = db.run(
                    "MATCH (i:ListItem {display: {display}})--(l:List {code: {code}})--(r:Repository) WHERE ID(r) = {repo_id} RETURN ID(i) as id, i.display as display",
                    {
                        "display": display,
                        "code": code,
                        "repo_id": repo_id
                    }).peek()
            else:
                item_result = db.run(
                    "MATCH (i:ListItem {display: {display}})--(l:List {code: {code}})--(r:Repository) WHERE ID(r) = {repo_id} RETURN ID(i) as id, i.display as display",
                    {
                        "display": display,
                        "code": code,
                        "repo_id": repo_id
                    }).peek()
            if item_result is not None:
                ret['exists'] = True
                ret['item_id'] = item_result['id']
                ret['display'] = item_result['display']
                return ret
            else:
                item_flds = [
                    "display: {display}", "code: {item_code}",
                    "description: {description}"
                ]
                item_params = {
                    "list_code": code,
                    "repo_id": repo_id,
                    "display": display,
                    "item_code": item_code,
                    "description": description
                }

                add_result = db.run(
                    "MATCH (r:Repository)--(l:List {code: {list_code}}) WHERE ID(r) = {repo_id} CREATE (i:ListItem {"
                    + ", ".join(item_flds) +
                    "})-[:PART_OF]->(l) RETURN ID(i) as id, i.display as display, i.code as code",
                    item_params)

                r = add_result.peek()
                if r:
                    ret['exists'] = False
                    ret['item_id'] = r['id']
                    ret['display'] = r['display']
                    ret['code'] = r['code']
                    return ret
                else:
                    raise DbError(message="Could not add List Item",
                                  context="List.addListItem",
                                  dberror="")
        except Exception as e:
            raise DbError(message="Could not add List Item",
                          context="List.addListItem",
                          dberror=e.message)
Exemple #23
0
    def addList(repo_id, name, code, merge_setting, description='', items={}):
        try:
            repo_id = int(repo_id)
        except TypeError:
            raise DbError(message="Invalid repo_id provided",
                          context="List.addList",
                          dberror="")
        ret = {"exists": False}
        try:
            result = db.run(
                "MATCH (l:List{code: {code}})--(r:Repository) WHERE ID(r) = {repo_id} RETURN ID(l) as id, l.name as name, l.code as code, l.description as description",
                {
                    "code": code,
                    "repo_id": int(repo_id)
                }).peek()

            if result:
                print result
                ret = {
                    "exists": True,
                    "id": result['id'],
                    "code": result['code'],
                    "name": result['name'],
                    'description': result['description']
                }
                return ret
            else:
                result = db.run(
                    "MATCH (r:Repository) WHERE ID(r) = {repo_id} CREATE (l:List {name: {name}, code: {code}, description: {description}, merge_allowed: {merge}, storage: 'Graph'})-[:PART_OF]->(r) return ID(l) as id",
                    {
                        "repo_id": repo_id,
                        "name": name,
                        "code": code,
                        "description": description,
                        "merge": merge_setting
                    }).peek()
        except Exception as e:
            raise DbError(message="Could not add list: " + e.message,
                          context="List.addList",
                          dberror=e.message)

        #add/edit List Items
        item_status = {}
        for item in items:
            item_res = ListManager.addListItem(repo_id, code, item['display'],
                                               item['code'],
                                               item['description'])

            if 'item_id' in item_res:
                item_status[item['code']] = {
                    'status_code': 200,
                    'item_id': item_res['item_id'],
                    'msg': 'Created new list item'
                }
            else:
                item_status[item['code']] = {
                    'status_code': 200,
                    'item_id': None,
                    'msg': 'Could not create list item'
                }

        if result:
            ret = {
                'id': result['id'],
                'name': name,
                'code': code,
                'description': description,
                'list_status': item_status
            }
        else:
            raise DbError(message="Could not add list",
                          context="List.addList",
                          dberror="")

        return ret
    def editType(repo_id, type_id, name, code, description, fields,
                 fieldsToDelete):
        # TODO validate params

        # TODO: check that repository is owned by current user

        result = db.run(
            "MATCH (r:Repository)--(t:SchemaType) WHERE ID(r) = {repo_id} AND ID(t) = {type_id} SET t.name = {name}, t.code = {code}, t.description = {description} RETURN ID(t) AS id",
            {
                "repo_id": int(repo_id),
                "type_id": int(type_id),
                "name": name,
                "code": code,
                "description": description
            })

        # add/edit fields
        field_status = {}
        for k in fields:
            settings = {
                f.replace("settings_", ""): v
                for f, v in fields[k].iteritems() if 'settings_' in f
            }
            if 'id' in fields[k]:
                # edit existing field
                fret = SchemaManager.editField(repo_id, code, fields[k].get(
                    'id', ''), fields[k].get('name',
                                             ''), fields[k].get('code', ''),
                                               fields[k].get('type', ''),
                                               fields[k]['description'],
                                               settings)
                if 'field_id' in fret:
                    field_status[fields[k]['code']] = {
                        'status_code': 200,
                        'field_id': fret['field_id'],
                        'msg': 'Edited field'
                    }
                else:
                    field_status[fields[k]['code']] = {
                        'status_code': 200,
                        'field_id': None,
                        'msg': 'Could not edit field'
                    }
            else:
                # add field
                fret = SchemaManager.addField(repo_id, code,
                                              fields[k].get('name', ''),
                                              fields[k].get('code', ''),
                                              fields[k].get('type', ''),
                                              fields[k].get('description',
                                                            ''), settings)

                if 'field_id' in fret:
                    field_status[fields[k]['code']] = {
                        'status_code': 200,
                        'field_id': fret['field_id'],
                        'msg': 'Created new field'
                    }
                else:
                    field_status[fields[k]['code']] = {
                        'status_code': 200,
                        'field_id': None,
                        'msg': 'Could not create new field'
                    }

        # delete fields
        if fieldsToDelete:
            for field_id in fieldsToDelete:
                SchemaManager.deleteField(repo_id, code, field_id)

        SchemaManager.resetTypeInfoCache()

        if result:
            ret = {}
            for r in result:
                ret['type'] = {
                    "id": r['id'],
                    "name": name,
                    "code": code,
                    "description": description,
                    "field_status": field_status
                }
                return ret
        else:
            raise DbError(message="Could not edit type",
                          context="Schema.editType",
                          dberror="")
Exemple #25
0
    def editPerson(identity, forename, surname, location, email, url, tagline,
                   is_disabled, nyunetid):
        if is_number(identity):
            ident_str = "ID(p)={identity}"
            identity = int(identity)
        else:
            ident_str = "p.email={identity}"

        update = []
        if forename is not None:
            update.append("p.forename = {forename}")

        if surname is not None:
            update.append("p.surname = {surname}")

        if location is not None:
            update.append("p.location = {location}")

        if email is not None:
            update.append("p.email = {email}")

        if url is not None:
            update.append("p.url = {url}")

        if tagline is not None:
            update.append("p.tagline = {tagline}")

        if nyunetid is not None:
            update.append("p.nyunetid = {nyunetid}")

        if is_disabled is not None:
            print is_disabled
            try:
                is_disabled = int(is_disabled)
                if is_disabled <> 0:
                    is_disabled = 1
                update.append("p.is_disabled = {is_disabled}")
            except:
                pass

        update_str = "%s" % ", ".join(map(str, update))

        if update_str != '' and update_str is not None:
            result = db.run(
                "MATCH (p:Person) WHERE " + ident_str + " SET " + update_str +
                " RETURN p.forename AS forename, p.surname AS surname, p.location AS location, p.email AS email, p.url AS url, p.tagline AS tagline, p.is_disabled AS is_disabled, p.nyunetid AS nyunetid",
                {
                    "identity": identity,
                    "forename": forename,
                    "surname": surname,
                    "location": location,
                    "email": email,
                    "url": url,
                    "tagline": tagline,
                    "is_disabled": is_disabled,
                    "nyunetid": nyunetid
                })

            if result:
                updated_person = {}
                for p in result:
                    updated_person['forename'] = p['forename']
                    updated_person['surname'] = p['surname']
                    updated_person['name'] = str(p['forename']) + " " + str(
                        p['surname'])
                    updated_person['location'] = p['location']
                    updated_person['email'] = p['email']
                    updated_person['url'] = p['url']
                    updated_person['tagline'] = p['tagline']
                    updated_person['is_disabled'] = p['is_disabled']
                    updated_person['nyunetid'] = p['nyunetid']

                if updated_person is not None:
                    return updated_person
                else:
                    raise FindError(message="Person does not exist",
                                    context="People.editPerson")

            else:
                raise DbError(message="Could not update person",
                              context="People.editPerson",
                              dberror="")
        else:
            raise ValidationError(message="Nothing to update",
                                  context="People.editPerson")
Exemple #26
0
    def addPerson(forename, surname, location, email, nyunetid, url, tagline,
                  password):
        if validate_email(email, verify=False) is False:
            raise SaveError(message="Email address is invalid",
                            context="People.addPerson")
        if email_domain_is_allowed(email) is False:
            raise SaveError(
                message="You cannot register with this email address",
                context="People.addPerson")

        # TODO - Enforce password more complex password requirements?
        if password is not None and (len(password) >= 6):
            password_hash = sha256_crypt.hash(password)

            ts = time.time()
            created_on = datetime.datetime.fromtimestamp(ts).strftime(
                '%Y-%m-%d %H:%M:%S')

            try:
                result = db.run(
                    "MATCH (n:Person{email: {email}}) RETURN ID(n) as id, n.surname as surname, n.forename AS forename, n.email as email, n.nyunetid as nyunetid",
                    {
                        "email": email
                    }).peek()
            except Exception as e:
                raise DbError(message="Could not look up user",
                              context="People.addPerson",
                              dberror=e.message)

            if result:
                raise SaveError(
                    message="User already exists with this email address",
                    context="People.addPerson")
                # return {
                #   "exists": True,
                #   "user_id": result['id'],
                #   "surname": result['surname'],
                #   "forename": result['forename'],
                #   "name": str(result['forename']) + " " + str(result['surname']),
                #   "email": result['email'],
                #   "nyunetid": result['nyunetid']
                # }
            else:
                try:
                    result = db.run(
                        "CREATE (n:Person {url: {url}, surname: {surname}, forename: {forename}, email: {email}, location: {location}, tagline: {tagline}, nyunetid: {nyunetid}, is_disabled: 0, is_admin: 0,"
                        +
                        "password: {password_hash}, created_on: {created_on}, prefs: ''})"
                        +
                        " RETURN n.forename AS forename, n.surname AS surname, n.location AS location, n.email AS email, n.url AS url, n.tagline AS tagline, n.nyunetid as nyunetid, ID(n) AS user_id",
                        {
                            "url": url,
                            "surname": surname,
                            "forename": forename,
                            "email": email,
                            "location": location,
                            "tagline": tagline,
                            "nyunetid": nyunetid,
                            "password_hash": password_hash,
                            "created_on": created_on
                        })
                except Exception as e:
                    raise DbError(message="Could not create user",
                                  context="People.addPerson",
                                  dberror=e.message)

                if result:
                    person = {}
                    for p in result:
                        person['surname'] = p['surname']
                        person['forename'] = p['forename']
                        person['name'] = str(p['forename']) + " " + str(
                            p['surname'])
                        person['location'] = p['location']
                        person['email'] = p['email']
                        person['nyunetid'] = p['nyunetid']
                        person['url'] = p['url']
                        person['tagline'] = p['tagline']
                        person['user_id'] = p['user_id']

                        send_mail(
                            p['email'], None, "Registration notification",
                            "registration", {
                                "email": p['email'],
                                "login_url": app_config["base_url"]
                            })
                        return person

                else:
                    raise SaveError(message="Could not add person",
                                    context="People.addPerson")

        raise SaveError(
            message="Password must be at least six characters in length",
            context="People.addPerson")
Exemple #27
0
    def getInfoForList(repo_id, code):
        repo_id = int(repo_id)
        try:
            code = int(code)
        except ValueError:
            pass
        try:
            if isinstance(code, int):
                list_res = db.run(
                    "MATCH (r:Repository)--(l:List) WHERE ID(l) = {code} AND ID(r) = {repo_id} RETURN ID(l) as id, l.name as name, l.code as code, l.description as description, l.merge_allowed as merge_allowed",
                    {
                        "code": code,
                        "repo_id": repo_id
                    }).peek()
                if list_res is None:
                    return None

                items_res = db.run(
                    "MATCH (i:ListItem)--(l:List)--(r:Repository) WHERE ID(l) = {code} AND ID(r) = {repo_id} RETURN ID(i) as id, i.display as display, i.code as code, i.description as description",
                    {
                        "code": code,
                        "repo_id": repo_id
                    })
            else:
                list_res = db.run(
                    "MATCH (r:Repository)--(l:List) WHERE l.code = {code} AND ID(r) = {repo_id} RETURN ID(l) as id, l.name as name, l.code as code, l.description as description, l.merge_allowed as merge_allowed",
                    {
                        "code": code,
                        "repo_id": repo_id
                    }).peek()
                if list_res is None:
                    return None

                items_res = db.run(
                    "MATCH (i:ListItem)--(l:List)--(r:Repository) WHERE l.code = {code} AND ID(r) = {repo_id} RETURN ID(i) as id, i.display as display, i.code as code, i.description as description",
                    {
                        "code": code,
                        "repo_id": repo_id
                    })

            info = {
                'list_id': list_res['id'],
                'name': list_res['name'],
                'code': list_res['code'],
                'description': list_res['description'],
                'merge_allowed': list_res['merge_allowed']
            }

            item_list = []
            if items_res:
                for r in items_res:
                    li = {
                        'id': r['id'],
                        'display': r['display'],
                        'code': r['code'],
                        'description': r['description']
                    }
                    item_list.append(li)

            info['items'] = item_list
            return info

        except Exception as e:
            raise DbError(message="Could not get list items for list",
                          context="List.getInfoForList",
                          dberror=e.message)
Exemple #28
0
    def editList(repo_id, list_id, name, code, description, items,
                 delete_items, merge_setting):
        try:
            repo_id = int(repo_id)
            list_id = int(list_id)
        except TypeError:
            raise DbError(message="Invalid repo_id or list_id provided",
                          context="List.addListItem",
                          dberror="")
        result = db.run(
            "MATCH (r:Repository)--(l:List) WHERE ID(r) = {repo_id} AND ID(l) = {list_id} SET l.name = {name}, l.code = {code}, l.description = {description}, l.merge_allowed = {merge} RETURN ID(l) AS id",
            {
                "repo_id": int(repo_id),
                "list_id": int(list_id),
                "name": name,
                "code": code,
                "description": description,
                "merge": merge_setting
            })

        # add/edit fields
        item_status = {}
        for k in items:
            if 'id' in items[k]:
                # edit existing field
                li_ret = ListManager.editListItem(repo_id, code,
                                                  items[k].get('id', ''),
                                                  items[k].get('display', ''),
                                                  items[k].get('code', ''),
                                                  items[k]['description'])

                if 'item_id' in li_ret:
                    item_status[items[k]['code']] = {
                        'status_code': 200,
                        'item_id': li_ret['item_id'],
                        'msg': 'Edited list item'
                    }
                else:
                    item_status[items[k]['code']] = {
                        'status_code': 200,
                        'item_id': None,
                        'msg': 'Could not edit list item'
                    }
            else:
                # add field
                li_ret = ListManager.addListItem(
                    repo_id, code, items[k].get('display', ''),
                    items[k].get('code', ''), items[k].get('description', ''))

                if 'item_id' in li_ret:
                    item_status[items[k]['code']] = {
                        'status_code': 200,
                        'item_id': li_ret['item_id'],
                        'msg': 'Created new list item'
                    }
                else:
                    item_status[items[k]['code']] = {
                        'status_code': 200,
                        'item_id': None,
                        'msg': 'Could not create new list item'
                    }

        # delete fields
        if delete_items:
            for item_id in delete_items:
                ListManager.deleteListItem(repo_id, code, item_id)

        if result:
            ret = {}
            for r in result:
                ret['type'] = {
                    "id": r['id'],
                    "name": name,
                    "code": code,
                    "description": description,
                    "item_status": item_status
                }
                return ret
        else:
            raise DbError(message="Could not edit list",
                          context="List.editList",
                          dberror="")
    def editField(repo_id, typecode, field_id, name, code, fieldtype,
                  description, settings):
        if code is None or len(code) == 0:
            raise ValidationError(message="Field code is required",
                                  context="Schema.editField")

        if name is None or len(name) == 0:
            raise ValidationError(message="Field name is required",
                                  context="Schema.editField")

        ret = {}

        # Check field type
        if fieldtype not in SchemaManager.getDataTypes():
            raise ValidationError(message="Invalid field type " + fieldtype,
                                  context="Schema.editField")

        ft = SchemaManager.getDataTypeInstance(fieldtype)
        if ft is None:
            raise ValidationError(message="Invalid field type " + fieldtype,
                                  context="Schema.editField")

        sv = ft.validateSettings(settings)
        if sv is not True:
            raise SettingsValidationError(
                message="Invalid settings for field " + name,
                errors={code: sv},
                context="Schema.editField")

        # TODO: check that repository is owned by current user
        SchemaManager.resetTypeInfoCache()

        result = db.run(
            "MATCH (f:SchemaField {code: {code}})--(t:SchemaType {code: {typecode}})--(r:Repository) WHERE ID(r) = {repo_id} AND ID(f) <> {field_id}  RETURN ID(f) as id, f.name as name",
            {
                "typecode": typecode,
                "code": code,
                "repo_id": int(repo_id),
                "field_id": int(field_id)
            }).peek()
        if result is not None:
            ret['msg'] = "Field already exists"
            ret['field_id'] = result['id']
            ret['name'] = result['name']
            return ret
        else:
            flds = [
                "f.name = {name}", "f.code = {code}",
                "f.description = {description}", "f.type = {fieldtype}"
            ]
            params = {
                "repo_id": int(repo_id),
                "name": name,
                "code": code,
                "description": description,
                "typecode": typecode,
                "fieldtype": fieldtype,
                "field_id": int(field_id)
            }

            for s in settings:
                flds.append("f.settings_" + s + " = {settings_" + s + "}")
                params["settings_" + s] = settings[s]

            if fieldtype == 'ListDataType':

                field_info = SchemaManager.getInfoForField(
                    repo_id, typecode, field_id)
                print field_info, settings
                if 'settings_list_code' not in field_info:
                    field_info['list_code'] = settings['list_code']
                    field_info['settings_list_code'] = settings['list_code']
                if settings['list_code'] != field_info['settings_list_code']:
                    from lib.managers.DataManager import DataManager
                    from lib.managers.ListManager import ListManager

                    schema_data = DataManager.getDataForType(repo_id, typecode)
                    list_data = ListManager.getInfoForList(
                        repo_id, settings['list_code'])

                    list_items = [li['display'] for li in list_data['items']]
                    for data in schema_data['data']:
                        if code not in data:
                            continue
                        list_entry = data[code]
                        if not list_data['merge_allowed'] or list_data[
                                'merge_allowed'] != 0:
                            if list_entry not in list_items:
                                data[code] = None
                                DataManager.update(data['id'], data)
                        else:
                            if list_entry in list_items:
                                continue
                            list_entry_code = item_code = re.sub(
                                r'[^A-Za-z0-9_]+', '_', list_entry).lower()
                            ListManager.addListItem(repo_id,
                                                    settings['list_code'],
                                                    list_entry,
                                                    list_entry_code)

            result = db.run(
                "MATCH (r:Repository)--(t:SchemaType {code: {typecode}})--(f:SchemaField) WHERE ID(r) = {repo_id} AND ID(f) = {field_id} SET "
                + ", ".join(flds) + " RETURN ID(f) as id, f.name as name",
                params)
            r = result.peek()

            # TODO: check query result
            if r:
                ret['field_id'] = r['id']
                ret['name'] = r['name']
                return ret
            else:
                raise DbError(message="Could not edit field",
                              context="Schema.editField",
                              dberror="")