diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 8809b27431d85da64c5001ea4bd6173065fc7bbf..2cc9ba94e3859389ea73168cbe0a903da212c7a2 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -220,12 +220,12 @@ pylint:
       - test/lint/pylint/requirements.txt
       - .gitlab-ci.yml
 
-#pylint-lint:
-#  stage: lint
-#  variables:
-#    GIT_STRATEGY: clone
-#    GIT_DEPTH: 0
-#    PYLINT_PLUGINS: "pylint_flask pylint_flask_sqlalchemy"
-#  image: ${CI_REGISTRY_IMAGE}/pylint:${CI_COMMIT_REF_NAME}
-#  script:
-#    - darker --check -i -L pylint --diff --revision remotes/origin/main .
+pylint-lint:
+  stage: lint
+  variables:
+    GIT_STRATEGY: clone
+    GIT_DEPTH: 0
+    PYLINT_PLUGINS: "pylint_flask pylint_flask_sqlalchemy"
+  image: ${CI_REGISTRY_IMAGE}/pylint:${CI_COMMIT_REF_NAME}
+  script:
+    - darker --check -i -L pylint --diff --revision remotes/origin/main .
diff --git a/login/app.py b/login/app.py
index fd3076439da8ded2f7d2b107cd8671935fca927d..ebb56e6b13d2353195f67ff22bb4b9d7e944dd03 100644
--- a/login/app.py
+++ b/login/app.py
@@ -25,19 +25,15 @@ import ory_kratos_client
 from ory_kratos_client.api import metadata_api
 from ory_kratos_client.api import v0alpha2_api as kratos_api
 from ory_kratos_client.model.generic_error import GenericError
-#from ory_kratos_client.model.inline_response200 import InlineResponse200
-#from ory_kratos_client.model.inline_response2001 import InlineResponse2001
-#from ory_kratos_client.model.inline_response503 import InlineResponse503
 
 from ory_kratos_client.model.admin_create_identity_body import AdminCreateIdentityBody
 from ory_kratos_client.model.admin_create_self_service_recovery_link_body import AdminCreateSelfServiceRecoveryLinkBody
-#from ory_kratos_client.model.submit_self_service_recovery_flow_body import SubmitSelfServiceRecoveryFlowBody
-#from ory_kratos_client.model.self_service_recovery_flow import SelfServiceRecoveryFlow
 
 from ory_kratos_client.model.identity_state import IdentityState
 
 from exceptions import BackendError
 
+from kratos import KratosUser
 
 
 # Initaliaze the FLASK app
@@ -154,6 +150,41 @@ app.cli.add_command(app_cli)
 
 
 ## CLI USER COMMANDS
+@user_cli.command('show')
+@click.argument('email')
+def show_user(email):
+    user = KratosUser.find_by_email(KRATOS_ADMIN, email)
+    print(user)
+    print("")
+    print(f"UUID:    {user.uuid}")
+    print(f"Updated: {user.updated_at}")
+    print(f"Created: {user.created_at}")
+    print(f"State:   {user.state}")
+
+@user_cli.command('updatename')
+@click.argument('email')
+@click.argument('name')
+def update_name_user(email, name):
+    user = KratosUser.find_by_email(KRATOS_ADMIN, email)
+    user.name = name
+    user.save()
+
+@user_cli.command('updateemail')
+@click.argument('email')
+@click.argument('newemail')
+def update_email_user(email, newemail):
+    user = KratosUser.find_by_email(KRATOS_ADMIN, email)
+    user.email = newemail
+    user.save()
+
+
+@user_cli.command('delete')
+@click.argument('email')
+def show_user(email):
+    user = KratosUser.find_by_email(KRATOS_ADMIN, email)
+    user.delete()
+
+
 
 @user_cli.command('create')
 @click.argument('email')
@@ -163,16 +194,22 @@ def create_user(email):
     obj = User()
     obj.email = email
 
