Finished WTForms support for properties + Refactored API so it doesn't handle form parsing anymore + added version.py and edited setup.py, version is now displayed in the footer of every page + reworked config to condense every persistence parameter and logging parameter
authorNicolas DURAND <nicolas.durand@iri.centrepompidou.fr>
Mon, 12 Jan 2015 12:00:30 +0100
changeset 38 d1bc73ce855a
parent 37 b7ec9ee75bbb
child 39 67d2ddbebf7e
Finished WTForms support for properties + Refactored API so it doesn't handle form parsing anymore + added version.py and edited setup.py, version is now displayed in the footer of every page + reworked config to condense every persistence parameter and logging parameter
setup.py
src/catedit/__init__.py
src/catedit/config.py.tmpl
src/catedit/models.py
src/catedit/persistence.py
src/catedit/resources.py
src/catedit/static/js/property_functions.js
src/catedit/templates/catbase.html
src/catedit/templates/cateditor.html
src/catedit/templates/catmodifs.html
src/catedit/templates/catrecap.html
src/catedit/version.py
src/catedit/views.py
--- a/setup.py	Wed Jan 07 12:38:57 2015 +0100
+++ b/setup.py	Mon Jan 12 12:00:30 2015 +0100
@@ -1,8 +1,12 @@
 from setuptools import setup, find_packages
 
+# Will set CURRENT_VERSION to the current version string and VERSION to the
+# current version tuple
+exec(compile(open("src/catedit/version.py"), "version.py", "exec"))
+
 setup(
     name='catedit',
-    version="0.1.2",
+    version=CURRENT_VERSION,
     url='http://www.iri.centrepompidou.fr',
     author='I.R.I.',
     author_email='dev@iri.centrepompidou.fr',
--- a/src/catedit/__init__.py	Wed Jan 07 12:38:57 2015 +0100
+++ b/src/catedit/__init__.py	Mon Jan 12 12:00:30 2015 +0100
@@ -5,15 +5,17 @@
 
 from logging import FileHandler, Formatter
 import os
+from catedit.version import CURRENT_VERSION
 
 from flask import Flask, session
+from flask_wtf.csrf import CsrfProtect
 from flask.ext.github import GitHub
 from flask.ext.cache import Cache
 from flask.ext.restful import Api
 
 from catedit.settings import AppSettings
 
-# set up app and database
+# Set up app
 app = Flask(__name__)
 app.config.from_object(AppSettings)
 cache = Cache(app, config={"CACHE_TYPE": "simple"})
@@ -32,14 +34,24 @@
 if not app_configured:
     raise Exception("Catedit not configured")
 
-#github
+# CSRF protection
+CsrfProtect(app)
+
+# Github
+app.config["GITHUB_CLIENT_ID"] = app.config["PERSISTENCE_CONFIG"] \
+                                           ["GITHUB_CLIENT_ID"]
+app.config["GITHUB_CLIENT_SECRET"] = app.config["PERSISTENCE_CONFIG"] \
+                                               ["GITHUB_CLIENT_SECRET"]
 github = GitHub(app)
 
-#api
+# Api
 api = Api(app)
 
+# Version
 
-#views
+app.config["CURRENT_VERSION"] = CURRENT_VERSION
+
+# Views and APIs
 from catedit.views import cat_editor, cat_recap, github_login,\
                           github_callback, logout
 
@@ -56,17 +68,18 @@
                  endpoint='category_changes')
 
 
-# set up logging
-if app.config["LOGGING"]:
-    file_handler = FileHandler(filename=app.config["LOG_FILE_PATH"])
+# Set up logging
+if app.config["LOGGING_CONFIG"]["IS_LOGGING"]:
+    file_handler = FileHandler(filename=app.config["LOGGING_CONFIG"]
+                                                  ["LOG_FILE_PATH"])
     file_handler.setFormatter(Formatter(
         '%(asctime)s %(levelname)s: %(message)s '
         '[in %(pathname)s:%(lineno)d]',
         '%Y-%m-%d %H:%M:%S'
     ))
     app.logger.addHandler(file_handler)
-    app.logger.setLevel(app.config["LOGGING_LEVEL"])
+    app.logger.setLevel(app.config["LOGGING_CONFIG"]["LOGGING_LEVEL"])
 
-# session management
+# Session management
 
 app.secret_key = app.config["SECRET_KEY"]
--- a/src/catedit/config.py.tmpl	Wed Jan 07 12:38:57 2015 +0100
+++ b/src/catedit/config.py.tmpl	Mon Jan 12 12:00:30 2015 +0100
@@ -12,34 +12,56 @@
 
     HOST = "0.0.0.0"
     DEBUG = True
-    LOGGING_LEVEL = "DEBUG"
 
     # WTForms settings
 
     SECRET_KEY = 'totally-secret-key'
 
-    # Saving file for local persistence
-    FILE_SAVE_DIRECTORY = "../../run/files/"
+    """
+        Logging parameters
+        * IS_LOGGING is a boolean to activate/deactivate logging
+        * LOGGING_LEVEL sets the minimum level of messages to log
+        * LOG_FILE_PATH sets where the log files will be saved
+    """
+    LOGGING_CONFIG = {
+        "IS_LOGGING": False,
+        "LOGGING_LEVEL": "DEBUG",
+        "LOG_FILE_PATH": "../../run/log/log.txt",
+    }
 
-    # Logging config
-    LOG_FILE_PATH = "../../run/log/log.txt"
-    LOGGING = False
+    """
+        Category persistence parameters
+        METHOD can be:
+        * "PersistenceToFile" : will save categories to files on system
+        * "PersistenceToGithub" : will save categories to files on Github
 
-    # Github repository config
+        You then need additional parameters related to the chosen METHOD.
+
+        If "PersistenceToFile" (Note: currently not supported)
+        * FILE_SAVE_PATH is the path to save the category files
 
-    REPOSITORY_LIST = [
-      "catedit-dev-testing",
-      "habitabilite-prototype"
-    ]
-    REPOSITORY_OWNER = "catedit-system"
-    CATEGORIES_PATH = "categories/"
-
-    # Github parameters
-
-    GITHUB_CLIENT_ID = "github-id-placeholder"
-    GITHUB_CLIENT_SECRET = "github-secret-placeholder"
-
-    # Property List
+        If "PersistenceToGithub"
+        * REPOSITORY_LIST is the list of repository available for users (Note:
+        for now, each user must have pushing right to EVERY repository in
+        this list in order to use the app)
+        * REPOSITORY_OWNER is the owner of the category repositories
+        * CATEGORIES_PATH is the path where the category serializations will
+        be saved within the repositories
+        * GITHUB_CLIENT_ID is the client ID of the Github app
+        * GITHUB_CLIENT_SECRET is the secret ID of the Github app
+    """
+    PERSISTENCE_CONFIG = {
+        "METHOD" : "PersistenceToGithub",
+        "REPOSITORY_LIST" : [
+            "catedit-dev-testing",
+            "catedit-dev-testing-2",
+            "habitabilite-prototype"
+        ],
+        "REPOSITORY_OWNER" : "catedit-system",
+        "CATEGORIES_PATH" : "categories/",
+        "GITHUB_CLIENT_ID" : "github-client-placeholder",
+        "GITHUB_CLIENT_SECRET" : "github-secret-placeholder",
+    }
 
     PROPERTY_LIST = {
         "subClassOf": {
@@ -49,20 +71,13 @@
             "rdflib_class": RDFS.subClassOf,
             "object_rdflib_class": URIRef,
         },
-        "value": {
-            "descriptive_label_fr": "Valeur",
-            "descriptive_label_en": "Value",
+        "comment": {
+            "descriptive_label_fr": "Commentaire",
+            "descriptive_label_en": "Comment",
             "object_type": "literal",
-            "rdflib_class": RDF.value,
+            "rdflib_class": RDFS.comment,
             "object_rdflib_class": Literal,
         },
-        "type": {
-            "descriptive_label_fr": "Type",
-            "descriptive_label_en": "Type",
-            "object_type": "uriref-category",
-            "rdflib_class": RDF.type,
-            "object_rdflib_class": URIRef,
-        },
         "resource": {
             "descriptive_label_fr": "Ressource",
             "descriptive_label_en": "Resource",
@@ -78,9 +93,3 @@
             "object_rdflib_class": URIRef,
         }
     }
-
-    # Category persistence parameters
-    # "PersistenceToFile" : will save categories to files on system
-    # "PersistenceToGithub" : will save categories to files on Github
-
-    PERSISTENCE_METHOD = "PersistenceToGithub"
--- a/src/catedit/models.py	Wed Jan 07 12:38:57 2015 +0100
+++ b/src/catedit/models.py	Mon Jan 12 12:00:30 2015 +0100
@@ -52,13 +52,21 @@
 
             if other_properties:
                 for (predicate, obj) in other_properties:
+                    rdf_obj = ""
+                    if (app.config["PROPERTY_LIST"]
+                                  [predicate]
+                                  ["object_type"] == "uriref-category"):
+                        rdf_obj = app.config["CATEGORY_NAMESPACE"] + obj
+                    else:
+                        rdf_obj = obj
                     self.cat_graph.add((self.this_category,
                                        app.config["PROPERTY_LIST"]
                                                  [predicate]
                                                  ["rdflib_class"],
                                        app.config["PROPERTY_LIST"]
                                                  [predicate]
-                                                 ["object_rdflib_class"](obj)))
+                                                 ["object_rdflib_class"]
+                                       (rdf_obj)))
 
         else:
             self.cat_graph = graph
@@ -157,13 +165,21 @@
                                                  ["rdflib_class"],
                                        None))
             for (predicate, obj) in new_other_properties:
+                rdf_obj = ""
+                if (app.config["PROPERTY_LIST"]
+                              [predicate]
+                              ["object_type"] == "uriref-category"):
+                    rdf_obj = app.config["CATEGORY_NAMESPACE"] + obj
+                else:
+                    rdf_obj = obj
                 self.cat_graph.add((self.this_category,
-                                    app.config["PROPERTY_LIST"]
-                                              [predicate]
-                                              ["rdflib_class"],
-                                    app.config["PROPERTY_LIST"]
-                                              [predicate]
-                                              ["object_rdflib_class"](obj)))
+                                   app.config["PROPERTY_LIST"]
+                                             [predicate]
+                                             ["rdflib_class"],
+                                   app.config["PROPERTY_LIST"]
+                                             [predicate]
+                                             ["object_rdflib_class"]
+                                   (rdf_obj)))
 
 
 class CategoryManager(object):
--- a/src/catedit/persistence.py	Wed Jan 07 12:38:57 2015 +0100
+++ b/src/catedit/persistence.py	Mon Jan 12 12:00:30 2015 +0100
@@ -80,7 +80,8 @@
         """
             Saves to a file
         """
-        path_to_save = app.config["FILE_SAVE_DIRECTORY"]+kwargs["name"]
+        path_to_save = app.config["PERSISTENCE_CONFIG"]["FILE_SAVE_DIRECTORY"]
+                       + kwargs["name"]
         file_to_save = open(path_to_save, 'wb')
         file_to_save.write(kwargs["content"])
         file_to_save.close()
@@ -89,7 +90,8 @@
         """
             Loads from a file
         """
-        path_to_load = app.config["FILE_SAVE_DIRECTORY"]+kwargs["name"]
+        path_to_load = app.config["PERSISTENCE_CONFIG"]["FILE_SAVE_DIRECTORY"]
+                       + kwargs["name"]
         file_to_load = open(path_to_load, 'rb')
         file_content = file_to_load.read()
         file_to_load.close()
@@ -99,7 +101,8 @@
         """
             Deletes a file
         """
-        path_to_delete = app.config["FILE_SAVE_DIRECTORY"]+kwargs["name"]
+        path_to_delete = app.config["PERSISTENCE_CONFIG"]
+                                   ["FILE_SAVE_DIRECTORY"] + kwargs["name"]
         os.remove(path_to_delete)
 
     # IDEA: return { file_name: file_content } type dict