-    # Trying to create idenity
-    try:
-        body = AdminCreateIdentityBody(
-            schema_id="default",
-            traits={'email':email},
-        ) # AdminCreateIdentityBody |  (optional)
-        kratos_obj = KRATOS_ADMIN.admin_create_identity(admin_create_identity_body=body)
-    except ory_kratos_client.exceptions.ApiException as err:
-        if err.status == 409:
-            print("Conflict during creation of user. User already exists?")
+    # Load kratos object
+    user = KratosUser(KRATOS_ADMIN)
+    user.email = email
+    user.save()
+    user = KratosUser(email)
+
+#    # Trying to create idenity
+#    try:
+#        body = AdminCreateIdentityBody(
+#            schema_id="default",
+#            traits={'email':email},
+#        ) # AdminCreateIdentityBody |  (optional)
+#        kratos_obj = KRATOS_ADMIN.admin_create_identity(admin_create_identity_body=body)
+#    except ory_kratos_client.exceptions.ApiException as err:
+#        if err.status == 409:
+#            print("Conflict during creation of user. User already exists?")
 
 
 
@@ -185,18 +222,8 @@ def create_user(email):
     #
     #  - After creating kratos user, check if success, otherwise throw warning.
 
-    body = AdminCreateIdentityBody(
-        schema_id="default",
-        traits={'email':email},
-    ) # AdminCreateIdentityBody |  (optional)
-
-        #state=IdentityState("active"),
-
-    kratos_obj = KRATOS_ADMIN.admin_create_identity(admin_create_identity_body=body)
-
-
-    obj.kratos_id = kratos_obj.id
 
+    obj.kratos_id = user.uuid
 
     db.session.add(obj)
 
@@ -208,9 +235,10 @@ def create_user(email):
 @click.argument('password')
 def setpassword_user(email, password):
     """Set a password for an account
-    :param: email    email address of account to set a password for
-    :param: password password to be set
-    :return: boolean true on success, if not set (too weak)
+    :param email:    email address of account to set a password for
+    :param password:  password to be set
+    :return:         true on success, false if not set (too weak)
+    :rtype: boolean
     :raise:          exception if unexepted error happens
     """
 
@@ -222,17 +250,16 @@ def setpassword_user(email, password):
     # admin interface (which is not e-mailed) and then follow the recovery
     # flow in the public facing pages of kratos
 
-    obj = User()
-
     try:
         # Get the ID of the user
-        kratos_id = obj.find_kratos_id(KRATOS_ADMIN, email)
+        kratos_user = KratosUser.find_by_email(KRATOS_ADMIN, email)
 
         # Get a recovery URL
-        url = obj.get_recovery_link(KRATOS_ADMIN, kratos_id)
+        url = kratos_user.get_recovery_link()
 
         # Execute UI sequence to set password, given we have a recovery URL
-        result = obj.ui_set_password(app.config["KRATOS_PUBLIC_URL"], url, password)
+        result = kratos_user.ui_set_password(app.config["KRATOS_PUBLIC_URL"], url, password)
+
     except BackendError as error:
         app.logger.error(f"Error while setting password: {error}")
         return False
@@ -249,15 +276,15 @@ def setpassword_user(email, password):
 @user_cli.command('list')
 def list_user():
     app.logger.info("Listing users")
-    users = User.query.all()
+    users = KratosUser.find_all(KRATOS_ADMIN)
 
     for obj in users:
-        print("Email: %s (admin: %s)" %(obj.email, obj.admin))
+        print(obj)
 
 
-@user_cli.command('delete',)
+@user_cli.command('delete2',)
 @click.argument('email')
-def delete_user(email):
+def delete2_user(email):
     app.logger.info("Trying to delete user: {0}".format(email))
     obj = User.query.filter_by(email=email).first()
 
diff --git a/login/exceptions.py b/login/exceptions.py
index ef723b537bfaeec3b4a79a87f764db861de869d7..4b0747a33ccf538f0bf5a87b361b6c86fb0235cb 100644
--- a/login/exceptions.py
+++ b/login/exceptions.py
@@ -1,4 +1,6 @@
 
 class BackendError(Exception):
-    """Base class for other exceptions"""
+    """The backend error is raised when interacting with
+    the backend fails or gives an unexpected result. The
+    error contains a oneliner description of the problem"""
     pass