@@ -108,10 +111,12 @@
             Lists all files in file directory (as set in config.py)
         """
         file_content_list = []
-        for file_name in os.listdir(app.config["FILE_SAVE_DIRECTORY"]):
+        for file_name in os.listdir(app.config["PERSISTENCE_CONFIG"]
+                                              ["FILE_SAVE_DIRECTORY"]):
             if not file_name or file_name[0] == ".":
                 continue
-            path_to_load = open(app.config["FILE_SAVE_DIRECTORY"]+file_name)
+            path_to_load = open(app.config["PERSISTENCE_CONFIG"]
+                                          ["FILE_SAVE_DIRECTORY"] + file_name)
             file_content = path_to_load.read()
             path_to_load.close()
             file_content_list.append(file_content)
@@ -189,7 +194,7 @@
         try:
             ref_master = github.get(
                 "repos/"
-                + app.config["REPOSITORY_OWNER"] + "/"
+                + app.config["PERSISTENCE_CONFIG"]["REPOSITORY_OWNER"] + "/"
                 + self.repository
                 + "/git/refs/heads/master"
             )
@@ -200,7 +205,7 @@
             logger.debug(
                 "Endpoint: "
                 + "repos/"
-                + app.config["REPOSITORY_OWNER"] + "/"
+                + app.config["PERSISTENCE_CONFIG"]["REPOSITORY_OWNER"] + "/"
                 + self.repository
                 + "/git/refs/heads/master"
             )
@@ -211,7 +216,7 @@
         try:
             last_commit_master = github.get(
                 "repos/"
-                + app.config["REPOSITORY_OWNER"] + "/"
+                + app.config["PERSISTENCE_CONFIG"]["REPOSITORY_OWNER"] + "/"
                 + self.repository
                 + "/git/commits/"
                 + ref_master["object"]["sha"]
@@ -227,7 +232,7 @@
         try:
             last_commit_tree = github.get(
                 "repos/"
-                + app.config["REPOSITORY_OWNER"] + "/"
+                + app.config["PERSISTENCE_CONFIG"]["REPOSITORY_OWNER"] + "/"
                 + self.repository
                 + "/git/trees/"
                 + last_commit_master["tree"]["sha"]
@@ -253,7 +258,8 @@
                 # no point doing anything, the file won't be in the new tree
                 if not(
                     element["path"] in [
-                        (app.config["CATEGORIES_PATH"] + cat_name)
+                        (app.config["PERSISTENCE_CONFIG"]
+                                   ["CATEGORIES_PATH"] + cat_name)
                         for cat_name in deletion_dict.keys()
                     ]
                 ):
@@ -265,7 +271,8 @@
                     # test if element is in modified categories
                     if (
                         element["path"] in [
-                            (app.config["CATEGORIES_PATH"] + cat_name)
+                            (app.config["PERSISTENCE_CONFIG"]
+                                       ["CATEGORIES_PATH"] + cat_name)
                             for cat_name in modification_dict.keys()
                         ]
                     ):
@@ -273,7 +280,8 @@
                         for (cat_name, cat_content) \
                                 in modification_dict.items():
                             if element["path"] == (
-                                app.config["CATEGORIES_PATH"] + cat_name
+                                app.config["PERSISTENCE_CONFIG"]
+                                          ["CATEGORIES_PATH"] + cat_name
                             ):
                                 # 4-1 for modified files, creating a new blob
                                 new_blob_data = {
@@ -283,7 +291,8 @@
                                 try:
                                     new_blob = github.post(
                                         "repos/"
-                                        + app.config["REPOSITORY_OWNER"] + "/"
+                                        + app.config["PERSISTENCE_CONFIG"]
+                                                    ["REPOSITORY_OWNER"] + "/"
                                         + self.repository
                                         + "/git/blobs",
                                         data=new_blob_data
@@ -313,11 +322,13 @@
         # Now we loop over modified categories to find the ones that don't
         # exist yet in the last commit tree in order to create blobs for them
         for (cat_name, cat_content) in modification_dict.items():
-            logger.debug(app.config["CATEGORIES_PATH"]+cat_content
+            logger.debug(app.config["PERSISTENCE_CONFIG"]
+                                   ["CATEGORIES_PATH"] + cat_content
                          + " should not be in "
                          + str([elt["path"] for
                                 elt in last_commit_tree["tree"]]))
-            if (app.config["CATEGORIES_PATH"] + cat_name not in
+            if (app.config["PERSISTENCE_CONFIG"]
+                          ["CATEGORIES_PATH"] + cat_name not in
                     [elt["path"] for elt in last_commit_tree["tree"]]):
 
                 # 4-1 for added files, creating a new blob
@@ -326,7 +337,8 @@
                 try:
                     new_blob = github.post(
                         "repos/"
-                        + app.config["REPOSITORY_OWNER"] + "/"
+                        + app.config["PERSISTENCE_CONFIG"]
+                                    ["REPOSITORY_OWNER"] + "/"
                         + self.repository
                         + "/git/blobs",
                         data=new_blob_data
@@ -340,7 +352,8 @@
                     logger.debug(ghe.response.text)
                 logger.debug(str(github.get("rate_limit")["resources"]))
                 new_tree_data["tree"].append({
-                    "path": app.config["CATEGORIES_PATH"] + cat_name,
+                    "path": app.config["PERSISTENCE_CONFIG"]
+                                      ["CATEGORIES_PATH"] + cat_name,
                     "mode": "100644",
                     "type": "blob",
                     "sha": new_blob["sha"]
@@ -351,7 +364,7 @@
         try:
             new_tree_response = github.post(
                 "repos/"
-                + app.config["REPOSITORY_OWNER"]+"/"
+                + app.config["PERSISTENCE_CONFIG"]["REPOSITORY_OWNER"] + "/"
                 + self.repository
                 + "/git/trees",
                 data=new_tree_data
@@ -371,7 +384,7 @@
         try:
             new_commit = github.post(
                 "repos/"
-                + app.config["REPOSITORY_OWNER"]+"/"
+                + app.config["PERSISTENCE_CONFIG"]["REPOSITORY_OWNER"] + "/"
                 + self.repository
                 + "/git/commits",
                 data=new_commit_data
@@ -391,7 +404,7 @@
         try:
             new_head = github.patch(
                 "repos/"
-                + app.config["REPOSITORY_OWNER"] + "/"
+                + app.config["PERSISTENCE_CONFIG"]["REPOSITORY_OWNER"] + "/"
                 + self.repository
                 + "/git/refs/heads/master",
                 data=json.dumps(new_head_data)
@@ -413,10 +426,12 @@
         """
         try:
             filedict = github.get("repos/"
-                                  + app.config["REPOSITORY_OWNER"]+"/"
+                                  + app.config["PERSISTENCE_CONFIG"]
+                                              ["REPOSITORY_OWNER"] + "/"
                                   + self.repository
                                   + "/contents/"
-                                  + app.config["CATEGORIES_PATH"]
+                                  + app.config["PERSISTENCE_CONFIG"]
+                                              ["CATEGORIES_PATH"]
                                   + kwargs["name"])
             file_content = str(b64decode(filedict["content"]), "utf-8")
         except GitHubError as ghe:
@@ -445,10 +460,12 @@
         filenames_list = []
         try:
             files_in_repo = github.get("repos/"
-                                       + app.config["REPOSITORY_OWNER"]+"/"
+                                       + app.config["PERSISTENCE_CONFIG"]
+                                                   ["REPOSITORY_OWNER"] + "/"
                                        + self.repository
                                        + "/contents/"
-                                       + app.config["CATEGORIES_PATH"])
+                                       + app.config["PERSISTENCE_CONFIG"]
+                                                   ["CATEGORIES_PATH"])
             filenames_list = [github_file["name"]
                               for github_file in files_in_repo]
             # logger.debug(filenames_list)
@@ -465,10 +482,12 @@
         for filename in filenames_list:
             try:
                 filedict = github.get("repos/"
-                                      + app.config["REPOSITORY_OWNER"]+"/"
+                                      + app.config["PERSISTENCE_CONFIG"]
+                                                  ["REPOSITORY_OWNER"] + "/"
                                       + self.repository
                                       + "/contents/"
-                                      + app.config["CATEGORIES_PATH"]
+                                      + app.config["PERSISTENCE_CONFIG"]
+                                                  ["CATEGORIES_PATH"]
                                       + filename)
                 file_content_list.append(str(b64decode(filedict["content"]),
                                          "utf-8"))
--- a/src/catedit/resources.py	Wed Jan 07 12:38:57 2015 +0100
+++ b/src/catedit/resources.py	Mon Jan 12 12:00:30 2015 +0100
@@ -8,7 +8,7 @@
 
 from rdflib import Graph
 from flask.ext.restful import Resource, reqparse
-from flask import request, session
+from flask import session
 from catedit import app, cache
 from catedit.models import Category, CategoryManager
 import catedit.persistence
@@ -39,7 +39,7 @@
         cat_manager_instance = CategoryManager(
             getattr(
                 catedit.persistence,
-                app.config["PERSISTENCE_METHOD"]
+                app.config["PERSISTENCE_CONFIG"]["METHOD"]
             )(repository=repository),
         )
         if cat_id is not None:
@@ -53,16 +53,28 @@
             return response
 
     # update category cat_id
-    def put(self, repository, cat_id=None):
+    def put(self, repository, cat_id=None, cat_data=None):
         """
             API to edit an existing category
-            * If cat_id is None and persistence support change sets, will
+
+            Args are:
+            * repository: the repository where the category cat_id is stored
+            * cat_id : the id of the category to edit
+            * cat_data : the new data of the category, dict of the form:
+            {
+                "label": edited_cat_label,
+                "description": edited_cat_description,
+                "properties": [(predicate1, object1), (predicate2, object2)]
+            }
+            List of predicate is available in config.py, key PROPERTY_LIST
+
+            Note: If cat_id is None and persistence support change sets, will
             submit all changes to category list
         """
         cat_manager_instance = CategoryManager(
             getattr(
                 catedit.persistence,
-                app.config["PERSISTENCE_METHOD"]
+                app.config["PERSISTENCE_CONFIG"]["METHOD"]
             )(repository=repository),
         )
         args = cat_parser.parse_args()
@@ -82,28 +94,6 @@
                     message=args["commit_message"]
                 )
         else:
-            new_property_list = []
-            logger.debug(args["property_predicate"])
-            logger.debug(args["property_object"])
-            if args["property_predicate"] is not None and \
-               args["property_object"] is not None:
-                for property_predicate, property_object in zip(
-                        args["property_predicate"],
-                        args["property_object"]):
-                    if property_object:
-                        property_object_to_append = property_object
-                        # if URIRef category, we must prefix id with namespace
-                        if (app.config["PROPERTY_LIST"]
-                                      [property_predicate]
-                                      ["object_type"]) == "uriref-category":
-                            property_object_to_append = \
-                                app.config["CATEGORY_NAMESPACE"] \
-                                + property_object
-                            logger.debug(property_object_to_append)
-                        new_property_list.append((property_predicate,
-                                                  property_object_to_append))
-            logger.debug(new_property_list)
-
             # is the edition occuring on an already modified category?
             if cat_id in session.get("modified_categories", {}) \
                                 .get(repository, {}).keys():
@@ -118,9 +108,9 @@
             else:
                 cat = cat_manager_instance.load_category(cat_id)
 
-            cat.edit_category(new_description=args["description"],
-                              new_label=args["label"],
-                              new_other_properties=new_property_list)
+            cat.edit_category(new_description=cat_data["description"],
+                              new_label=cat_data["label"],
+                              new_other_properties=cat_data["properties"])
 
             session["modified_categories"][repository][cat.cat_id] = str(
                 cat.cat_graph.serialize(format="turtle"), "utf-8"
@@ -138,31 +128,25 @@
         cache.clear()
         return 204
 
-    def post(self, repository):
+    def post(self, repository, cat_data):
         """
             API to create a new category
+
+            Args are:
+            * repository: the repository where the category cat_id is stored
+            * cat_data : the new data of the category, dict of the form:
+            {
+                "label": edited_cat_label,
+                "description": edited_cat_description,
+                "properties": [(predicate1, object1), (predicate2, object2)]
+            }
+            List of predicate is available in config.py, key PROPERTY_LIST
         """
-        args = cat_parser.parse_args()
-        property_list = []
-        logger.debug(args["property_predicate"])
-        logger.debug(args["property_object"])
-        for property_predicate, property_object in zip(
-                request.form.getlist('property_predicate'),
-                request.form.getlist('property_object')):
-            if property_object:
-                if (app.config["PROPERTY_LIST"]
-                              [property_predicate]
-                              ["object_type"]) == "uriref-category":
-                    property_list.append((property_predicate,
-                                          app.config["CATEGORY_NAMESPACE"]
-                                          + property_object))
-                else:
-                    property_list.append((property_predicate,
-                                          property_object))
-        logger.debug(property_list)
-        cat = Category(label=args["label"],
-                       description=args["description"],
-                       other_properties=property_list)
+        cat = Category(
+            label=cat_data["label"],
+            description=cat_data["description"],
+            other_properties=cat_data["properties"]
+        )
 
         if cat.cat_id not in session["modified_categories"][repository].keys():
             session["modified_categories"][repository][cat.cat_id] = str(
@@ -215,7 +199,7 @@
             cat_manager_instance = CategoryManager(
                 getattr(
                     catedit.persistence,
-                    app.config["PERSISTENCE_METHOD"]
+                    app.config["PERSISTENCE_CONFIG"]["METHOD"]
                 )(repository=repository),
             )
             cat_list = cat_manager_instance.list_categories()
@@ -320,8 +304,7 @@
         """
         logger.debug(modified_cat_id)
         logger.debug(str(session.get("modified_categories", {})))
-        logger.debug(str(session.get("modified_categories", {})
-                                .get(repository, {})))
+        
         if modified_cat_id is None:
             return {
                 "modified_categories": session.get("modified_categories", {})
--- a/src/catedit/static/js/property_functions.js	Wed Jan 07 12:38:57 2015 +0100
+++ b/src/catedit/static/js/property_functions.js	Mon Jan 12 12:00:30 2015 +0100
@@ -9,12 +9,12 @@
 
     initPropertyCount : function(divName,initValue){
       propertyCount=initValue;
-      if (propertyCount > 0) {
+      if (propertyCount >= 0) {
         document.getElementById(divName).className="visible";
       }
     },
 
-    addProperty : function(divToReveal, divToAddFieldsTo){
+    addProperty : function(divToReveal, divToAddFieldsTo, csrfToken){
         var selectElement = document.getElementById('property_selector');
         if (selectElement.options[selectElement.selectedIndex].id != "property_type_default") {
           var selectedOptionValue = selectElement.options[selectElement.selectedIndex].value;
@@ -43,9 +43,10 @@
              ((propertyObjectValue != "") && (propertyOptionObjectType == "uriref-link")) ||
              ((propertyObjectValue != "default") && (propertyOptionObjectType == "uriref-category"))) {
             var newProperty = document.createElement('tr');
-            newProperty.setAttribute('id','property_tr'+(createdProperties+1));
-            var newPropertyHTML = '<input type="hidden" id="property_predicate'+(createdProperties+1)+'" name="property_predicate" value="'+selectedOptionValue+'"> \
-                                   <input type="hidden" id="property_object'+(createdProperties+1)+'" name="property_object" value="'+propertyObjectValue+'"> \
+            newProperty.setAttribute('id','properties-'+(createdProperties+1));
+            var newPropertyHTML = '<input id="properties-'+(createdProperties+1)+'-csrf_token" name="properties-'+(createdProperties+1)+'-csrf_token" value="'+(csrfToken)+'" type="hidden"> \
+                                   <input type="hidden" id="property_predicate'+(createdProperties+1)+'" name="properties-'+(createdProperties+1)+'-property_predicate" value="'+selectedOptionValue+'"> \
+                                   <input type="hidden" id="property_object'+(createdProperties+1)+'" name="properties-'+(createdProperties+1)+'-property_object" value="'+propertyObjectValue+'"> \
                                    <td id="predicate_td'+(createdProperties+1)+'"> \
                                      <strong>'+selectedOptionText+'</strong> \
                                    </td> \
@@ -61,7 +62,7 @@
             parentElement.insertBefore(newProperty, parentElement.firstChild);
             createdProperties++;
             propertyCount++;
-            if (propertyCount > 0) {
+            if (propertyCount >= 0) {
               document.getElementById(divToReveal).className="visible";
             }
           }
@@ -70,7 +71,7 @@
 
     removeProperty : function(index, divToReveal){
         if (propertyCount > 0) {
-          divItem=document.getElementById("property_tr"+index);
+          divItem=document.getElementById("properties-"+index);
           divItem.parentNode.removeChild(divItem);
           propertyCount--;
           if (propertyCount == 0) {
--- a/src/catedit/templates/catbase.html	Wed Jan 07 12:38:57 2015 +0100
+++ b/src/catedit/templates/catbase.html	Mon Jan 12 12:00:30 2015 +0100
@@ -38,7 +38,7 @@
           <form class="navbar-form navbar-right">
             <select class="form-control select-repo" name="navrepo" onchange="window.location.href=this.form.navrepo.options[this.form.navrepo.selectedIndex].value">
               {% block repo_list %}
-                {% for repo in config["REPOSITORY_LIST"] %}
+                {% for repo in config["PERSISTENCE_CONFIG"]["REPOSITORY_LIST"] %}
                   <option value="{{url_for('cat_recap', repository=repo)}}" {% if repo==current_repository %}selected="selected"{% endif %}>{{repo}}</option>
                 {% endfor %}
               {% endblock repo_list %}
@@ -54,7 +54,7 @@
   </div>
   <footer class="footer">
     <div class="text-right footer-notes">
-      CatEdit - Prototype
+      CatEdit - Prototype v{{config["CURRENT_VERSION"]}}
       <br><br>
     </div>
   </footer>
--- a/src/catedit/templates/cateditor.html	Wed Jan 07 12:38:57 2015 +0100
+++ b/src/catedit/templates/cateditor.html	Mon Jan 12 12:00:30 2015 +0100
@@ -7,13 +7,6 @@
 {% block title %} {{ current_repository}}: Editeur {% endblock title %}
 {% block head %}
   {{ super() }}
-  <script src="{{ url_for('static', filename='js/property_functions.js') }}" language="Javascript" type="text/javascript"></script>
-  {% if cat_id %}
-    <script type=text/javascript>
-      CatEditScripts.initPropertyCount("properties",{{cat_properties|length}});
-      CatEditScripts.initCreatedProperties({{cat_properties|length}});
-    </script>
-  {% endif %}
 {% endblock head %}
 {% block navbar_items %}
   {{ super() }}
@@ -81,52 +74,55 @@
           <option value="{{ cat.cat_id }}"> {{ cat.cat_label }} </option>
         {% endfor %}
       </select>
-      <input type="button" value="Ajouter propriété" onClick="CatEditScripts.addProperty('properties','property_table_body');" class="btn btn-default" {{ readonly }}>
+      <input type="button" value="Ajouter propriété" onClick="CatEditScripts.addProperty('properties_div','property_table_body','{{ csrf_token() }}');" class="btn btn-default" {{ readonly }}>
     </div>
     <div class="alert alert-warning hidden" role="alert" id="uriref-category-field-text">
     </div>
-    <div id="properties">
+    <div id="properties_div">
       <div class="row">
         <div class="col-md-6">
           <br>
           <table id="property_table" class="table table-condensed">
             <tbody id="property_table_body">
-            {% set property_count=1 %}
-            {% for (predicate, object) in cat_properties %}
-                <tr id="property_tr{{property_count}}">
-                  {% if config["PROPERTY_LIST"][predicate]["object_type"]=="uriref-category" %}
+            {% set property_count=0 %}
+            {% for property in form.properties %}
+                <tr id="properties-{{property_count}}">
+                  <input id="properties-{{property_count}}-csrf_token" name="properties-{{property_count}}-csrf_token" value="{{ csrf_token() }}" type="hidden">
+                  {% if config["PROPERTY_LIST"][property.property_predicate.data]["object_type"]=="uriref-category" %}
+                    {{property.property_object.data}} vs:
                     {% for cat in cat_list %}
-                      {% if object == config["CATEGORY_NAMESPACE"]+cat.cat_id %}
+                      {{config["CATEGORY_NAMESPACE"]+cat.cat_id}}, 
+                      {% if property.property_object.data == config["CATEGORY_NAMESPACE"]+cat.cat_id %}
                         {% if cat.cat_id not in deleted_cat_list %}
-                          <input type="hidden" id="property_predicate{{ property_count }}" name="property_predicate" value="{{predicate}}"/>
-                          <input type="hidden" id="property_object{{ property_count }}" name="property_object" value="{{cat.cat_id}}"/>
+                          {{ property.property_predicate() }}
+                          {{ property.property_object() }}
                           <td id="predicate_td{{ property_count }}">
-                            <strong>{{ config["PROPERTY_LIST"][predicate]["descriptive_label_fr"] }}</strong>
+                            <strong>{{ config["PROPERTY_LIST"][property.property_predicate.data]["descriptive_label_fr"] }}</strong>
                           </td>
-                          <td id="object_td{{ property_count }}">
+                          <td id="object_td{{property_count-1}}">
                             {{ cat.cat_label }}
                           </td>
-                          <td id="delete_button_td{{ property_count }}" class="text-center">
-                            <input type="button" id="property_delete_button{{ property_count }}" class="btn btn-default property-delete-button" onClick="CatEditScripts.removeProperty({{ property_count }}, 'properties')" value="Supprimer">
+                          <td id="delete_button_td{{property_count-1}}" class="text-center">
+                            <input type="button" id="property_delete_button{{property_count-1}}" class="btn btn-default property-delete-button" onClick="CatEditScripts.removeProperty({{ property_count }}, 'properties_div')" value="Supprimer">
                           </td>
                         {% endif %}
                       {% endif %}
                     {% endfor %}
                   {% else %}
-                    <input type="hidden" id="property_predicate{{ property_count }}" name="property_predicate" value="{{predicate}}"/>
-                    <input type="hidden" id="property_object{{ property_count }}" name="property_object" value="{{object}}"/>
+                      {{ property.property_predicate() }}
+                      {{ property.property_object() }}
                     <td id="predicate_td{{ property_count }}">
-                      <strong>{{ config["PROPERTY_LIST"][predicate]["descriptive_label_fr"] }}</strong>
+                      <strong>{{ config["PROPERTY_LIST"][property.property_predicate.data]["descriptive_label_fr"] }}</strong>
                     </td>
                     <td id="object_td{{ property_count }}">
-                      {% if config["PROPERTY_LIST"][predicate]["object_type"]=="uriref-link" %}
-                        <a href="{{ object }}">{{ object }}</a>
+                      {% if config["PROPERTY_LIST"][property.property_predicate.data]["object_type"]=="uriref-link" %}
+                        <a href="{{ property.property_object.data }}">{{ property.property_object.data }}</a>
                       {% else %}
-                        {{ object }}
+                        {{ property.property_object.data }}
                       {% endif %}
                     </td>
-                    <td id="delete_button_td{{ property_count }}" class="text-center">
-                      <input type="button" id="property_delete_button{{ property_count }}" class="btn btn-default property-delete-button" onClick="CatEditScripts.removeProperty({{ property_count }}, 'properties')" value="Supprimer">
+                    <td id="delete_button_td{{property_count-1}}" class="text-center">
+                      <input type="button" id="property_delete_button{{property_count-1}}" class="btn btn-default property-delete-button" onClick="CatEditScripts.removeProperty({{ property_count }}, 'properties_div')" value="Supprimer">
                     </td>
                   {% endif %}
                 {% set property_count=property_count+1 %}
@@ -141,4 +137,11 @@
     <a href="{{ url_for('cat_recap', repository=current_repository)}}"class="btn btn-default">Annuler</a>
   </form>
   {% if readonly %} </fieldset> {% endif %}
+  <script src="{{ url_for('static', filename='js/property_functions.js') }}" language="Javascript" type="text/javascript"></script>
+  {% if cat_id %}
+    <script type=text/javascript>
+      CatEditScripts.initPropertyCount('properties_div',{{cat_properties|length}});
+      CatEditScripts.initCreatedProperties({{cat_properties|length}});
+    </script>
+  {% endif %}
 {% endblock page_content %}
--- a/src/catedit/templates/catmodifs.html	Wed Jan 07 12:38:57 2015 +0100
+++ b/src/catedit/templates/catmodifs.html	Mon Jan 12 12:00:30 2015 +0100
@@ -10,7 +10,7 @@
   <script src="{{ url_for('static', filename='js/jquery-1.11.1.min.js') }}" language="Javascript" type="text/javascript"></script>
   <script>
     $(document).ready(function(){
-      {% for cat in cat_list %}
+      {% for cat in existing_cat_list %}
         $("#properties_{{cat.cat_id}}").hide();
         $("#info_button_{{cat.cat_id}}").click(function(){
           $("#properties_{{cat.cat_id}}").slideToggle();
@@ -71,12 +71,12 @@
       </td>
     </tr>
     {% else %}
-      {% if cat_list|length == 0 %}
+      {% if existing_cat_list|length == 0 %}
         <tr>
           <td class="col-md-12" colspan="2">Aucune catégorie n'a été créée pour l'instant. {% if not readonly %}<a href="{{ url_for('cat_editor', repository=current_repository) }}">Créer une catégorie</a>{% endif %}</td>
         </tr>
       {% else %}
-        {% for cat in cat_list %}
+        {% for cat in existing_cat_list %}
           <tr>
             <td class="col-md-2">{{ cat.cat_label }}</td>
             <td class="col-md-8">{{ cat.cat_description}}</td>
@@ -90,6 +90,7 @@
               <td class="text-center">
                 <a title="Supprimer catégorie">
                   <form method="POST" action="{{ url_for('cat_modifs', deleted_cat_id=cat.cat_id, repository=current_repository) }}" class="form-inline form-button">
+                    <input name="csrf_token" value="{{ csrf_token() }}" type="hidden">
                     <fieldset {% if readonly %}disabled{% endif %}>
                       <button type="submit" class="btn btn-default">
                         <span class="glyphicon glyphicon-trash" title="Supprimer catégorie"/>
@@ -113,7 +114,7 @@
                       <dt>{{ config["PROPERTY_LIST"][predicate]["descriptive_label_fr"] }}</dt>
                       <dd>
                         {% if config["PROPERTY_LIST"][predicate]["object_type"]=="uriref-category" %}
-                          {% for cat in cat_list %}
+                          {% for cat in existing_cat_list %}
                             {% if object == config["CATEGORY_NAMESPACE"]+cat.cat_id %}
                               {{ cat.cat_label }}
                             {% endif %}
@@ -184,7 +185,7 @@
                     <dt>{{ config["PROPERTY_LIST"][predicate]["descriptive_label_fr"] }}</dt>
                     <dd>
                       {% if config["PROPERTY_LIST"][predicate]["object_type"]=="uriref-category" %}
-                        {% for cat in cat_list %}
+                        {% for cat in total_cat_list %}
                           {% if object == config["CATEGORY_NAMESPACE"]+cat.cat_id %}
                             {{ cat.cat_label }}
                           {% endif %}
@@ -201,6 +202,7 @@
               </div>
               <div id="delete_created_{{cat.cat_id}}">
                 <form method="POST" action="{{ url_for('cat_modifs', deleted_modifs_id=cat.cat_id, repository=current_repository) }}" class="form-inline align-center">
+                  <input name="csrf_token" value="{{ csrf_token() }}" type="hidden">
                   <fieldset {% if readonly %}disabled{% endif %}>
                     <div class="input-group">
                       <div class="input-group-addon">
@@ -245,7 +247,7 @@
                     <dt>{{ config["PROPERTY_LIST"][predicate]["descriptive_label_fr"] }}</dt>
                     <dd>
                       {% if config["PROPERTY_LIST"][predicate]["object_type"]=="uriref-category" %}
-                        {% for cat in cat_list %}
+                        {% for cat in total_cat_list %}
                           {% if object == config["CATEGORY_NAMESPACE"]+cat.cat_id %}
                             {{ cat.cat_label }}
                           {% endif %}
@@ -262,6 +264,7 @@
               </div>
               <div id="delete_modified_{{cat.cat_id}}">
                 <form method="POST" action="{{ url_for('cat_modifs', deleted_modifs_id=cat.cat_id, repository=current_repository) }}" class="form-inline align-center">
+                  <input name="csrf_token" value="{{ csrf_token() }}" type="hidden">
                   <fieldset {% if readonly %}disabled{% endif %}>
                     <div class="input-group">
                       <div class="input-group-addon">
@@ -288,13 +291,14 @@
       </tr>
       {% else %}
         {% for deleted_cat in deleted_cat_namelist %}
-          {% for existing_cat in cat_list %}
+          {% for existing_cat in existing_cat_list %}
             {% if existing_cat.cat_id == deleted_cat %}
               <tr class="danger">
                 <td class="col-md-2">{{ existing_cat.cat_label }}</td>
                 <td class="col-md-8"><i>Cette catégorie va être supprimée quand vous soumettrez vos modifications.</i></td>
                 <td class="col-md-2 text-center">
                   <form method="POST" action="{{ url_for('cat_modifs', deleted_cat_id=deleted_cat, repository=current_repository) }}">
+                    <input name="csrf_token" value="{{ csrf_token() }}" type="hidden">
                     <fieldset {% if readonly %}disabled{% endif %}>
                       <input type="submit" class="btn btn-default" value="Restaurer">
                     </fieldset>
--- a/src/catedit/templates/catrecap.html	Wed Jan 07 12:38:57 2015 +0100
+++ b/src/catedit/templates/catrecap.html	Mon Jan 12 12:00:30 2015 +0100
@@ -93,6 +93,7 @@
             {% if (cat.state == "untouched") %}
             <td class="col-md-1 text-center">
               <form method="POST" action="{{url_for('cat_recap', deleted_cat_id=cat.cat_id, repository=current_repository)}}" class="form-inline">
+                <input name="csrf_token" value="{{ csrf_token() }}" type="hidden">
                 <a title="Supprimer catégorie">
                   <button class="btn btn-default" type="submit"><span class="glyphicon glyphicon-trash"/></button>
                 </a>
@@ -101,6 +102,7 @@
             {% elif (cat.state == "created" or cat.state == "modified") %}
             <td class="col-md-1 text-center">
               <form method="POST" action="{{url_for('cat_recap', deleted_modifs_id=cat.cat_id, repository=current_repository)}}" class="form-inline">
+                <input name="csrf_token" value="{{ csrf_token() }}" type="hidden">
                 <a title="Supprimer changements">
                   <button class="btn btn-default"><span class="glyphicon glyphicon-remove-sign"/></button>
                 </a>
@@ -109,6 +111,7 @@
             {% else %}
             <td colspan="2">
               <form method="POST" action="{{url_for('cat_recap', deleted_cat_id=cat.cat_id, repository=current_repository)}}" class="form-inline">
+                <input name="csrf_token" value="{{ csrf_token() }}" type="hidden">
                 <a title="Restaurer catégorie">
                   <button class="btn btn-default" type="submit">Restaurer</button>
                 </a>
@@ -157,6 +160,7 @@
   </table>
   {% if session.get("user_logged") %}
   <form method="POST" action="{{url_for('cat_recap', repository=current_repository)}}" class="form-inline">
+    <input name="csrf_token" value="{{ csrf_token() }}" type="hidden">
     <h4> Annuler tous mes changements actuels :
       <a title="Supprimer changements">
         <button type="submit" class="btn btn-default" {% if readonly %}disabled{% endif %}>
@@ -168,6 +172,6 @@
   <h4> Soumettre mes changements actuels : <a href="{{ url_for('cat_modifs', repository=current_repository)}}" title="Soumettre changements" class="btn btn-default" {% if readonly %}disabled{% endif %}><span class="glyphicon glyphicon-share"/></a>
   </h4>
   {% endif %}
-  <h3> Consulter l'historique des modifications : <a href="https://github.com/{{config['REPOSITORY_OWNER']}}/{{current_repository}}/commits/master" title="Aller à l'historique des modifications sur Github" class="btn btn-default"><span class="glyphicon glyphicon-list"/></a></h3>
-  <h3> Consulter les discussions générales sur cet ensemble de catégorie (Issues) : <a href="https://github.com/{{config['REPOSITORY_OWNER']}}/{{current_repository}}/issues" title="Aller à la page de discussion sur l'ensemble de catégories" class="btn btn-default"><span class="glyphicon glyphicon-comment"/></a></h3>
+  <h3> Consulter l'historique des modifications : <a href="https://github.com/{{config['PERSISTENCE_CONFIG']['REPOSITORY_OWNER']}}/{{current_repository}}/commits/master" title="Aller à l'historique des modifications sur Github" class="btn btn-default"><span class="glyphicon glyphicon-list"/></a></h3>
+  <h3> Consulter les discussions générales sur cet ensemble de catégorie (Issues) : <a href="https://github.com/{{config['PERSISTENCE_CONFIG']['REPOSITORY_OWNER']}}/{{current_repository}}/issues" title="Aller à la page de discussion sur l'ensemble de catégories" class="btn btn-default"><span class="glyphicon glyphicon-comment"/></a></h3>
 {% endblock page_content %}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/catedit/version.py	Mon Jan 12 12:00:30 2015 +0100
@@ -0,0 +1,20 @@
+"""
+    version.py:
+    Module to get the current CatEdit version, the only place where we have to
+    increment version numbers
+"""
+
+__all__ = ["VERSION", "get_version", "CURRENT_VERSION"]
+
+VERSION = (0, 1, 2)
+
+def get_version():
+    """
+        Function to convert the tuple to a string
+    """
+    version = "%s.%s" % (VERSION[0], VERSION[1])
+    if version[2]:
+        version = "%s.%s" % (version, VERSION[2])
+    return version
+
+CURRENT_VERSION = get_version()
--- a/src/catedit/views.py	Wed Jan 07 12:38:57 2015 +0100
+++ b/src/catedit/views.py	Mon Jan 12 12:00:30 2015 +0100
@@ -10,15 +10,19 @@
 from flask.ext.github import GitHubError
 from flask_wtf import Form
 from catedit.resources import CategoryAPI, CategoryChangesAPI
-from wtforms import StringField, TextAreaField, \
-                    FormField, FieldList, HiddenField
+from wtforms import StringField, TextAreaField, FormField, FieldList, HiddenField
 from wtforms.validators import DataRequired, Optional, AnyOf
 from rdflib import Graph
 from io import StringIO
 
 logger = app.logger
 
+
 class PropertyForm(Form):
+    """
+        Form of a given property, each one is a couple of hidden fields that
+        can be Javascript-generated in the template
+    """
     property_predicate = HiddenField(
         validators=[AnyOf(values=app.config["PROPERTY_LIST"].keys())]
     )
@@ -26,6 +30,7 @@
         validators=[DataRequired()]
     )
 
+
 class CategoryForm(Form):
     """
         Custom form class for creating a category with the absolute minimal
@@ -39,7 +44,8 @@
         "Description de la categorie (obligatoire)",
         validators=[DataRequired()]
     )
-    properties = FieldList(FormField(PropertyForm),validators=[Optional()])
+    properties = FieldList(FormField(PropertyForm), validators=[Optional()])
+
 
 class CommitForm(Form):
     """
@@ -77,7 +83,7 @@
 
         Note: it also handles category deletion from the same page.
     """
-    if repository not in app.config["REPOSITORY_LIST"]:
+    if repository not in app.config["PERSISTENCE_CONFIG"]["REPOSITORY_LIST"]:
         abort(404)
 
     cat_api_instance = CategoryAPI()
@@ -190,15 +196,18 @@
         session, links to the editor forms, allows the users to cancel their
         own changes and submits all their changes.
     """
-    if repository not in app.config["REPOSITORY_LIST"]:
+    if repository not in app.config["PERSISTENCE_CONFIG"]["REPOSITORY_LIST"]:
         abort(404)
 
     logger.debug(repository)
 
-    cat_list = []
     changes_list = []
+
+    existing_cat_list = []
     modified_cat_list = []
     created_cat_list = []
+    total_cat_list = []
+
     deleted_cat_namelist = []
     modified_cat_namelist = []
 
@@ -206,6 +215,7 @@
     cat_changes_api_instance = CategoryChangesAPI()
 
     if deleted_cat_id is None and deleted_modifs_id is None:
+
         commit_form = CommitForm(request.form)
 
         # if it's a GET with no delete_cat_id or deleted_modifs_id, then we'll
@@ -219,6 +229,8 @@
                     repository=repository
                 )[0]
 
+                cat_data = dict({})
+
                 # Creating existing cat list
                 for serialized_cat in serialized_cat_list:
                     cat_rdf_graph = Graph()
@@ -226,10 +238,16 @@
                                         format='turtle')
                     cat = Category(graph=cat_rdf_graph)
 
-                    cat_list.append({"cat_label": cat.label,
-                                     "cat_description": cat.description,
-                                     "cat_id": cat.cat_id,
-                                     "cat_properties": cat.properties})
+                    cat_data = {
+                        "cat_label": cat.label,
+                        "cat_description": cat.description,
+                        "cat_id": cat.cat_id,
+                        "cat_properties": cat.properties
+                    }
+
+                    existing_cat_list.append(cat_data)
+                    total_cat_list.append(cat_data)
+                    cat_data = dict({})
 
                 # Creating modified and created cat lists
                 for modified_cat_name in \
@@ -243,20 +261,21 @@
                         format='turtle'
                     )
                     modified_cat = Category(graph=modified_cat_rdf_graph)
+
+                    cat_data = {
+                        "cat_label": modified_cat.label,
+                        "cat_description": modified_cat.description,
+                        "cat_id": modified_cat.cat_id,
+                        "cat_properties": modified_cat.properties
+                    }
                     if modified_cat.cat_id in \
                             [existing_cat["cat_id"]
-                                for existing_cat in cat_list]:
-                        modified_cat_list.append(
-                            {"cat_label": modified_cat.label,
-                             "cat_description": modified_cat.description,
-                             "cat_id": modified_cat.cat_id,
-                             "cat_properties": modified_cat.properties})
+                                for existing_cat in existing_cat_list]:
+                        modified_cat_list.append(cat_data)
                     else:
-                        created_cat_list.append(
-                            {"cat_label": modified_cat.label,
-                             "cat_description": modified_cat.description,
-                             "cat_id": modified_cat.cat_id,
-                             "cat_properties": modified_cat.properties})
+                        created_cat_list.append(cat_data)
+                        total_cat_list.append(cat_data)
+                    cat_data = dict({})
 
                 # Creating deleted cat list
                 deleted_cat_namelist = list(
@@ -265,8 +284,16 @@
                 modified_cat_namelist = list(
                     changes_list["modified_categories"].keys()
                 )
+                logger.debug("total:"+str(total_cat_list))
+                logger.debug("existing:"+str(existing_cat_list))
+                logger.debug("created:"+str(created_cat_list))
+                logger.debug("modified:"+str(modified_cat_list))
+                logger.debug("modified names:"+str(modified_cat_namelist))
+                logger.debug("deleted names:"+str(deleted_cat_namelist))
+
             return render_template('catmodifs.html',
-                                   cat_list=cat_list,
+                                   total_cat_list=total_cat_list,
+                                   existing_cat_list=existing_cat_list,
                                    created_cat_list=created_cat_list,
                                    modified_cat_list=modified_cat_list,
                                    modified_cat_namelist=modified_cat_namelist,
@@ -312,7 +339,7 @@
         View that handles creation and edition of categories. Template is
         cateditor.html, located in src/templates
     """
-    if repository not in app.config["REPOSITORY_LIST"]:
+    if repository not in app.config["PERSISTENCE_CONFIG"]["REPOSITORY_LIST"]:
         abort(404)
 
     cat_api_instance = CategoryAPI()
@@ -357,33 +384,38 @@
         current_cat = Category(graph=cat_rdf_graph)
         current_cat_id = current_cat.cat_id
         current_cat_properties = current_cat.properties
+        logger.debug(current_cat.properties)
 
-        cat_form = CategoryForm(request.form, obj=current_cat)
-        cat_form.label.data = current_cat.label
-        cat_form.description.data = current_cat.description
-    else:
-        cat_form = CategoryForm(request.form)
+    cat_form = CategoryForm(request.form)
 
     if request.method == "GET":
         """
             GET Method means we will display the editor
         """
-        deleted_cat_dict = {}
+        if current_cat is not None:
+            cat_form.label.data = current_cat.label
+            cat_form.description.data = current_cat.description
+            for (cat_predicate, cat_object) in current_cat_properties:
+                cat_form.properties.append_entry({
+                    "property_predicate": cat_predicate,
+                    "property_object": cat_object
+                })
+
         # deleted categories we won't append to cat_list
+        deleted_cat_dict = {}
+        # modified categories to append to cat_list in case label changed
         modified_cat_dict = {}
-        # modified categories to append to cat_list in case label changed
+        # existing categories we get from CategoryAPI
         serialized_cat_list = []
-        # existing categories we get from CategoryAPI
+        # changes list we get from CategoryChangesAPI
         cat_changes = {}
-        # changes list we get from CategoryChangesAPI
 
-        cat_list = []
         # list of category that will be used in property editor, list of dict
         # {"cat_id": cat.cat_id,
         #  "cat_label": cat.label,
         #  "cat_description": cat.description,
         #  "cat_properties": cat.properties}
-
+        cat_list = []
 
         if session.get("user_logged", None) is not None:
             serialized_cat_list = cat_api_instance.get(repository)
@@ -433,18 +465,37 @@
         """
         if (session.get("user_logged", None) is not None and
                 session.get("user_can_edit", False) is not False):
+
+            logger.debug(cat_form.errors)
+
             if cat_form.validate_on_submit():
-                logger.debug(cat_form.label.data)
-                logger.debug(cat_form.description.data)
-                logger.debug(cat_form.properties.data)
+                cat_data = {}
+                cat_data["label"] = cat_form.label.data
+                cat_data["description"] = cat_form.description.data
+                cat_data["properties"] = [
+                    (cat_property["property_predicate"],
+                     cat_property["property_object"])
+                    for cat_property in cat_form.properties.data
+                ]
+                logger.debug(cat_data)
+
                 if cat_id is not None:
-                    cat_api_instance.put(repository=repository, cat_id=cat_id)
+                    logger.debug(str(cat_data))
+                    cat_api_instance.put(
+                        repository=repository,
+                        cat_id=cat_id,
+                        cat_data=cat_data
+                    )
                 else:
-                    cat_api_instance.post(repository=repository)
+                    logger.debug(str(cat_data))
+                    cat_api_instance.post(
+                        repository=repository,
+                        cat_data=cat_data
+                    )
                 return redirect(url_for('cat_recap', repository=repository))
             else:
-                # if form doesn't validate we don't want to delete whatever changes
-                # the user did
+                # if form doesn't validate we don't want to delete whatever
+                # changes the user did
                 return render_template('cateditor.html',
                                        cat_id=cat_id,
                                        cat_properties=cat.properties,
@@ -453,8 +504,8 @@
                                        deleted_cat_list=deleted_cat_list,
                                        current_repository=repository)
 
+        # If user wasn't logged or couldn't edit but somehow submitted a POST
         else:
-        # User wasn't logged or couldn't edit but somehow submitted a POST
             return redirect(url_for('cat_index'))
 
 
@@ -468,21 +519,24 @@
         "FileEditUser"
     """
     if getattr(catedit.persistence,
-               app.config["PERSISTENCE_METHOD"])().session_compliant is True:
+               app.config["PERSISTENCE_CONFIG"]
+                         ["METHOD"])().session_compliant is True:
         session["save_user_changes"] = True
         session["modified_categories"] = {
-            repo: {} for repo in app.config["REPOSITORY_LIST"]
+            repo: {} for repo in app.config["PERSISTENCE_CONFIG"]
+                                           ["REPOSITORY_LIST"]
         }
         session["deleted_categories"] = {
-            repo: {} for repo in app.config["REPOSITORY_LIST"]
+            repo: {} for repo in app.config["PERSISTENCE_CONFIG"]
+                                           ["REPOSITORY_LIST"]
         }