diff --git a/login/kratos.py b/login/kratos.py
index 8e83eb839552e62e95b46510cd06e733700b4b91..57743858270b3ee940037e4590c879a5f7cb3dbe 100644
--- a/login/kratos.py
+++ b/login/kratos.py
@@ -17,8 +17,8 @@ from sqlalchemy import Integer, String, ForeignKey, Boolean
 # Some imports commented out to satisfy pylint. They will be used once more
 # functions are migrated to this model
 #
-#from ory_kratos_client.model.admin_create_identity_body \
-#    import AdminCreateIdentityBody
+from ory_kratos_client.model.admin_create_identity_body \
+    import AdminCreateIdentityBody
 from ory_kratos_client.model.admin_update_identity_body \
     import AdminUpdateIdentityBody
 
@@ -75,6 +75,10 @@ class KratosUser():
 
 
     def save(self):
+
+        # Kratos API expect for state an IdentifyState object, while
+        # during updating, it expects a string. 
+
         if self.uuid:
             body = AdminUpdateIdentityBody(
                 schema_id="default",
@@ -88,15 +92,21 @@ class KratosUser():
             except ory_kratos_client.ApiException as e:
                 print("Exception when calling V0alpha2Api->admin_update_identity: %s\n" % e)
         else:
+            traits = {'email':self.email}
+
+            if self.name:
+                traits['name'] = self.name
+
             body = AdminCreateIdentityBody(
                 schema_id="default",
-                state=self.state,
-                traits={'email':self.email, 'name':self.name},
+                traits=traits
             )
             try:
-                # Update an Identity
-                api_response = self.api.admin_create_identity(self.uuid,
+                # Create an Identity
+                api_response = self.api.admin_create_identity(
                         admin_create_identity_body=body)
+                if api_response.id:
+                    self.uuid = api_response.id
             except ory_kratos_client.ApiException as e:
                 print("Exception when calling V0alpha2Api->admin_update_identity: %s\n" % e)
 
diff --git a/login/models.py b/login/models.py
index 502b710663704a7b374c5bd96930318841a5e576..933c270dac2e039ceae90166b256283612103e68 100644
--- a/login/models.py
+++ b/login/models.py
@@ -82,173 +82,6 @@ class User(db.Model):
 
         return dict(id_token=token)
 
-    @staticmethod
-    def find_kratos_id(api, email):
-        """Queries Kratos to find kratos ID for this given identifier
-        :param: api Kratos ADMIN API Object
-        :param: email Identifier to look for
-        :return: Return none or string with ID
-        """
-
-        kratos_id = None
-
-        # Get out user ID by iterating over all available IDs
-        data = api.admin_list_identities()
-        for kratos_obj in data.value:
-            # Unique identifier we use
-            if kratos_obj.traits['email'] == email:
-                kratos_id = str(kratos_obj.id)
-
-        return kratos_id
-
-
-    @staticmethod
-    def get_recovery_link(api, kratos_id):
-        """Call the kratos API to create a recovery URL for a kratos ID
-        :param: api Kratos ADMIN API Object
-        :param: kratos_id UUID of kratos object
-        :return: Return none or string with recovery URL
-        """
-
-        try:
-            # Create body request to get recovery link with admin API
-            body = AdminCreateSelfServiceRecoveryLinkBody(
-                expires_in="15m",
-                identity_id=str(kratos_id)
-            )
-
-            # Get recovery link from admin API
-            call = api.admin_create_self_service_recovery_link(
-                admin_create_self_service_recovery_link_body=body)
-
-            url = call.recovery_link
-        except KratosApiException:
-            return None
-        return url
-
-
-    @staticmethod
-    def extract_cookies(cookies):
-        """Extract session and CSRF cookie from a list of cookies.
-
-        Iterate over a list of cookies and extract the session
-        cookies required for Kratos User Panel UI
-
-        :param: cookies List of cookies
-        :return: string Cookies as string
-        """
-
-        # Find kratos session cookie & csrf
-        cookie_csrf = None
-        cookie_session = None
-        for cookie in cookies:
-            search = re.match(r'ory_kratos_session=([^;]*);.*$', cookie)
-            if search:
-                cookie_session = "ory_kratos_session=" + search.group(1)
-            search = re.match(r'(csrf_token[^;]*);.*$', cookie)
-            if search:
-                cookie_csrf = search.group(1)
-
-        if not cookie_csrf or not cookie_session:
-            raise BackendError("Flow started, but expected cookies not found")
-
-        # Combined the relevant cookies
-        cookie = cookie_csrf + "; " + cookie_session
-        return cookie
-
-    def ui_set_password(self, api_url, recovery_url, password):
-        """Follow a Kratos UI sequence to set password
-        Kratos does not provide an interface to set a password directly. However
-        we still can set a password by following the UI sequence. To so so we
-        to follow the steps which are normally done in a browser once someone
-        clicks the recovery link.
-        :param: api_url      URL to public endpoint of API
-        :param: recovery_url Recovery URL as generated by Kratos
-        :param: password     Password
-        :raise:              Exception with error message as first argument
-        :return: boolen      True on success, False on failure (usualy password
-                             to simple)
-        """
-
-        # Step 1: Open the recovery link and extract the cookies, as we need them
-        #         for the next steps
-        try:
-            # We override the default Redirect handler with our custom handler to
-            # be able to catch the cookies.
-            opener = urllib.request.build_opener(RedirectFilter)
-            opener.open(recovery_url)
-        # If we do not have a 2xx status, urllib throws an error, as we "stopped"
-        # at our redirect, we expect a 3xx status
-        except urllib.error.HTTPError as req:
-            if req.status == 302:
-                cookies = req.headers.get_all('Set-Cookie')
-                url =  req.headers.get('Location')
-            else:
-                raise BackendError('Unable to fetch recovery link') from req
-        else:
-            raise BackendError('Unable to fetch recovery link')
-
-        # Step 2: Extract cookies and data for next step. We expect to have an
-        #         authorized session now. We need the cookies for followup calls
-        #         to make changes to the account (set password)
-
-        # Get flow id
-        search = re.match(r'.*\?flow=(.*)', url)
-        if search:
-            flow = search.group(1)
-        else:
-            raise BackendError('No Flow ID found for recovery sequence')
-
-        # Extract cookies with helper function
-        cookie = self.extract_cookies(cookies)
-
-        # Step 3: Get the "UI", kratos expect us to call the API to get the UI
-        #         elements which inclused the CSRF token, which is needed when
-        #         posting the password data
-        try:
-            url = api_url + "/self-service/settings/flows?id=" + flow
-
-            req = Request(url, headers={'Cookie':cookie})
-            opener = urllib.request.build_opener()
-
-            # Execute the request, read the data, decode the JSON, get the
-            # right CSRF token out of the decoded JSON
-            obj = json.loads(opener.open(req).read())
-            token = obj['ui']['nodes'][0]['attributes']['value']
-
-        except Exception as error:
-            raise BackendError("Unable to get password reset UI") from error
-
-
-        # Step 4: Post out password
-        url = api_url + "self-service/settings?flow=" + flow
-
-        # Create POST data as form data
-        data = {
-            'method': 'password',
-            'password': password,
-            'csrf_token': token
-        }
-        data = urllib.parse.urlencode(data)
-        data = data.encode('ascii')
-
-        # POST the new password
-        try:
-            req = Request(url, data = data, headers={'Cookie':cookie}, method="POST")
-            opener = urllib.request.build_opener(RedirectFilter)
-            opener.open(req)
-            # If we do not have a 2xx status, urllib throws an error, as we "stopped"
-            # at our redirect, we expect a 3xx status
-        except urllib.error.HTTPError as req:
-            if req.status == 302:
-                return True
-            if req.status == 303:
-                # Something went wrong, usuall because the password is too
-                # simple. Kratos does not give a proper hint about the
-                # underlying error
-                return False
-        raise BackendError("Unable to set password by submitting form")
-
 
 # Pylint complains about too-few-public-methods. Methods will be added once
 # this is implemented.