-    if app.config["PERSISTENCE_METHOD"] == "PersistenceToGithub":
+    if app.config["PERSISTENCE_CONFIG"]["METHOD"] == "PersistenceToGithub":
         logger.debug(str(github.get("rate_limit")["resources"]))
         return github.authorize(
             scope="repo",
             redirect_uri=url_for('github_callback', _external=True)
         )
-    elif app.config["PERSISTENCE_METHOD"] == "PersistenceToFile":
+    elif app.config["PERSISTENCE_CONFIG"]["METHOD"] == "PersistenceToFile":
         session["user_logged"] = True
         session["user_can_edit"] = True
         session["user_login"] = "FileEditUser"
@@ -515,8 +569,14 @@
             logger.debug(repo["name"])
         session["user_can_edit"] = True
         user_repos_name = [repo["name"] for repo in repo_list]
-        logger.debug(str(user_repos_name)+" "+str(app.config["REPOSITORY_LIST"]))
-        if not all((repo in user_repos_name) for repo in app.config["REPOSITORY_LIST"]):
+        logger.debug(
+            str(user_repos_name) + " "
+            + str(app.config["PERSISTENCE_CONFIG"]
+                            ["REPOSITORY_LIST"])
+        )
+        if not all((repo in user_repos_name)
+                   for repo in app.config["PERSISTENCE_CONFIG"]
+                                         ["REPOSITORY_LIST"]):
             session["user_can_edit"] = False
         logger.debug(session["user_can_edit"])
     except GitHubError as ghe:
@@ -554,9 +614,11 @@
     session["user_can_edit"] = None
     session["save_user_changes"] = None
     session["modified_categories"] = {
-        repo: {} for repo in app.config["REPOSITORY_LIST"]
+        repo: {} for repo in app.config["PERSISTENCE_CONFIG"]
+                                       ["REPOSITORY_LIST"]
     }
     session["deleted_categories"] = {
-        repo: {} for repo in app.config["REPOSITORY_LIST"]
+        repo: {} for repo in app.config["PERSISTENCE_CONFIG"]
+                                       ["REPOSITORY_LIST"]
     }
     return redirect(url_for('cat_index'))