diff --git a/.dockerignore b/.dockerignore
index 40b878db5b1c97fc77049537a71bb2e249abe5dc..dea15c8ebc8f82a9ab7f47a1e164c92860d9e5eb 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -1 +1,7 @@
-node_modules/
\ No newline at end of file
+node_modules/
+__tests__/
+jest*
+*.log
+*.env*
+.dockerignore
+.gitignore
diff --git a/.env.development b/.env.development
new file mode 100644
index 0000000000000000000000000000000000000000..4e952694681366c56d97f30f301859516d5c0146
--- /dev/null
+++ b/.env.development
@@ -0,0 +1,33 @@
+NODE_ENV=development
+PROCESS_TYPE=web
+PORT=4000
+LOG_LEVEL=debug
+
+KEYCLOAK_HOST=
+KEYCLOAK_PORT=
+KEYCLOAK_USER=
+KEYCLOAK_PASSWORD=
+KEYCLOAK_GRANT_TYPE=
+KEYCLOAK_REALM=
+KEYCLOAK_SERVER_URL=
+KEYCLOAK_CLIENT_ID=
+KEYCLOAK_CREDENTIALS_SECRET=
+KEYCLOAK_SERVER_PUBLIC_KEY=
+
+DB_HOST=
+DB_USER=
+DB_PASSWORD=
+DB_DATABASE=
+DB_PORT=
+
+IN_SYLVA_EMAIL=
+IN_SYLVA_EMAIL_PASSWORD=
+IN_SYLVA_SMTP_HOST=
+IN_SYLVA_SMTP_PORT=
+IN_SYLVA_EMAIL_FROM=
+IN_SYLVA_EMAIL_TO=
+IN_SYLVA_ADMIN_USERNAME=
+IN_SYLVA_ADMIN_PASSWORD=
+
+BOT_SERVICE_TOKEN=
+BOT_SERVICE_CHANNEL=
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
index fcfc329338b1ab467dede15212ea558d75bd4096..ef33cbda12f2f00dbda46e0eaafb88e99dd37189 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,28 +1,25 @@
-FROM node:14-buster-slim
+FROM node:20.16.0
 
-RUN apt update && apt install -y git openssh-client
+# Update the package list and install packages
+RUN wget -qO- https://www.mongodb.org/static/pgp/server-8.0.asc | tee /etc/apt/trusted.gpg.d/server-8.0.asc
+RUN echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/8.0 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-8.0.list
 
-RUN npm install --global pm2
+RUN apt-get update && apt-get install -y git mongodb-mongosh && rm -rf /var/lib/apt/lists/*
 
-EXPOSE 22 
 
-ARG SSH_KEY
-ARG SSH_KEY_PASSPHRASE
-RUN chmod go-w /root
+# Install PM2
+RUN yarn global add pm2
 
-RUN mkdir -p /root/.ssh && \
-    chmod 600 /root/.ssh 
+# Set up the app
+WORKDIR /app
+COPY package.json ./
 
-RUN echo "$SSH_KEY" >> /root/.ssh/id_rsa && \
-     echo "$SSH_KEY_PASSPHRASE" >> /root/.ssh/id_rsa.pub 
+# Install dependencies
+RUN yarn install
 
-RUN chmod -R 600 /root/.ssh/id_rsa && \
-     chmod -R 600 /root/.ssh/id_rsa.pub 
+# Copy the rest of the application code
+COPY . .
 
-RUN ssh-keyscan -Ht rsa forgemia.inra.fr,147.100.164.13 >> ~/.ssh/known_hosts
-
-COPY . /app
-
-RUN cd /app && yarn
+ENTRYPOINT [ "/bin/bash", "./entrypoint.sh"]
 
 CMD [ "pm2-runtime","--name","in-sylva.gatekeeper", "yarn start:prod"]
diff --git a/__test__/models/group.test.js b/__test__/models/group.test.js
deleted file mode 100644
index d5fbb110f574adb1a8bebb3f30d23adfd581743c..0000000000000000000000000000000000000000
--- a/__test__/models/group.test.js
+++ /dev/null
@@ -1,31 +0,0 @@
-'use strict'
-
-const { Group, GroupsPolicy, GroupUser } = require('../../app/models/Group')
-
-describe("Testing 1Group entitiy", () => {
-    it('Insert new Group', async () => {
-        await Group.create({
-            name: "Test name for the Group 2.",
-            name: "Test description for the Group 2.",
-            user_id: 1
-        })
-    })
-})
-
-describe("Testing 2GroupsPolicy entity", () => {
-    it("Insert new GroupsPolicy", async () => {
-        await GroupsPolicy.create({
-            group_id: 1,
-            policy_id: 1
-        })
-    })
-})
-
-describe("Testing 3GroupUser entity", () => {
-    it("Insert new GroupUser", async () => {
-        await GroupUser.create({
-            group_id: 1,
-            user_id: 1
-        })
-    })
-})
\ No newline at end of file
diff --git a/__test__/models/policy.test.js b/__test__/models/policy.test.js
deleted file mode 100644
index 2a2b7acd00c6640426e71d2a036ffb0ab223eb6c..0000000000000000000000000000000000000000
--- a/__test__/models/policy.test.js
+++ /dev/null
@@ -1,21 +0,0 @@
-'use strict'
-
-const { Policy } = require('../../app/models/Policy')
-
-describe("Testing Policy entity", () => {
-    it("Insert new Policy", async () => {
-        await Policy.create({
-            name: "New Policy",
-            source_id: 1,
-            is_default: false,
-            user_id: 1
-        })
-    })
-})
-
-
-describe("Testing FPolicy entity", () => {
-    it("Fetch new FPolicies", async () => {
-
-    })
-})
\ No newline at end of file
diff --git a/__test__/models/policyField.test.js b/__test__/models/policyField.test.js
deleted file mode 100644
index 7d08aea17e4bdf21f1e40927016d56edb413581b..0000000000000000000000000000000000000000
--- a/__test__/models/policyField.test.js
+++ /dev/null
@@ -1,13 +0,0 @@
-'use strict'
-
-const { PolicyField } = require('../../app/models/Policy')
-
-describe('Testing CPolicyField entity', () => {
-    it("Insert new PolicyField", async () => {
-
-        await PolicyField.create({
-            policy_id: 1,
-            std_field_id: 1
-        })
-    })
-})
\ No newline at end of file
diff --git a/__test__/models/role.test.js b/__test__/models/role.test.js
deleted file mode 100644
index 5909d0f4582fc2b2d71d3cb3997cece6f517993a..0000000000000000000000000000000000000000
--- a/__test__/models/role.test.js
+++ /dev/null
@@ -1,24 +0,0 @@
-'use strict'
-const { Role, RoleUser } = require('../../app/models/Role')
-
-describe("Testing Role entity", () => {
-
-    it("Delete roles", async () => {
-        await Role.destroy()
-    }),
-
-        it("Insert new Role", async () => {
-            await Role.create({
-                name: "admin",
-                description: "admin description"
-            })
-        })
-
-    it("Insert new CRoleUser", async () => {
-        await RoleUser.create({
-            role_id: 1,
-            kc_id: "3026ee0c-e1d3-4ce8-9289-2507ef797523"
-        })
-    })
-
-})  
\ No newline at end of file
diff --git a/__test__/models/searchHistory.test.js b/__test__/models/searchHistory.test.js
deleted file mode 100644
index 624678769f034b5eb3532ae49d29ca4b05bfd877..0000000000000000000000000000000000000000
--- a/__test__/models/searchHistory.test.js
+++ /dev/null
@@ -1,44 +0,0 @@
-'use strict'
-
-const { SearchHistory } = require('../../app/models/UserHistory')
-
-describe("Testing searchHistory entity with Sequelize orm", () => {
-
-    it("Insert new searchHistory", async () => {
-        await SearchHistory.create({
-            kc_id: "fe3b88e4-a231-47a2-9d9e-18bd9be0d637",
-            query: "query test",
-            name: "name test",
-            ui_structure: "ui_structure",
-            description: "description test"
-        }).then(c => {
-            return c
-        })
-    })
-
-
-    /*it("test findAll searchHistories", async () => {
-
-        const sHistories = await SearchHistory.findAll({
-            where: {
-                kc_id: "fe3b88e4-a231-47a2-9d9e-18bd9be0d637"
-            }
-        })
-
-        console.log(typeof sHistories)
-        expect(sHistories.length > 0)
-    }) */
-    /*
-    it("test delete searchHistory", async () => {
-        const result = await SearchHistory.destroy({
-            where: {
-                id:'1'
-            }
-        })
-        
-        console.log(result)
-    }) */
-
-})
-
-
diff --git a/__test__/models/source.test.js b/__test__/models/source.test.js
deleted file mode 100644
index 692e8639d8aef99117dc9a167e5723e6ee21b7a5..0000000000000000000000000000000000000000
--- a/__test__/models/source.test.js
+++ /dev/null
@@ -1,13 +0,0 @@
-'use strict'
-
-const { Source } = require('../../app/models/Source')
-
-describe("Testing Source entity", () => {
-    it('insert new Source', async () => {
-        await Source.create({
-            name: "test source name 2",
-            description : "test source description"
-        })
-    })
-})
-
diff --git a/__test__/models/stdField.test.js b/__test__/models/stdField.test.js
deleted file mode 100644
index 135fc55634c4436b8564c09246a89b944f048bd1..0000000000000000000000000000000000000000
--- a/__test__/models/stdField.test.js
+++ /dev/null
@@ -1,21 +0,0 @@
-'use strict'
-
-const {StdField } = require('../../app/models/StdField')
-
-describe('Testing StdField entity', () => {
-    it("insert StdField entity", async () => {
-        await StdField.create({
-            category: "category",
-            field_name: "field_name", 
-            definition_and_comment: "definition_and_comment", 
-            obligation_or_condition: "obligation_or_condition",
-            cardinality: "cardinality",
-            field_type:"field_type", 
-            values:"values", 
-            ispublic: true,
-            isoptional: false
-        }).then(c => {
-            return c
-        })
-    })
-})
\ No newline at end of file
diff --git a/__tests__/api/groups/get.test.js b/__tests__/api/groups/get.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..f38c99127a0244578fc3ecfa7a78675540778bda
--- /dev/null
+++ b/__tests__/api/groups/get.test.js
@@ -0,0 +1,88 @@
+const {
+  getGroupHandler,
+  getAllGroupsHandler,
+} = require("@/app/api/groups/get");
+const { getAllGroups, getGroup } = require("@/app/dal/groupService");
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+
+jest.mock("@/app/dal/groupService");
+jest.mock("@/app/utils/errorHandler");
+
+describe("getGroupHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      params: {},
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when id is missing", async () => {
+    await getGroupHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(["id"], ctx);
+  });
+
+  it("should get group and set status to 200", async () => {
+    ctx.params.id = "group123";
+    const mockResponse = { id: "group123", name: "Test Group" };
+    getGroup.mockResolvedValue(mockResponse);
+
+    await getGroupHandler(ctx);
+
+    expect(ctx.body).toEqual(mockResponse);
+    expect(ctx.status).toBe(200);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.params.id = "group123";
+    getGroup.mockImplementation(() => {
+      throw error;
+    });
+
+    await getGroupHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
+
+describe("getAllGroupsHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should get all groups and set status to 200", async () => {
+    const mockResponse = [
+      { id: 1, name: "Group 1" },
+      { id: 2, name: "Group 2" },
+    ];
+    getAllGroups.mockResolvedValue(mockResponse);
+
+    await getAllGroupsHandler(ctx);
+
+    expect(ctx.body).toEqual(mockResponse);
+    expect(ctx.status).toBe(200);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    getAllGroups.mockImplementation(() => {
+      throw error;
+    });
+
+    await getAllGroupsHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
diff --git a/__tests__/api/groups/post.test.js b/__tests__/api/groups/post.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..d1ee165bd869fad2911652e5ad5ca2c67444e0a3
--- /dev/null
+++ b/__tests__/api/groups/post.test.js
@@ -0,0 +1,67 @@
+const { createGroupHandler } = require("@/app/api/groups/post");
+const { createGroup } = require("@/app/dal/groupService");
+const {
+  handleMissingParameters,
+  handleInternalError,
+} = require("@/app/utils/errorHandler");
+
+jest.mock("@/app/dal/groupService");
+jest.mock("@/app/utils/errorHandler");
+
+describe("createGroupHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      request: {
+        body: {},
+      },
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when name, description, or kc_id is missing", async () => {
+    await createGroupHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(
+      ["name", "description", "kc_id"],
+      ctx
+    );
+  });
+
+  it("should create group and set status to 201", async () => {
+    ctx.request.body = {
+      name: "Test Group",
+      description: "Test Description",
+      kc_id: "kc123",
+    };
+    const mockResponse = {
+      id: 1,
+      name: "Test Group",
+      description: "Test Description",
+    };
+    createGroup.mockResolvedValue(mockResponse);
+
+    await createGroupHandler(ctx);
+
+    expect(ctx.body).toEqual(mockResponse);
+    expect(ctx.status).toBe(201);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.request.body = {
+      name: "Test Group",
+      description: "Test Description",
+      kc_id: "kc123",
+    };
+    createGroup.mockImplementation(() => {
+      throw error;
+    });
+
+    await createGroupHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
diff --git a/__tests__/api/groups/update.test.js b/__tests__/api/groups/update.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..672c030bc7ecaf547984cdc8d99cecbba14cf8bb
--- /dev/null
+++ b/__tests__/api/groups/update.test.js
@@ -0,0 +1,227 @@
+// update.test.js
+
+const {
+  updateGroupHandler,
+  addUserToGroupHandler,
+  removeUserFromGroupHandler,
+  addPolicyToGroupHandler,
+} = require("@/app/api/groups/update");
+const {
+  createGroup,
+  addUserToGroup,
+  removeUserFromGroup,
+  addPolicyToGroup,
+  updateGroup,
+} = require("@/app/dal/groupService");
+const {
+  handleMissingParameters,
+  handleInternalError,
+} = require("@/app/utils/errorHandler");
+
+jest.mock("@/app/dal/groupService");
+jest.mock("@/app/utils/errorHandler");
+
+describe("updateGroupHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      params: {},
+      request: {
+        body: {},
+      },
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when name, description, or id is missing", async () => {
+    await updateGroupHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(
+      ["name", "description", "id"],
+      ctx
+    );
+  });
+
+  it("should update group and set status to 201", async () => {
+    ctx.params.id = "group123";
+    ctx.request.body = {
+      name: "Updated Group",
+      description: "Updated Description",
+    };
+    const mockResponse = {
+      id: "group123",
+      name: "Updated Group",
+      description: "Updated Description",
+    };
+    updateGroup.mockResolvedValue(mockResponse);
+
+    await updateGroupHandler(ctx);
+
+    expect(ctx.body).toEqual(mockResponse);
+    expect(ctx.status).toBe(200);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.params.id = "group123";
+    ctx.request.body = {
+      name: "Updated Group",
+      description: "Updated Description",
+    };
+    updateGroup.mockImplementation(() => {
+      throw error;
+    });
+
+    await updateGroupHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
+
+describe("addUserToGroupHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      params: {},
+      request: {
+        body: {},
+      },
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when kc_id or groupId is missing", async () => {
+    await addUserToGroupHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(["kc_id", "id"], ctx);
+  });
+
+  it("should add user to group and set status to 201", async () => {
+    ctx.params.id = "group123";
+    ctx.request.body = {
+      kc_id: "kc123",
+    };
+    const mockResponse = { kc_id: "kc123", groupId: "group123" };
+    addUserToGroup.mockResolvedValue(mockResponse);
+
+    await addUserToGroupHandler(ctx);
+
+    expect(ctx.body).toEqual(mockResponse);
+    expect(ctx.status).toBe(201);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.params.id = "group123";
+    ctx.request.body = {
+      kc_id: "kc123",
+    };
+    addUserToGroup.mockImplementation(() => {
+      throw error;
+    });
+
+    await addUserToGroupHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
+
+describe("removeUserFromGroupHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      params: {},
+      request: {
+        body: {},
+      },
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when kc_id or id is missing", async () => {
+    await removeUserFromGroupHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(["kc_id", "id"], ctx);
+  });
+
+  it("should remove user from group and set status to 204", async () => {
+    ctx.params = { kc_id: "kc123", id: "group123" };
+    removeUserFromGroup.mockResolvedValue({});
+
+    await removeUserFromGroupHandler(ctx);
+
+    expect(ctx.body).toEqual(null);
+    expect(ctx.status).toBe(204);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.params = { kc_id: "kc123", id: "group123" };
+    removeUserFromGroup.mockImplementation(() => {
+      throw error;
+    });
+
+    await removeUserFromGroupHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
+
+describe("addPolicyToGroupHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      params: {},
+      request: {
+        body: {},
+      },
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when policy_id or id is missing", async () => {
+    await addPolicyToGroupHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(
+      ["policy_id", "id"],
+      ctx
+    );
+  });
+
+  it("should add policy to group and set status to 201", async () => {
+    ctx.params.id = "group123";
+    ctx.request.body = {
+      policy_id: "policy123",
+    };
+    const mockResponse = { policy_id: "policy123", group_id: "group123" };
+    addPolicyToGroup.mockResolvedValue(mockResponse);
+
+    await addPolicyToGroupHandler(ctx);
+
+    expect(ctx.body).toEqual(mockResponse);
+    expect(ctx.status).toBe(201);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.params.id = "group123";
+    ctx.request.body = {
+      policy_id: "policy123",
+    };
+    addPolicyToGroup.mockImplementation(() => {
+      throw error;
+    });
+
+    await addPolicyToGroupHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
diff --git a/__tests__/api/policies/delete.test.js b/__tests__/api/policies/delete.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..90173888931a78889f7f4565521f71606f1d81a3
--- /dev/null
+++ b/__tests__/api/policies/delete.test.js
@@ -0,0 +1,51 @@
+// delete.test.js
+
+const { deletePolicyHandler } = require("@/app/api/policies/delete");
+const { deletePolicy } = require("@/app/dal/policyService");
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+
+jest.mock("@/app/dal/policyService");
+jest.mock("@/app/utils/errorHandler");
+
+describe("deletePolicyHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      params: {},
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when id is missing", async () => {
+    await deletePolicyHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(["id"], ctx);
+  });
+
+  it("should delete policy and set status to 204", async () => {
+    ctx.params.id = "policy123";
+    deletePolicy.mockResolvedValue(null);
+
+    await deletePolicyHandler(ctx);
+
+    expect(ctx.body).toBeNull();
+    expect(ctx.status).toBe(204);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.params.id = "policy123";
+    deletePolicy.mockImplementation(() => {
+      throw error;
+    });
+
+    await deletePolicyHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
diff --git a/__tests__/api/policies/get.test.js b/__tests__/api/policies/get.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..12553e5916f78074dce653574c7a15a6accfa977
--- /dev/null
+++ b/__tests__/api/policies/get.test.js
@@ -0,0 +1,88 @@
+const {
+  getAllPoliciesHandler,
+  getPolicyHandler,
+} = require("@/app/api/policies/get");
+const { getAllPolicies, getPolicy } = require("@/app/dal/policyService");
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+
+jest.mock("@/app/dal/policyService");
+jest.mock("@/app/utils/errorHandler");
+
+describe("getAllPoliciesHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should get all policies and set status to 200", async () => {
+    const mockResponse = [
+      { id: 1, name: "Policy 1" },
+      { id: 2, name: "Policy 2" },
+    ];
+    getAllPolicies.mockResolvedValue(mockResponse);
+
+    await getAllPoliciesHandler(ctx);
+
+    expect(ctx.body).toEqual(mockResponse);
+    expect(ctx.status).toBe(200);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    getAllPolicies.mockImplementation(() => {
+      throw error;
+    });
+
+    await getAllPoliciesHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
+
+describe("getPolicyHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      params: {},
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when id is missing", async () => {
+    await getPolicyHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(["id"], ctx);
+  });
+
+  it("should get policy and set status to 200", async () => {
+    ctx.params.id = "policy123";
+    const mockResponse = { id: "policy123", name: "Test Policy" };
+    getPolicy.mockResolvedValue(mockResponse);
+
+    await getPolicyHandler(ctx);
+
+    expect(ctx.body).toEqual(mockResponse);
+    expect(ctx.status).toBe(200);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.params.id = "policy123";
+    getPolicy.mockImplementation(() => {
+      throw error;
+    });
+
+    await getPolicyHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
diff --git a/__tests__/api/policies/post.test.js b/__tests__/api/policies/post.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..72dc9d2d74c0b1436c9ea1d105f35ef56225474d
--- /dev/null
+++ b/__tests__/api/policies/post.test.js
@@ -0,0 +1,66 @@
+const { createPolicyHandler } = require("@/app/api/policies/post");
+const { createPolicy } = require("@/app/dal/policyService");
+const {
+  handleMissingParameters,
+  handleInternalError,
+} = require("@/app/utils/errorHandler");
+
+jest.mock("@/app/dal/policyService");
+jest.mock("@/app/utils/errorHandler");
+
+describe("createPolicyHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      request: {
+        body: {},
+      },
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when name, source_id, or kc_id is missing", async () => {
+    await createPolicyHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(
+      ["name", "kc_id"],
+      ctx
+    );
+  });
+
+  it("should create policy and set status to 201", async () => {
+    ctx.request.body = {
+      name: "Test Policy",
+      kc_id: "kc123",
+    };
+    const mockResponse = {
+      id: 1,
+      name: "Test Policy",
+      kc_id: "kc123",
+    };
+    createPolicy.mockResolvedValue(mockResponse);
+
+    await createPolicyHandler(ctx);
+
+    expect(ctx.body).toEqual(mockResponse);
+    expect(ctx.status).toBe(201);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.request.body = {
+      name: "Test Policy",
+      source_id: "source123",
+      kc_id: "kc123",
+    };
+    createPolicy.mockImplementation(() => {
+      throw error;
+    });
+
+    await createPolicyHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
diff --git a/__tests__/api/policies/update.test.js b/__tests__/api/policies/update.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..455782f3bfa23e3af3f0c7f0433777f66b6fa54e
--- /dev/null
+++ b/__tests__/api/policies/update.test.js
@@ -0,0 +1,271 @@
+// update.test.js
+
+const {
+  updatePolicyHandler,
+  addFieldToPolicyHandler,
+  removeFieldFromPolicyHandler,
+  addSourceToPolicyHandler,
+  removeSourceFromPolicyHandler,
+} = require("@/app/api/policies/update");
+const {
+  updatePolicy,
+  addFieldToPolicy,
+  removeFieldFromPolicy,
+  addSourceToPolicy,
+  removeSourceFromPolicy,
+} = require("@/app/dal/policyService");
+const {
+  handleMissingParameters,
+  handleInternalError,
+} = require("@/app/utils/errorHandler");
+
+jest.mock("@/app/dal/policyService");
+jest.mock("@/app/utils/errorHandler");
+
+describe("updatePolicyHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      request: {
+        body: {},
+      },
+      params: {},
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when id, name, or isDefault is missing", async () => {
+    await updatePolicyHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(
+      ["id", "name", "isDefault"],
+      ctx
+    );
+  });
+
+  it("should update policy and set status to 204", async () => {
+    ctx.params.id = "policy123";
+    ctx.request.body = {
+      name: "Updated Policy",
+      isDefault: true,
+    };
+    const mockResponse = {
+      id: "policy123",
+      name: "Updated Policy",
+      isDefault: true,
+    };
+    updatePolicy.mockResolvedValue(mockResponse);
+
+    await updatePolicyHandler(ctx);
+
+    expect(ctx.body).toEqual(mockResponse);
+    expect(ctx.status).toBe(204);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.params.id = "policy123";
+    ctx.request.body = {
+      name: "Updated Policy",
+      isDefault: true,
+    };
+    updatePolicy.mockImplementation(() => {
+      throw error;
+    });
+
+    await updatePolicyHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
+
+describe("addFieldToPolicyHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      params: {},
+      request: {
+        body: {},
+      },
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when id or field_id is missing", async () => {
+    await addFieldToPolicyHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(
+      ["id", "field_id"],
+      ctx
+    );
+  });
+
+  it("should add field to policy and set status to 201", async () => {
+    ctx.params.id = "policy123";
+    ctx.request.body.field_id = "field123";
+    const mockResponse = { success: true };
+    addFieldToPolicy.mockResolvedValue(mockResponse);
+
+    await addFieldToPolicyHandler(ctx);
+
+    expect(ctx.body).toEqual(mockResponse);
+    expect(ctx.status).toBe(201);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.params.id = "policy123";
+    ctx.request.body.field_id = "field123";
+    addFieldToPolicy.mockImplementation(() => {
+      throw error;
+    });
+
+    await addFieldToPolicyHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
+
+describe("removeFieldFromPolicyHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      params: {},
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when id or policy_id is missing", async () => {
+    await removeFieldFromPolicyHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(
+      ["id", "field_id"],
+      ctx
+    );
+  });
+
+  it("should remove field from policy and set status to 204", async () => {
+    ctx.params.id = "policy123";
+    ctx.params.field_id = "field123";
+    const mockResponse = { success: true };
+    removeFieldFromPolicy.mockResolvedValue(mockResponse);
+
+    await removeFieldFromPolicyHandler(ctx);
+
+    expect(ctx.status).toBe(204);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.params.id = "policy123";
+    ctx.params.field_id = "field123";
+    removeFieldFromPolicy.mockImplementation(() => {
+      throw error;
+    });
+
+    await removeFieldFromPolicyHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
+
+describe("addSourceToPolicyHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      params: {},
+      request: {
+        body: {},
+      },
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when id or source_id is missing", async () => {
+    await addSourceToPolicyHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(
+      ["id", "source_id"],
+      ctx
+    );
+  });
+
+  it("should add source to policy and set status to 201", async () => {
+    ctx.params.id = "policy123";
+    ctx.request.body.source_id = "source123";
+    const mockResponse = { success: true };
+    addSourceToPolicy.mockResolvedValue(mockResponse);
+
+    await addSourceToPolicyHandler(ctx);
+
+    expect(ctx.body).toEqual(mockResponse);
+    expect(ctx.status).toBe(201);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.params.id = "policy123";
+    ctx.request.body.source_id = "source123";
+    addSourceToPolicy.mockImplementation(() => {
+      throw error;
+    });
+
+    await addSourceToPolicyHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
+
+describe("removeSourceFromPolicyHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      params: {},
+      request: {
+        body: {},
+      },
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when id or source_id is missing", async () => {
+    await removeSourceFromPolicyHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(
+      ["id", "source_id"],
+      ctx
+    );
+  });
+
+  it("should add source to policy and set status to 201", async () => {
+    ctx.params = { id: "policy123", source_id: "source123" };
+    removeSourceFromPolicy.mockResolvedValue(null);
+
+    await removeSourceFromPolicyHandler(ctx);
+
+    expect(ctx.body).toEqual(null);
+    expect(ctx.status).toBe(204);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.params = { id: "policy123", source_id: "source123" };
+    removeSourceFromPolicy.mockImplementation(() => {
+      throw error;
+    });
+
+    await removeSourceFromPolicyHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
diff --git a/__tests__/api/roles/delete.test.js b/__tests__/api/roles/delete.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..be4c9aa23b841257f20d3ba78a8a2b5d791e9930
--- /dev/null
+++ b/__tests__/api/roles/delete.test.js
@@ -0,0 +1,49 @@
+const { deleteRoleHandler } = require("@/app/api/roles/delete");
+const { deleteRole } = require("@/app/dal/roleService");
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+
+jest.mock("@/app/dal/roleService");
+jest.mock("@/app/utils/errorHandler");
+
+describe("deleteRoleHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      params: {},
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when id is missing", async () => {
+    await deleteRoleHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(["id"], ctx);
+  });
+
+  it("should delete role and set status to 204", async () => {
+    ctx.params.id = "role123";
+    deleteRole.mockResolvedValue(null);
+
+    await deleteRoleHandler(ctx);
+
+    expect(ctx.body).toBeNull();
+    expect(ctx.status).toBe(204);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.params.id = "role123";
+    deleteRole.mockImplementation(() => {
+      throw error;
+    });
+
+    await deleteRoleHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
diff --git a/__tests__/api/roles/get.test.js b/__tests__/api/roles/get.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..f31ac4c1ac66989ebba76fd8218bd983acf50002
--- /dev/null
+++ b/__tests__/api/roles/get.test.js
@@ -0,0 +1,132 @@
+const {
+  getRolesHandler,
+  getRoleHandler,
+  getUserRolesHandler,
+} = require("@/app/api/roles/get");
+const { getRoles, getRole, getUserRoles } = require("@/app/dal/roleService");
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+
+jest.mock("@/app/dal/roleService");
+jest.mock("@/app/utils/errorHandler");
+
+describe("getRolesHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should get roles and set status to 200", async () => {
+    const mockResponse = [{ id: "role1" }, { id: "role2" }];
+    getRoles.mockResolvedValue(mockResponse);
+
+    await getRolesHandler(ctx);
+
+    expect(ctx.body).toEqual(mockResponse);
+    expect(ctx.status).toBe(200);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    getRoles.mockImplementation(() => {
+      throw error;
+    });
+
+    await getRolesHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
+
+describe("getRoleHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      params: {},
+      request: {
+        body: {},
+      },
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when id is missing", async () => {
+    await getRoleHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(["id"], ctx);
+  });
+
+  it("should get role by id and set status to 200", async () => {
+    ctx.params.id = "role123";
+    const mockResponse = { id: "role123", name: "Role Name" };
+    getRole.mockResolvedValue(mockResponse);
+
+    await getRoleHandler(ctx);
+
+    expect(ctx.body).toEqual(mockResponse);
+    expect(ctx.status).toBe(200);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.params.id = "role123";
+    getRole.mockImplementation(() => {
+      throw error;
+    });
+
+    await getRoleHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
+
+describe("getUserRolesHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      request: {
+        body: {},
+      },
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when kc_id is missing", async () => {
+    await getUserRolesHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(["kc_id"], ctx);
+  });
+
+  it("should get user roles by kc_id and set status to 200", async () => {
+    ctx.request.body.kc_id = "kc123";
+    const mockResponse = [{ id: "role1" }, { id: "role2" }];
+    getUserRoles.mockResolvedValue(mockResponse);
+
+    await getUserRolesHandler(ctx);
+
+    expect(ctx.body).toEqual(mockResponse);
+    expect(ctx.status).toBe(200);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.request.body.kc_id = "kc123";
+    getUserRoles.mockImplementation(() => {
+      throw error;
+    });
+
+    await getUserRolesHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
diff --git a/__tests__/api/roles/post.test.js b/__tests__/api/roles/post.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..e08ff6fbde78d3a19fe274507b4eb311d006c4f7
--- /dev/null
+++ b/__tests__/api/roles/post.test.js
@@ -0,0 +1,195 @@
+const {
+  createRoleHandler,
+  addUserToRoleHandler,
+  removeUserFromRoleHandler,
+} = require("@/app/api/roles/post");
+const {
+  createRole,
+  addUserToRole,
+  removeUserFromRole,
+} = require("@/app/dal/roleService");
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+
+jest.mock("@/app/dal/roleService");
+jest.mock("@/app/utils/errorHandler");
+
+describe("createRoleHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      request: {
+        body: {},
+      },
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when name and description are missing", async () => {
+    await createRoleHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(
+      ["name", "description"],
+      ctx
+    );
+  });
+
+  it("should handle missing parameters when name is missing", async () => {
+    ctx.request.body.description = "A description";
+
+    await createRoleHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(["name"], ctx);
+  });
+
+  it("should handle missing parameters when description is missing", async () => {
+    ctx.request.body.name = "A name";
+
+    await createRoleHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(["description"], ctx);
+  });
+
+  it("should create role and set status to 201", async () => {
+    ctx.request.body = { name: "A name", description: "A description" };
+    const mockResponse = {
+      id: "role123",
+      name: "A name",
+      description: "A description",
+    };
+    createRole.mockResolvedValue(mockResponse);
+
+    await createRoleHandler(ctx);
+
+    expect(ctx.body).toEqual(mockResponse);
+    expect(ctx.status).toBe(201);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.request.body = { name: "A name", description: "A description" };
+    createRole.mockImplementation(() => {
+      throw error;
+    });
+
+    await createRoleHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
+
+describe("addUserToRoleHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      params: {},
+      request: {
+        body: {},
+      },
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when id is missing", async () => {
+    ctx.request.body.kc_id = "kc123";
+
+    await addUserToRoleHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(["id"], ctx);
+  });
+
+  it("should handle missing parameters when kc_id is missing", async () => {
+    ctx.params.id = "role123";
+
+    await addUserToRoleHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(["kc_id"], ctx);
+  });
+
+  it("should add user to role and set status to 201", async () => {
+    ctx.params.id = "role123";
+    ctx.request.body.kc_id = "kc123";
+    const mockResponse = {
+      id: "role123",
+      kc_id: "kc123",
+    };
+    addUserToRole.mockResolvedValue(mockResponse);
+
+    await addUserToRoleHandler(ctx);
+
+    expect(ctx.body).toEqual(mockResponse);
+    expect(ctx.status).toBe(201);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.params.id = "role123";
+    ctx.request.body.kc_id = "kc123";
+    addUserToRole.mockImplementation(() => {
+      throw error;
+    });
+
+    await addUserToRoleHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
+
+describe("removeUserFromRoleHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      params: {},
+      request: {
+        body: {},
+      },
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when id is missing", async () => {
+    ctx.params.kc_id = "kc123";
+
+    await removeUserFromRoleHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(["id"], ctx);
+  });
+
+  it("should handle missing parameters when kc_id is missing", async () => {
+    ctx.params.id = "role123";
+
+    await removeUserFromRoleHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(["kc_id"], ctx);
+  });
+
+  it("should remove user from role and set status to 204", async () => {
+    ctx.params.id = "role123";
+    ctx.params.kc_id = "kc123";
+
+    await removeUserFromRoleHandler(ctx);
+
+    expect(ctx.status).toBe(204);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.params.id = "role123";
+    ctx.params.kc_id = "kc123";
+    removeUserFromRole.mockImplementation(() => {
+      throw error;
+    });
+
+    await removeUserFromRoleHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
diff --git a/__tests__/api/roles/update.test.js b/__tests__/api/roles/update.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..5850a435f696848a459cba5b948c51ddd2ccb2b5
--- /dev/null
+++ b/__tests__/api/roles/update.test.js
@@ -0,0 +1,88 @@
+const { updateRoleHandler } = require("@/app/api/roles/put");
+const { updateRole } = require("@/app/dal/roleService");
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+
+jest.mock("@/app/dal/roleService");
+jest.mock("@/app/utils/errorHandler");
+
+describe("updateRoleHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      params: {},
+      request: {
+        body: {},
+      },
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when id, name, and description are missing", async () => {
+    await updateRoleHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(
+      ["id", "name", "description"],
+      ctx
+    );
+  });
+
+  it("should handle missing parameters when id is missing", async () => {
+    ctx.request.body = { name: "Role Name", description: "Role Description" };
+
+    await updateRoleHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(["id"], ctx);
+  });
+
+  it("should handle missing parameters when name is missing", async () => {
+    ctx.params.id = "role123";
+    ctx.request.body.description = "Role Description";
+
+    await updateRoleHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(["name"], ctx);
+  });
+
+  it("should handle missing parameters when description is missing", async () => {
+    ctx.params.id = "role123";
+    ctx.request.body.name = "Role Name";
+
+    await updateRoleHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(["description"], ctx);
+  });
+
+  it("should update role and set status to 204", async () => {
+    ctx.params.id = "role123";
+    ctx.request.body = { name: "Role Name", description: "Role Description" };
+    const mockResponse = {
+      id: "role123",
+      name: "Role Name",
+      description: "Role Description",
+    };
+    updateRole.mockResolvedValue(mockResponse);
+
+    await updateRoleHandler(ctx);
+
+    expect(ctx.body).toEqual(mockResponse);
+    expect(ctx.status).toBe(204);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.params.id = "role123";
+    ctx.request.body = { name: "Role Name", description: "Role Description" };
+    updateRole.mockImplementation(() => {
+      throw error;
+    });
+
+    await updateRoleHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
diff --git a/__tests__/api/search/post.test.js b/__tests__/api/search/post.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..d844c8b7ef52af3f03e23e8cf76ea3943156dcb6
--- /dev/null
+++ b/__tests__/api/search/post.test.js
@@ -0,0 +1,67 @@
+const { getQueryResultsHandler } = require("@/app/api/search/post");
+const { search } = require("@/app/dal/elasticService");
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+
+jest.mock("@/app/dal/elasticService");
+jest.mock("@/app/utils/errorHandler");
+
+describe("getQueryResultsHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      request: {
+        body: {},
+      },
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when query is missing", async () => {
+    await getQueryResultsHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(
+      ["query", "sourcesId", "fieldsId"],
+      ctx
+    );
+  });
+
+  it("should get query results and set status to 200", async () => {
+    ctx.request.body = {
+      query: "test query",
+      sourcesId: [1, 2, 3],
+      fieldsId: [1, 2, 3],
+      index: "test_index",
+      scroll_id: "test_scroll_id",
+    };
+    const mockResponse = { hits: { hits: [] } };
+    search.mockResolvedValue(mockResponse);
+
+    await getQueryResultsHandler(ctx);
+
+    expect(ctx.body).toEqual([]);
+    expect(ctx.status).toBe(200);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.request.body = {
+      query: "test query",
+      sourcesId: [1, 2, 3],
+      fieldsId: [1, 2, 3],
+      index: "test_index",
+      scroll_id: "test_scroll_id",
+    };
+    search.mockImplementation(() => {
+      throw error;
+    });
+
+    await getQueryResultsHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
diff --git a/__tests__/api/sources/delete.test.js b/__tests__/api/sources/delete.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..113ec10b028ab9b69a678bfdc365f21f421820c3
--- /dev/null
+++ b/__tests__/api/sources/delete.test.js
@@ -0,0 +1,50 @@
+const { deleteSourceHandler } = require("@/app/api/sources/delete");
+const { deleteSource } = require("@/app/dal/sourceService");
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+
+jest.mock("@/app/dal/sourceService");
+jest.mock("@/app/utils/errorHandler");
+
+describe("deleteSourceHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      params: {},
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when id is missing", async () => {
+    await deleteSourceHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(["id"], ctx);
+  });
+
+  it("should delete source and set status to 200", async () => {
+    ctx.params.id = "source123";
+    const mockResponse = { success: true };
+    deleteSource.mockResolvedValue(mockResponse);
+
+    await deleteSourceHandler(ctx);
+
+    expect(ctx.body).toEqual(null);
+    expect(ctx.status).toBe(204);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.params.id = "source123";
+    deleteSource.mockImplementation(() => {
+      throw error;
+    });
+
+    await deleteSourceHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
diff --git a/__tests__/api/sources/get.test.js b/__tests__/api/sources/get.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..f186abe870f50631a4fb4ac3e67d6fc85bf0c924
--- /dev/null
+++ b/__tests__/api/sources/get.test.js
@@ -0,0 +1,208 @@
+const {
+  getSourcesHandler,
+  getSourceHandler,
+  getSourcesByProviderHandler,
+  getIndexedSourcesHandler,
+  getIndexedSourcesByProviderHandler,
+} = require("@/app/api/sources/get");
+const {
+  getSources,
+  getSource,
+  getSourcesByProvider,
+  getIndexedSources,
+  getIndexedSourcesByProvider,
+} = require("@/app/dal/sourceService");
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+
+jest.mock("@/app/dal/sourceService");
+jest.mock("@/app/utils/errorHandler");
+
+describe("getSourcesHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should get sources and set status to 200", async () => {
+    const mockResponse = [{ id: "source1" }, { id: "source2" }];
+    getSources.mockResolvedValue(mockResponse);
+
+    await getSourcesHandler(ctx);
+
+    expect(ctx.body).toEqual(mockResponse);
+    expect(ctx.status).toBe(200);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    getSources.mockImplementation(() => {
+      throw error;
+    });
+
+    await getSourcesHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
+
+describe("getSourceHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      params: {},
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when id is missing", async () => {
+    await getSourceHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(["id"], ctx);
+  });
+
+  it("should get source by id and set status to 200", async () => {
+    ctx.params.id = "source123";
+    const mockResponse = { id: "source123", name: "Source Name" };
+    getSource.mockResolvedValue(mockResponse);
+
+    await getSourceHandler(ctx);
+
+    expect(ctx.body).toEqual(mockResponse);
+    expect(ctx.status).toBe(200);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.params.id = "source123";
+    getSource.mockImplementation(() => {
+      throw error;
+    });
+
+    await getSourceHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
+
+describe("getSourcesByProviderHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      params: {},
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when kc_id is missing", async () => {
+    await getSourcesByProviderHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(["kc_id"], ctx);
+  });
+
+  it("should get sources by provider and set status to 200", async () => {
+    ctx.params.kc_id = "kc123";
+    const mockResponse = [{ id: "source1" }, { id: "source2" }];
+    getSourcesByProvider.mockResolvedValue(mockResponse);
+
+    await getSourcesByProviderHandler(ctx);
+
+    expect(ctx.body).toEqual(mockResponse);
+    expect(ctx.status).toBe(200);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.params.kc_id = "kc123";
+    getSourcesByProvider.mockImplementation(() => {
+      throw error;
+    });
+
+    await getSourcesByProviderHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
+
+describe("getIndexedSourcesHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should get indexed sources and set status to 200", async () => {
+    const mockResponse = [{ id: "source1" }, { id: "source2" }];
+    getIndexedSources.mockResolvedValue(mockResponse);
+
+    await getIndexedSourcesHandler(ctx);
+
+    expect(ctx.body).toEqual(mockResponse);
+    expect(ctx.status).toBe(200);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    getIndexedSources.mockImplementation(() => {
+      throw error;
+    });
+
+    await getIndexedSourcesHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
+
+describe("getIndexedSourcesByProviderHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      params: {},
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when kc_id is missing", async () => {
+    await getIndexedSourcesByProviderHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(["kc_id"], ctx);
+  });
+
+  it("should get indexed sources by provider and set status to 200", async () => {
+    ctx.params.kc_id = "kc123";
+    const mockResponse = [{ id: "source1" }, { id: "source2" }];
+    getIndexedSourcesByProvider.mockResolvedValue(mockResponse);
+
+    await getIndexedSourcesByProviderHandler(ctx);
+
+    expect(ctx.body).toEqual(mockResponse);
+    expect(ctx.status).toBe(200);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.params.kc_id = "kc123";
+    getIndexedSourcesByProvider.mockImplementation(() => {
+      throw error;
+    });
+
+    await getIndexedSourcesByProviderHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
diff --git a/__tests__/api/sources/post.test.js b/__tests__/api/sources/post.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..7dbd15a29bd62609d18faafe3d1552abe0f118df
--- /dev/null
+++ b/__tests__/api/sources/post.test.js
@@ -0,0 +1,69 @@
+const { createSourceHandler } = require("@/app/api/sources/post");
+const { createSource } = require("@/app/dal/sourceService");
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+
+jest.mock("@/app/dal/sourceService");
+jest.mock("@/app/utils/errorHandler");
+
+describe("createSourceHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      request: {
+        body: {},
+      },
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when name, description, metaUrfms and kc_id are missing", async () => {
+    await createSourceHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(
+      ["name", "description", "kc_id", "metaUrfms"],
+      ctx
+    );
+  });
+
+  it("should create source and set status to 201", async () => {
+    ctx.request.body = {
+      name: "A name",
+      description: "A description",
+      metaUrfms: "metaUrfms",
+      kc_id: "kc_id",
+    };
+    const mockResponse = {
+      id: "source123",
+      name: "A name",
+      description: "A description",
+    };
+    createSource.mockResolvedValue(mockResponse);
+
+    await createSourceHandler(ctx);
+
+    expect(ctx.body).toEqual(mockResponse);
+    expect(ctx.status).toBe(201);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.request.body = {
+      name: "A name",
+      description: "A description",
+      metaUrfms: "metaUrfms",
+      kc_id: "kc_id",
+    };
+    createSource.mockImplementation(() => {
+      throw error;
+    });
+
+    await createSourceHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
diff --git a/__tests__/api/std_fields/get.test.js b/__tests__/api/std_fields/get.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..19908a62bc65fd85a47e27b3f8866e3e444a4477
--- /dev/null
+++ b/__tests__/api/std_fields/get.test.js
@@ -0,0 +1,90 @@
+// get.test.js
+
+const {
+  getStdFieldsHandler,
+  getStdFieldHandler,
+} = require("@/app/api/std_fields/get");
+const { getStdFields, getStdField } = require("@/app/dal/stdFieldService");
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+
+jest.mock("@/app/dal/stdFieldService");
+jest.mock("@/app/utils/errorHandler");
+
+describe("getStdFieldsHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should get standard fields and set status to 200", async () => {
+    const mockResponse = [{ id: "field1" }, { id: "field2" }];
+    getStdFields.mockResolvedValue(mockResponse);
+
+    await getStdFieldsHandler(ctx);
+
+    expect(ctx.body).toEqual(mockResponse);
+    expect(ctx.status).toBe(200);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    getStdFields.mockImplementation(() => {
+      throw error;
+    });
+
+    await getStdFieldsHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
+
+describe("getStdFieldHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      params: {},
+      request: {
+        body: {},
+      },
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when id is missing", async () => {
+    await getStdFieldHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(["id"], ctx);
+  });
+
+  it("should get standard field by id and set status to 200", async () => {
+    ctx.params.id = "field123";
+    const mockResponse = { name: "Field Name" };
+    getStdField.mockResolvedValue(mockResponse);
+
+    await getStdFieldHandler(ctx);
+
+    expect(ctx.body).toEqual(mockResponse);
+    expect(ctx.status).toBe(200);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.params.id = "field123";
+    getStdField.mockImplementation(() => {
+      throw error;
+    });
+
+    await getStdFieldHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
diff --git a/__tests__/api/std_fields/post.test.js b/__tests__/api/std_fields/post.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..3e12d7733bb33c15e9dbc6ca64e3ca6fec3e36eb
--- /dev/null
+++ b/__tests__/api/std_fields/post.test.js
@@ -0,0 +1,46 @@
+const { createOrUpdateStdFieldHandler } = require("@/app/api/std_fields/post");
+const { createOrUpdateStdField } = require("@/app/dal/stdFieldService");
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+
+jest.mock("@/app/dal/stdFieldService");
+jest.mock("@/app/utils/errorHandler");
+
+describe("createOrUpdateStdFieldHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      request: {
+        body: {},
+      },
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should create standard field and set status to 201", async () => {
+    ctx.request.body.name = "New Field";
+    const mockResponse = { id: "field123", name: "New Field" };
+    createOrUpdateStdField.mockResolvedValue(mockResponse);
+
+    await createOrUpdateStdFieldHandler(ctx);
+
+    expect(ctx.body).toEqual(mockResponse);
+    expect(ctx.status).toBe(201);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.request.body.name = "New Field";
+    createOrUpdateStdField.mockImplementation(() => {
+      throw error;
+    });
+
+    await createOrUpdateStdFieldHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
diff --git a/__tests__/api/std_fields/update.test.js b/__tests__/api/std_fields/update.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..e90bfc70ef16eb829183c1430ef2230282ea03a3
--- /dev/null
+++ b/__tests__/api/std_fields/update.test.js
@@ -0,0 +1,55 @@
+const { updateStdFieldHandler } = require("@/app/api/std_fields/update");
+const { createOrUpdateStdField } = require("@/app/dal/stdFieldService");
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+
+jest.mock("@/app/dal/stdFieldService");
+jest.mock("@/app/utils/errorHandler");
+
+describe("updateStdFieldHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      params: {},
+      request: {
+        body: {},
+      },
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when id is missing", async () => {
+    await updateStdFieldHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(["id"], ctx);
+  });
+
+  it("should update standard field and set status to 204", async () => {
+    ctx.params.id = "field123";
+    ctx.request.body = { name: "Updated Field" };
+    const mockResponse = { id: "field123", name: "Updated Field" };
+    createOrUpdateStdField.mockResolvedValue(mockResponse);
+
+    await updateStdFieldHandler(ctx);
+
+    expect(ctx.body).toEqual(mockResponse);
+    expect(ctx.status).toBe(204);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.params.id = "field123";
+    ctx.request.body = { name: "Updated Field" };
+    createOrUpdateStdField.mockImplementation(() => {
+      throw error;
+    });
+
+    await updateStdFieldHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
diff --git a/__tests__/api/user-display-fields/get.test.js b/__tests__/api/user-display-fields/get.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..94ecf8d6c93bf478759073af38cce90ef52ed462
--- /dev/null
+++ b/__tests__/api/user-display-fields/get.test.js
@@ -0,0 +1,55 @@
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("../../../app/utils/errorHandler");
+const {
+  getUserDisplayFields,
+} = require("../../../app/dal/userDisplayFieldsService");
+const {
+  getUserDisplayFieldsHandler,
+} = require("../../../app/api/user-display-fields/get");
+
+jest.mock("@/app/dal/userService");
+jest.mock("@/app/dal/userDisplayFieldsService");
+jest.mock("@/app/utils/errorHandler");
+
+describe("getUserDisplayFieldsHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      params: {},
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when kc_id is missing", async () => {
+    await getUserDisplayFieldsHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(["kc_id"], ctx);
+  });
+
+  it("should get user display fields and set status to 200", async () => {
+    ctx.params.kc_id = "user123";
+    const mockResponse = { field1: "value1", field2: "value2" };
+    getUserDisplayFields.mockResolvedValue(mockResponse);
+
+    await getUserDisplayFieldsHandler(ctx);
+
+    expect(ctx.body).toEqual(mockResponse);
+    expect(ctx.status).toBe(200);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.params.kc_id = "user123";
+    getUserDisplayFields.mockImplementation(() => {
+      throw error;
+    });
+
+    await getUserDisplayFieldsHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
diff --git a/__tests__/api/user-requests/delete.test.js b/__tests__/api/user-requests/delete.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..dec90c18b5128d7f13f967482828961a6768b324
--- /dev/null
+++ b/__tests__/api/user-requests/delete.test.js
@@ -0,0 +1,51 @@
+// delete.test.js
+
+const { deleteRequestHandler } = require("@/app/api/user-requests/delete");
+const { deleteRequest } = require("@/app/dal/userRequestService");
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+
+jest.mock("@/app/dal/userRequestService");
+jest.mock("@/app/utils/errorHandler");
+
+describe("deleteRequestHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      params: {},
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when id is missing", async () => {
+    await deleteRequestHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(["id"], ctx);
+  });
+
+  it("should delete request and set status to 204", async () => {
+    ctx.params.id = "req123";
+    deleteRequest.mockResolvedValue({});
+
+    await deleteRequestHandler(ctx);
+
+    expect(ctx.body).toEqual(null);
+    expect(ctx.status).toBe(204);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.params.id = "req123";
+    deleteRequest.mockImplementation(() => {
+      throw error;
+    });
+
+    await deleteRequestHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
diff --git a/__tests__/api/user-requests/get.test.js b/__tests__/api/user-requests/get.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..56723de073ccb116acb2a9c017fd90110341186e
--- /dev/null
+++ b/__tests__/api/user-requests/get.test.js
@@ -0,0 +1,165 @@
+// get.test.js
+
+const {
+  getAllRequestsHandler,
+  getAllPendingRequestsHandler,
+  getAllUserRequestsHandler,
+  getAllPendingUserRequestsHandler,
+} = require("@/app/api/user-requests/get");
+const {
+  getAllRequests,
+  getAllPendingRequests,
+} = require("@/app/dal/userRequestService");
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+
+jest.mock("@/app/dal/userRequestService");
+jest.mock("@/app/utils/errorHandler");
+
+describe("getAllRequestsHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should get all requests and set status to 200", async () => {
+    const mockResponse = [{ id: 1, request: "test request" }];
+    getAllRequests.mockResolvedValue(mockResponse);
+
+    await getAllRequestsHandler(ctx);
+
+    expect(ctx.body).toEqual(mockResponse);
+    expect(ctx.status).toBe(200);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    getAllRequests.mockImplementation(() => {
+      throw error;
+    });
+
+    await getAllRequestsHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
+
+describe("getAllPendingRequestsHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should get all pending requests and set status to 200", async () => {
+    const mockResponse = [{ id: 1, request: "pending request" }];
+    getAllPendingRequests.mockResolvedValue(mockResponse);
+
+    await getAllPendingRequestsHandler(ctx);
+
+    expect(ctx.body).toEqual(mockResponse);
+    expect(ctx.status).toBe(200);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    getAllPendingRequests.mockImplementation(() => {
+      throw error;
+    });
+
+    await getAllPendingRequestsHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
+
+describe("getAllUserRequestsHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      body: null,
+      status: null,
+      params: { kc_id: "test-id" },
+    };
+  });
+
+  it("should get all requests for a user and set status to 200", async () => {
+    const mockResponse = [{ id: 1, request: "test request" }];
+    getAllRequests.mockResolvedValue(mockResponse);
+
+    await getAllUserRequestsHandler(ctx);
+
+    expect(ctx.body).toEqual(mockResponse);
+    expect(ctx.status).toBe(200);
+  });
+
+  it("should handle missing parameters", async () => {
+    ctx.params.kc_id = null;
+
+    await getAllUserRequestsHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(["kc_id"], ctx);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    getAllRequests.mockImplementation(() => {
+      throw error;
+    });
+
+    await getAllUserRequestsHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
+
+describe("getAllPendingUserRequestsHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      body: null,
+      status: null,
+      params: { kc_id: "test-id" },
+    };
+  });
+
+  it("should get all pending requests for a user and set status to 200", async () => {
+    const mockResponse = [{ id: 1, request: "pending request" }];
+    getAllPendingRequests.mockResolvedValue(mockResponse);
+
+    await getAllPendingUserRequestsHandler(ctx);
+
+    expect(ctx.body).toEqual(mockResponse);
+    expect(ctx.status).toBe(200);
+  });
+
+  it("should handle missing parameters", async () => {
+    ctx.params.kc_id = null;
+
+    await getAllPendingUserRequestsHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(["kc_id"], ctx);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    getAllPendingRequests.mockImplementation(() => {
+      throw error;
+    });
+
+    await getAllPendingUserRequestsHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
diff --git a/__tests__/api/user-requests/post.test.js b/__tests__/api/user-requests/post.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..0e574b0de43a0db5a5d239119e201d9c28fd7ceb
--- /dev/null
+++ b/__tests__/api/user-requests/post.test.js
@@ -0,0 +1,137 @@
+// post.test.js
+
+const {
+  createRequestHandler,
+  updateRequestHandler,
+} = require("@/app/api/user-requests/post");
+const {
+  createRequest,
+  updateRequest,
+} = require("@/app/dal/userRequestService");
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+
+jest.mock("@/app/dal/userRequestService");
+jest.mock("@/app/utils/errorHandler");
+
+describe("createRequestHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      params: {},
+      request: {
+        body: {},
+      },
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when kc_id or message is missing", async () => {
+    await createRequestHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(
+      ["kc_id", "message"],
+      ctx
+    );
+  });
+
+  it("should create request and set status to 201", async () => {
+    ctx.params.kc_id = "kc123";
+    ctx.request.body = { message: "test message" };
+    const mockResponse = { id: 1, kc_id: "kc123", message: "test message" };
+    createRequest.mockResolvedValue(mockResponse);
+
+    await createRequestHandler(ctx);
+
+    expect(ctx.body).toEqual(mockResponse);
+    expect(ctx.status).toBe(201);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.params.kc_id = "kc123";
+    ctx.request.body = { message: "test message" };
+    createRequest.mockImplementation(() => {
+      throw error;
+    });
+
+    await createRequestHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
+
+describe("updateRequestHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      params: {},
+      request: {
+        body: {},
+      },
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when id or is_processed is missing", async () => {
+    await updateRequestHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(
+      ["id", "is_processed"],
+      ctx
+    );
+  });
+
+  it("should return 400 if is_processed is not a boolean", async () => {
+    ctx.params.id = {
+      id: "req123",
+    };
+    ctx.request.body.is_processed = "not_boolean";
+
+    jest.mock("@/app/utils/errorHandler", () => {
+      const originalModule = jest.requireActual("@/app/utils/errorHandler");
+      return {
+        ...originalModule,
+        handleInternalError: jest.fn(),
+      };
+    });
+
+    await updateRequestHandler(ctx);
+    expect(handleMissingParameters.mock.calls).toHaveLength(1);
+    expect(handleMissingParameters).toHaveBeenCalledWith(
+      ["is_processed must be a boolean"],
+      ctx
+    );
+  });
+
+  it("should update request and set status to 201", async () => {
+    ctx.params.id = "req123";
+    ctx.request.body.is_processed = true;
+    const mockResponse = { id: "req123", is_processed: "true" };
+    updateRequest.mockResolvedValue(mockResponse);
+
+    await updateRequestHandler(ctx);
+
+    expect(ctx.body).toEqual(mockResponse);
+    expect(ctx.status).toBe(201);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.params.id = "req123";
+    ctx.request.body.is_processed = true;
+    updateRequest.mockImplementation(() => {
+      throw error;
+    });
+
+    await updateRequestHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
diff --git a/__tests__/api/user-search-history/delete.test.js b/__tests__/api/user-search-history/delete.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..1ed4c00b42f783e4ae975c3f5c55a5001f447afc
--- /dev/null
+++ b/__tests__/api/user-search-history/delete.test.js
@@ -0,0 +1,94 @@
+// delete.test.js
+
+const {
+  deleteHistoryHandler,
+  deleteAllHistoryByUserHandler,
+} = require("@/app/api/user-search-history/delete");
+const {
+  deleteHistory,
+  deleteAllHistoryByUser: deleteAllHistoryByUserService,
+} = require("@/app/dal/searchHistoryService");
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+
+jest.mock("@/app/dal/searchHistoryService");
+jest.mock("@/app/utils/errorHandler");
+
+describe("deleteHistoryHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      params: {},
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when id is missing", async () => {
+    await deleteHistoryHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(["id"], ctx);
+  });
+
+  it("should delete history and set status to 204", async () => {
+    ctx.params.id = "history123";
+
+    await deleteHistoryHandler(ctx);
+
+    expect(ctx.status).toBe(204);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.params.id = "history123";
+    deleteHistory.mockImplementation(() => {
+      throw error;
+    });
+
+    await deleteHistoryHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
+
+describe("deleteAllHistoryByUserHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      params: {},
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when kc_id is missing", async () => {
+    await deleteAllHistoryByUserHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(["kc_id"], ctx);
+  });
+
+  it("should delete all history by user and set status to 204", async () => {
+    ctx.params.kc_id = "kc123";
+    deleteAllHistoryByUserService.mockResolvedValue([]);
+
+    await deleteAllHistoryByUserHandler(ctx);
+
+    expect(ctx.status).toBe(204);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.params.kc_id = "kc123";
+    deleteAllHistoryByUserService.mockImplementation(() => {
+      throw error;
+    });
+
+    await deleteAllHistoryByUserHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
diff --git a/__tests__/api/user-search-history/get.test.js b/__tests__/api/user-search-history/get.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..2bf46b7b27a58da6890b6fa1d4cf35fd980ff50d
--- /dev/null
+++ b/__tests__/api/user-search-history/get.test.js
@@ -0,0 +1,58 @@
+// get.test.js
+
+const { getHistoryHandler } = require("@/app/api/user-search-history/get");
+const {
+  handleMissingParameters,
+  handleInternalError,
+} = require("@/app/utils/errorHandler");
+const { getSearchHistoryByUser } = require("@/app/dal/searchHistoryService");
+
+jest.mock("@/app/utils/errorHandler");
+jest.mock("@/app/dal/searchHistoryService");
+
+describe("getHistoryHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      request: {
+        body: {},
+      },
+      body: null,
+      status: null,
+      params: {},
+    };
+  });
+
+  it("should handle missing parameters", async () => {
+    await getHistoryHandler(ctx);
+    expect(handleMissingParameters).toHaveBeenCalledWith(["kc_id"], ctx);
+  });
+
+  it("should return search history and set status to 200", async () => {
+    const mockHistory = [{ id: 1, search: "test search" }];
+    ctx.params = {
+      kc_id: "kc123",
+    };
+    getSearchHistoryByUser.mockResolvedValue(mockHistory);
+
+    await getHistoryHandler(ctx);
+
+    expect(ctx.status).toBe(200);
+    expect(ctx.body).toEqual(mockHistory);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.params = {
+      kc_id: "kc123",
+    };
+    getSearchHistoryByUser.mockImplementation(() => {
+      throw error;
+    });
+
+    await getHistoryHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
diff --git a/__tests__/api/user-search-history/post.test.js b/__tests__/api/user-search-history/post.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..25ee21c10fb088933fcce3d888989d68b5d14450
--- /dev/null
+++ b/__tests__/api/user-search-history/post.test.js
@@ -0,0 +1,75 @@
+// post.test.js
+
+const {
+  addSearchHistoryToUserHandler,
+} = require("@/app/api/user-search-history/post");
+const { addSearchHistoryToUser } = require("@/app/dal/searchHistoryService");
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+
+jest.mock("@/app/dal/searchHistoryService");
+jest.mock("@/app/utils/errorHandler");
+
+describe("addSearchHistoryToUserHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      params: {},
+      request: {
+        body: {},
+      },
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when any required parameter is missing", async () => {
+    ctx.request.body = { query: "test query" };
+
+    await addSearchHistoryToUserHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(
+      ["kc_id", "name", "ui_structure", "description"],
+      ctx
+    );
+  });
+
+  it("should add search history and set status to 201", async () => {
+    const mockResponse = { id: 1, query: "test query" };
+
+    ctx.params = { kc_id: "test-id" };
+    ctx.request.body = {
+      query: "test query",
+      name: "test name",
+      ui_structure: "test structure",
+      description: "test description",
+    };
+    addSearchHistoryToUser.mockResolvedValue(mockResponse);
+
+    await addSearchHistoryToUserHandler(ctx);
+
+    expect(ctx.body).toEqual(mockResponse);
+    expect(ctx.status).toBe(201);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.params = { kc_id: "test-id" };
+    ctx.request.body = {
+      query: "test query",
+      name: "test name",
+      ui_structure: "test structure",
+      description: "test description",
+    };
+    addSearchHistoryToUser.mockImplementation(() => {
+      throw error;
+    });
+
+    await addSearchHistoryToUserHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
diff --git a/__tests__/api/users/delete.test.js b/__tests__/api/users/delete.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..6d9a423ab8dc21120f5ae03410018f7119adfaff
--- /dev/null
+++ b/__tests__/api/users/delete.test.js
@@ -0,0 +1,52 @@
+const { deleteUserHandler } = require("@/app/api/users/delete");
+const userService = require("@/app/dal/userService");
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+
+jest.mock("@/app/dal/userService");
+jest.mock("@/app/utils/errorHandler");
+
+describe("deleteUserHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      params: {},
+      request: {
+        body: {},
+      },
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when kc_id is missing", async () => {
+    await deleteUserHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(["kc_id"], ctx);
+  });
+
+  it("should delete user and set status to 204", async () => {
+    ctx.params = { kc_id: "kc123" };
+    userService.deleteUser.mockResolvedValue({});
+
+    await deleteUserHandler(ctx);
+
+    expect(ctx.body).toEqual({});
+    expect(ctx.status).toBe(204);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.params = { kc_id: "kc123" };
+    userService.deleteUser.mockImplementation(() => {
+      throw error;
+    });
+
+    await deleteUserHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
diff --git a/__tests__/api/users/get.test.js b/__tests__/api/users/get.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..484738e371315aeb7b2f9b8cb2aa05e34d25407a
--- /dev/null
+++ b/__tests__/api/users/get.test.js
@@ -0,0 +1,78 @@
+"use strict";
+const { getUsersHandler, getUserHandler } = require("@/app/api/users/get");
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+const { getUsers, getUser } = require("@/app/dal/userService");
+
+jest.mock("@/app/utils/errorHandler");
+jest.mock("@/app/dal/userService");
+
+describe("User Handlers", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      params: {},
+      body: null,
+      status: null,
+    };
+  });
+
+  describe("getUsersHandler", () => {
+    it("should return all users and set status to 200", async () => {
+      const mockUsers = [
+        { id: 1, name: "User 1" },
+        { id: 2, name: "User 2" },
+      ];
+      getUsers.mockResolvedValue(mockUsers);
+
+      await getUsersHandler(ctx);
+
+      expect(ctx.body).toEqual(mockUsers);
+      expect(ctx.status).toBe(200);
+    });
+
+    it("should handle internal error", async () => {
+      const error = new Error("Internal Error");
+      getUsers.mockImplementation(() => {
+        throw error;
+      });
+
+      await getUsersHandler(ctx);
+
+      expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+    });
+  });
+
+  describe("getUserHandler", () => {
+    it("should handle missing parameters", async () => {
+      await getUserHandler(ctx);
+      expect(handleMissingParameters).toHaveBeenCalledWith(["kc_id"], ctx);
+    });
+
+    it("should return user data and set status to 200", async () => {
+      const mockUser = { id: 1, name: "Test User" };
+      ctx.params.kc_id = 1;
+      getUser.mockResolvedValue(mockUser);
+
+      await getUserHandler(ctx);
+
+      expect(ctx.body).toEqual(mockUser);
+      expect(ctx.status).toBe(200);
+    });
+
+    it("should handle internal error", async () => {
+      const error = new Error("Internal Error");
+      ctx.params.kc_id = 1;
+      getUser.mockImplementation(() => {
+        throw error;
+      });
+
+      await getUserHandler(ctx);
+
+      expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+    });
+  });
+});
diff --git a/__tests__/api/users/post.test.js b/__tests__/api/users/post.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..ced1bdfbd8f53d182a2a3904fd578994b7e9d74a
--- /dev/null
+++ b/__tests__/api/users/post.test.js
@@ -0,0 +1,96 @@
+// post.test.js
+
+const { getOrCreateUserHandler } = require("@/app/api/users/post");
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+const { createUser, getUser } = require("@/app/dal/userService");
+const prisma = require("@/prisma/client");
+
+jest.mock("@/prisma/client", () => ({
+  user: {
+    findFirst: jest.fn(),
+    create: jest.fn(),
+  },
+}));
+
+jest.mock("@/app/dal/userService");
+jest.mock("@/app/utils/errorHandler");
+
+describe("getOrCreateUserHandler", () => {
+  let ctx;
+
+  beforeEach(() => {
+    ctx = {
+      request: {
+        body: {},
+      },
+      body: null,
+      status: null,
+    };
+  });
+
+  it("should handle missing parameters when kc_id is missing", async () => {
+    ctx.request.body = { email: "test@example.com" };
+
+    await getOrCreateUserHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(["kc_id"], ctx);
+  });
+
+  it("should handle missing parameters when email is missing", async () => {
+    ctx.request.body = { kc_id: "kc123" };
+
+    await getOrCreateUserHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(["email"], ctx);
+  });
+
+  it("should handle missing parameters when both kc_id and email are missing", async () => {
+    ctx.request.body = {};
+
+    await getOrCreateUserHandler(ctx);
+
+    expect(handleMissingParameters).toHaveBeenCalledWith(
+      ["kc_id", "email"],
+      ctx
+    );
+  });
+
+  it("should return user data and set status to 200 if user exists", async () => {
+    const mockUser = { id: 1, kc_id: "kc123", email: "test@example.com" };
+    ctx.request.body = { kc_id: "kc123", email: "test@example.com" };
+    getUser.mockResolvedValue(mockUser);
+
+    await getOrCreateUserHandler(ctx);
+
+    expect(ctx.body).toEqual(mockUser);
+    expect(ctx.status).toBe(200);
+  });
+
+  it("should create a new user and set status to 201 if user does not exist", async () => {
+    const mockUser = { id: 1, kc_id: "kc123", email: "test@example.com" };
+    ctx.request.body = { kc_id: "kc123", email: "test@example.com" };
+    getUser.mockResolvedValue(null);
+    createUser.mockResolvedValue(mockUser);
+
+    prisma.user.findFirst.mockResolvedValue(null);
+    await getOrCreateUserHandler(ctx);
+
+    expect(ctx.body).toEqual(mockUser);
+    expect(ctx.status).toBe(201);
+  });
+
+  it("should handle internal error", async () => {
+    const error = new Error("Internal Error");
+    ctx.request.body = { kc_id: "kc123", email: "test@example.com" };
+    createUser.mockImplementation(() => {
+      throw error;
+    });
+
+    await getOrCreateUserHandler(ctx);
+
+    expect(handleInternalError).toHaveBeenCalledWith(error, ctx);
+  });
+});
diff --git a/app/api/group/delete.js b/app/api/group/delete.js
deleted file mode 100644
index 5a8c7cd09ba653d1c5a7c24cb6cfe38f32d2a6eb..0000000000000000000000000000000000000000
--- a/app/api/group/delete.js
+++ /dev/null
@@ -1,42 +0,0 @@
-'use strict'
-
-const groupService = require('../../dal/groupService');
-const logger = require('../../utils/logger');
-
-const Group = {
-    async deleteGroup(ctx) {
-        try {
-            ctx.body = await groupService.deleteGroup(ctx.request.body);
-            ctx.status = 201;
-            logger.info('Group deleted.');
-        } catch (error) {
-            throw error;
-        }
-    },
-
-    async deleteGroupPolicy(ctx) {
-        try {
-            ctx.body = await groupService.deleteGroupPolicy(ctx.request.body);
-            ctx.status = 201;
-            logger.info('Group policy deleted.');
-        } catch (error) {
-            throw error;
-        }
-    },
-
-    async deleteGroupUser(ctx) {
-        try {
-            ctx.body = await groupService.deleteGroupUser(ctx.request.body);
-            ctx.status = 201;
-            logger.info('Group user deleted.');
-        } catch (error) {
-            throw error;
-        }
-    },
-};
-
-module.exports = {
-    deleteGroup : Group.deleteGroup,
-    deleteGroupPolicy: Group.deleteGroupPolicy,
-    deleteGroupUser: Group.deleteGroupUser
-};
diff --git a/app/api/group/get.js b/app/api/group/get.js
deleted file mode 100644
index 8a99ad0512411e53234e463a89a0ed1f2d27477f..0000000000000000000000000000000000000000
--- a/app/api/group/get.js
+++ /dev/null
@@ -1,42 +0,0 @@
-'use strict'
-
-const groupService = require('../../dal/groupService');
-const logger = require('../../utils/logger');
-
-const Group = {
-    async groups(ctx) {
-        try {
-            ctx.body = await groupService.groups();
-            ctx.status = 201;
-            logger.info('Groups fetched.');
-        } catch (error) {
-            throw error;
-        }
-    },
-
-    async groupPolicies(ctx) {
-        try {
-            ctx.body = await groupService.groupPolicies();
-            ctx.status = 201;
-            logger.info('Group policies fetched.');
-        } catch (error) {
-           throw error;
-        }
-    },
-
-    async groupUsers(ctx) {
-        try {
-            ctx.body = await groupService.groupUsers(ctx.request.body);
-            ctx.status = 201;
-            logger.info('Group users fetched.');
-        } catch (error) {
-           throw error;
-        }
-    }
-};
-
-module.exports = {
-    groups: Group.groups,
-    groupPolicies: Group.groupPolicies,
-    groupUsers: Group.groupUsers,
-};
diff --git a/app/api/group/index.js b/app/api/group/index.js
deleted file mode 100644
index 32fb0668b48efeb86f601558977fb064eb9f6388..0000000000000000000000000000000000000000
--- a/app/api/group/index.js
+++ /dev/null
@@ -1,23 +0,0 @@
-'use strict'
-
-const { groups, groupUsers, groupPolicies } = require('./get');
-const { createGroup, createGroupPolicy, createGroupUser } = require('./post');
-const { deleteGroup, deleteGroupPolicy, deleteGroupUser } = require('./delete');
-const { updateGroup, updateGroupPolicy, updateGroupUser } = require('./update');
-
-const GroupHandler = {
-    groups,
-    groupUsers,
-    groupPolicies,
-    createGroup,
-    createGroupPolicy,
-    createGroupUser,
-    deleteGroup,
-    deleteGroupPolicy,
-    deleteGroupUser,
-    updateGroup,
-    updateGroupPolicy,
-    updateGroupUser
-};
-
-module.exports = GroupHandler;
diff --git a/app/api/group/post.js b/app/api/group/post.js
deleted file mode 100644
index dd0a5b530a1994c9476e5affc2d97a53a5af7e65..0000000000000000000000000000000000000000
--- a/app/api/group/post.js
+++ /dev/null
@@ -1,42 +0,0 @@
-'use strict'
-
-const groupService = require('../../dal/groupService');
-const logger = require('../../utils/logger');
-
-const Group = {
-    async createGroup(ctx) {
-        try {
-            ctx.body = await groupService.createGroup(ctx.request.body);
-            ctx.status = 201;
-            logger.info('Group created.');
-        } catch (error) {
-            throw error;
-        }
-    },
-
-    async createGroupPolicy(ctx) {
-        try {
-            ctx.body = await groupService.createGroupPolicy(ctx.request.body);
-            ctx.status = 201;
-            logger.info('Assigned policy to group.');
-        } catch (error) {
-            throw error;
-        }
-    },
-
-    async createGroupUser(ctx) {
-        try {
-            ctx.body = await groupService.createGroupUser(ctx.request.body);
-            ctx.status = 201;
-            logger.info('Assigned user to group.');
-        } catch (error) {
-            throw error;
-        }
-    }
-};
-
-module.exports = {
-    createGroup: Group.createGroup,
-    createGroupPolicy: Group.createGroupPolicy,
-    createGroupUser: Group.createGroupUser,
-};
diff --git a/app/api/group/update.js b/app/api/group/update.js
deleted file mode 100644
index 6241040bfbb0c205c72932040f0bba23b7979678..0000000000000000000000000000000000000000
--- a/app/api/group/update.js
+++ /dev/null
@@ -1,42 +0,0 @@
-'use strict'
-
-const groupService = require('../../dal/groupService');
-const logger = require('../../utils/logger');
-
-const Group = {
-    async updateGroup(ctx) {
-        try {
-            ctx.body = await groupService.updateGroup(ctx.request.body);
-            ctx.status = 201;
-            logger.info('Group updated.');
-        } catch (error) {
-            throw error;
-        }
-    },
-
-    async updateGroupPolicy(ctx) {
-        try {
-            ctx.body = await groupService.updateGroupPolicy(ctx.request.body);
-            ctx.status = 201;
-            logger.info('Group policy updated.');
-        } catch (error) {
-            throw error;
-        }
-    },
-
-    async updateGroupUser(ctx) {
-        try {
-            ctx.body = await groupService.updateGroupUser(ctx.request.body);
-            ctx.status = 201;
-            logger.info('Group user updated.');
-        } catch (error) {
-            throw error;
-        }
-    },
-};
-
-module.exports = {
-    updateGroup: Group.updateGroup,
-    updateGroupPolicy: Group.updateGroupPolicy,
-    updateGroupUser: Group.updateGroupUser,
-};
diff --git a/app/api/groups/delete.js b/app/api/groups/delete.js
new file mode 100644
index 0000000000000000000000000000000000000000..7d0afb2d33bcbb5bcb5a0ce2c45c353038142e04
--- /dev/null
+++ b/app/api/groups/delete.js
@@ -0,0 +1,25 @@
+"use strict";
+
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+const { deleteGroup } = require("@/app/dal/groupService");
+
+async function deleteGroupHandler(ctx) {
+  const { id } = ctx.params;
+  if (!id) {
+    handleMissingParameters(["id"], ctx);
+  } else {
+    try {
+      await deleteGroup(id);
+      ctx.status = 204;
+    } catch (err) {
+      handleInternalError(err, ctx);
+    }
+  }
+}
+
+module.exports = {
+  deleteGroupHandler,
+};
diff --git a/app/api/groups/get.js b/app/api/groups/get.js
new file mode 100644
index 0000000000000000000000000000000000000000..e4695bcf102705fa8fcc42df16ec695d99da5578
--- /dev/null
+++ b/app/api/groups/get.js
@@ -0,0 +1,34 @@
+"use strict";
+
+const {
+  handleMissingParameters,
+  handleInternalError,
+} = require("@/app/utils/errorHandler");
+const { getAllGroups, getGroup } = require("@/app/dal/groupService");
+
+async function getGroupHandler(ctx) {
+  const { id } = ctx.params;
+  if (!id) {
+    handleMissingParameters(["id"], ctx);
+  }
+  try {
+    ctx.body = await getGroup(id);
+    ctx.status = 200;
+  } catch (error) {
+    handleInternalError(error, ctx);
+  }
+}
+
+async function getAllGroupsHandler(ctx) {
+  try {
+    ctx.body = await getAllGroups();
+    ctx.status = 200;
+  } catch (error) {
+    handleInternalError(error, ctx);
+  }
+}
+
+module.exports = {
+  getAllGroupsHandler,
+  getGroupHandler,
+};
diff --git a/app/api/groups/post.js b/app/api/groups/post.js
new file mode 100644
index 0000000000000000000000000000000000000000..461735f103f6cda7359755ec29ff923c0dac37a7
--- /dev/null
+++ b/app/api/groups/post.js
@@ -0,0 +1,29 @@
+"use strict";
+
+const {
+  handleMissingParameters,
+  handleInternalError,
+} = require("@/app/utils/errorHandler");
+const { createGroup } = require("@/app/dal/groupService");
+
+async function createGroupHandler(ctx) {
+  const { name, description, kc_id } = ctx.request.body;
+  if (!name || !description || !kc_id) {
+    const missingParameters = [];
+    if (!name) missingParameters.push("name");
+    if (!description) missingParameters.push("description");
+    if (!kc_id) missingParameters.push("kc_id");
+    handleMissingParameters(missingParameters, ctx);
+  } else {
+    try {
+      ctx.body = await createGroup(name, description, kc_id);
+      ctx.status = 201;
+    } catch (error) {
+      handleInternalError(error, ctx);
+    }
+  }
+}
+
+module.exports = {
+  createGroupHandler,
+};
diff --git a/app/api/groups/update.js b/app/api/groups/update.js
new file mode 100644
index 0000000000000000000000000000000000000000..6f9d821b1aff7b6c7252b98da31215f668ce8958
--- /dev/null
+++ b/app/api/groups/update.js
@@ -0,0 +1,110 @@
+"use strict";
+
+const {
+  handleMissingParameters,
+  handleInternalError,
+} = require("@/app/utils/errorHandler");
+const {
+  addUserToGroup,
+  addPolicyToGroup,
+  removePolicyFromGroup,
+  removeUserFromGroup,
+  updateGroup,
+} = require("@/app/dal/groupService");
+
+async function updateGroupHandler(ctx) {
+  const { id } = ctx.params;
+  const { name, description } = ctx.request.body;
+  if (!name || !description || !id) {
+    const missingParameters = [];
+    if (!name) missingParameters.push("name");
+    if (!description) missingParameters.push("description");
+    if (!id) missingParameters.push("id");
+    handleMissingParameters(missingParameters, ctx);
+  } else {
+    try {
+      ctx.body = await updateGroup(id, name, description);
+      ctx.status = 200;
+    } catch (error) {
+      handleInternalError(error, ctx);
+    }
+  }
+}
+
+async function addUserToGroupHandler(ctx) {
+  const { id } = ctx.params;
+  const { kc_id } = ctx.request.body;
+  if (!kc_id || !id) {
+    const missingParameters = [];
+    if (!kc_id) missingParameters.push("kc_id");
+    if (!id) missingParameters.push("id");
+    handleMissingParameters(missingParameters, ctx);
+  } else {
+    try {
+      ctx.body = await addUserToGroup(kc_id, id);
+      ctx.status = 201;
+    } catch (error) {
+      handleInternalError(error, ctx);
+    }
+  }
+}
+
+async function removeUserFromGroupHandler(ctx) {
+  const { id, kc_id } = ctx.params;
+  if (!kc_id || !id) {
+    const missingParameters = [];
+    if (!kc_id) missingParameters.push("kc_id");
+    if (!id) missingParameters.push("id");
+    handleMissingParameters(missingParameters, ctx);
+  } else {
+    try {
+      await removeUserFromGroup(kc_id, id);
+      ctx.status = 204;
+    } catch (error) {
+      handleInternalError(error, ctx);
+    }
+  }
+}
+
+async function addPolicyToGroupHandler(ctx) {
+  const { id } = ctx.params;
+  const { policy_id } = ctx.request.body;
+  if (!policy_id || !id) {
+    const missingParameters = [];
+    if (!policy_id) missingParameters.push("policy_id");
+    if (!id) missingParameters.push("id");
+    handleMissingParameters(missingParameters, ctx);
+  } else {
+    try {
+      ctx.body = await addPolicyToGroup(policy_id, id);
+      ctx.status = 201;
+    } catch (error) {
+      handleInternalError(error, ctx);
+    }
+  }
+}
+
+async function removePolicyFromGroupHandler(ctx) {
+  const { policy_id, id } = ctx.params;
+  if (!policy_id || !id) {
+    const missingParameters = [];
+    if (!policy_id) missingParameters.push("policy_id");
+    if (!id) missingParameters.push("id");
+    handleMissingParameters(missingParameters, ctx);
+  } else {
+    try {
+      ctx.body = await removePolicyFromGroup(policy_id, id);
+      ctx.status = 204;
+    } catch (error) {
+      handleInternalError(error, ctx);
+    }
+  }
+}
+
+module.exports = {
+  updateGroupHandler,
+  addUserToGroupHandler,
+  addPolicyToGroupHandler,
+  removeUserFromGroupHandler,
+  removePolicyFromGroupHandler,
+};
diff --git a/app/api/index.js b/app/api/index.js
index a69d35fc0717d34a1f10da4774b1e28a44f88e00..52944e52485cbff91f02c79827ea4ecd9b38a9ba 100644
--- a/app/api/index.js
+++ b/app/api/index.js
@@ -1,106 +1,189 @@
-'use strict'
+"use strict";
 
 const Router = require("koa-router");
 const bodyParser = require("koa-bodyparser");
-/* const { keycloak } = require('../../init-keycloak') */
-
-// Handlers
-const userHandler = require('./users');
-const roleHandler = require('./roles');
-const allocationRoleHandler = require('./role-user');
-const searchHistoryHandler = require('./user-search-history');
-const userRequestHandler = require('./user-requests');
-const groupHandler = require('./group');
-const policyHandler = require('./policy');
-const UserFieldsDisplaySettingsHandler = require("./user-fields-display-settings");
-
 const routers = new Router();
 
-routers.use(bodyParser());
-
-routers.get('/healthcheck', (ctx) => {
-    ctx.res.statusCode = 200;
-    ctx.res.end('OK');
-});
-
-// Users
-routers.post('/user', userHandler.create);
-routers.post('/user/findOne',/* keycloak.protect(),*/ userHandler.user);
-routers.get('/user/find',/* keycloak.protect(),*/ userHandler.users);
-routers.delete('/user/delete',/* keycloak.protect(),*/ userHandler.deleteUser);
-routers.put('/user/update',/* keycloak.protect(),*/ userHandler.update);
-routers.post('/user/kcid', /* keycloak.protect(),*/ userHandler.kcId);
-routers.post('/user/detail', /* keycloak.protect(),*/ userHandler.detail);
-routers.post('/user/assigned-by-role', userHandler.getAssignedUserByRole);
-routers.post('/user/send-mail', userHandler.sendMail);
-routers.post('/user/reset-password', userHandler.resetPassword);
-
-// System admin user
-routers.post('/user/create-system-user', userHandler.createSystemUser);
-routers.get('/user/with-groups-and-roles', userHandler.usersWithGroupAndRole);
-routers.post('/user/one-with-groups-and-roles', userHandler.userWithGroupAndRole);
-
-// Search history
-routers.post('/user/add-history', searchHistoryHandler.create);
-routers.post('/user/fetch-history', searchHistoryHandler.fetch);
-routers.delete('/user/delete-history', searchHistoryHandler.deleteUserSearchHistory);
-
-// User fields display settings
-routers.post('/user/fields-display-settings/', /* keycloak.protect(),*/ UserFieldsDisplaySettingsHandler.createUserFieldsDisplaySettings);
-routers.get('/user/fields-display-settings/:userId',/* keycloak.protect(),*/ UserFieldsDisplaySettingsHandler.findUserFieldsDisplaySettings);
-routers.get('/user/fields-display-settings/',/* keycloak.protect(),*/ UserFieldsDisplaySettingsHandler.findUsersFieldsDisplaySettings);
-routers.put('/user/fields-display-settings/',/* keycloak.protect(),*/ UserFieldsDisplaySettingsHandler.updateUserFieldsDisplaySettings);
-routers.delete('/user/fields-display-settings/:userId',/* keycloak.protect(),*/ UserFieldsDisplaySettingsHandler.deleteUserFieldsDisplaySettings);
-
-// User requests
-routers.post('/user/create-request', userRequestHandler.createRequest);
-routers.delete('/user/delete-request', userRequestHandler.deleteRequest);
-routers.post('/user/process-request', userRequestHandler.processRequest);
-routers.get('/user/list-requests', userRequestHandler.fetchRequests);
-routers.post('/user/list-requests-by-user', userRequestHandler.fetchRequestsByUser);
-routers.get('/user/list-pending-requests', userRequestHandler.fetchPendingRequests);
-
-// Groups
-routers.post('/user/groups', groupHandler.groups);
-routers.post('/user/group-policies', groupHandler.groupPolicies);
-routers.post('/user/group-users', groupHandler.groupUsers);
-routers.post('/user/add-group', groupHandler.createGroup);
-routers.post('/user/add-group-policy', groupHandler.createGroupPolicy);
-routers.post('/user/add-group-user', groupHandler.createGroupUser);
-routers.put('/user/update-group', groupHandler.updateGroup);
-routers.put('/user/update-group-policy', groupHandler.updateGroupPolicy);
-routers.put('/user/update-group-user', groupHandler.updateGroupUser);
-routers.delete('/user/delete-group', groupHandler.deleteGroup);
-routers.delete('/user/delete-group-policy', groupHandler.deleteGroupPolicy);
-routers.delete('/user/delete-group-user', groupHandler.deleteGroupUser);
-
-// Policies
-routers.post('/policy/add', policyHandler.createPolicy);
-routers.delete('/policy/delete', policyHandler.deletePolicy);
-routers.put('/policy/update', policyHandler.updatePolicy);
-routers.get('/policy/list', policyHandler.policies);
-routers.post('/policy/list-by-user', policyHandler.policiesByUser);
-routers.post('/policy/assigned-fields', policyHandler.assignedPolicies);
-routers.get('/policy/policies-with-sources', policyHandler.getPoliciesWithSources);
-routers.post('/policy/policies-with-sources-by-user', policyHandler.getPoliciesWithSourcesByUser);
-routers.post('/policy/policies-with-groups', policyHandler.getGroupDetailsByPolicy);
-routers.post('/policyField/add', policyHandler.createPolicyField);
-routers.delete('/policyField/delete', policyHandler.deletePolicyField);
-routers.put('/policyField/update', policyHandler.updatePolicyField);
-routers.get('/policyField/list', policyHandler.policyFields);
-routers.post('/policySource/add', policyHandler.createPolicySource);
-
-// Roles
-routers.post('/role',/* keycloak.protect(),*/ roleHandler.createRole);
-routers.get('/role/find', /* keycloak.protect(),*/ roleHandler.roles);
-routers.get('/role/findOne', /* keycloak.protect(),*/ roleHandler.role);
-routers.delete('/role/delete', /* keycloak.protect(),*/ roleHandler.deleteRole);
-routers.put('/role/update', /* keycloak.protect(),*/ roleHandler.update);
-
-// Role allocation to users
-routers.post('/allocate-role-to-user', /* keycloak.protect(),*/allocationRoleHandler.create);
-routers.post('/allocatedRoles', /* keycloak.protect(),*/allocationRoleHandler.allocatedRoles);
-routers.put('/allocatedRoles/update', /* keycloak.protect(),*/allocationRoleHandler.update);
-routers.delete('/allocatedRoles/delete',/* keycloak.protect(),*/allocationRoleHandler.deleteAllocatedRole);
+const { getUsersHandler, getUserHandler } = require("@/app/api/users/get");
+const { getOrCreateUserHandler } = require("@/app/api/users/post");
+const { deleteUserHandler } = require("@/app/api/users/delete");
+
+const { getHistoryHandler } = require("@/app/api/user-search-history/get");
+const {
+  addSearchHistoryToUserHandler,
+} = require("@/app/api/user-search-history/post");
+const {
+  deleteHistoryHandler,
+  deleteAllHistoryByUserHandler,
+} = require("@/app/api/user-search-history/delete");
+
+const {
+  getAllRequestsHandler,
+  getAllPendingRequestsHandler,
+  getAllUserRequestsHandler,
+} = require("@/app/api/user-requests/get");
+const {
+  createRequestHandler,
+  updateRequestHandler,
+} = require("@/app/api/user-requests/post");
+const { deleteRequestHandler } = require("@/app/api/user-requests/delete");
+
+const {
+  getAllGroupsHandler,
+  getGroupHandler,
+} = require("@/app/api/groups/get");
+const {
+  addUserToGroupHandler,
+  removeUserFromGroupHandler,
+  addPolicyToGroupHandler,
+  updateGroupHandler,
+  removePolicyFromGroupHandler,
+} = require("@/app/api/groups/update");
+const { createGroupHandler } = require("@/app/api/groups/post");
+const { deleteGroupHandler } = require("@/app/api/groups/delete");
+
+const {
+  getAllPoliciesHandler,
+  getPolicyHandler,
+} = require("@/app/api/policies/get");
+const { createPolicyHandler } = require("@/app/api/policies/post");
+const {
+  updatePolicyHandler,
+  addFieldToPolicyHandler,
+  removeFieldFromPolicyHandler,
+  addSourceToPolicyHandler,
+  removeSourceFromPolicyHandler,
+} = require("@/app/api/policies/update");
+const { deletePolicyHandler } = require("@/app/api/policies/delete");
+
+const {
+  getStdFieldsHandler,
+  getPublicStdFieldsHandler,
+  getStdFieldHandler,
+} = require("@/app/api/std_fields/get");
+
+const {
+  getUserDisplayFieldsHandler,
+} = require("@/app/api/user-display-fields/get");
+
+const { createOrUpdateStdFieldHandler } = require("@/app/api/std_fields/post");
+
+const { deleteAllStdFieldsHandler } = require("@/app/api/std_fields/delete");
+
+const {
+  getSourcesHandler,
+  getSourcesByProviderHandler,
+  getIndexedSourcesByProviderHandler,
+  getIndexedSourcesHandler,
+} = require("@/app/api/sources/get");
+const { createSourceHandler } = require("@/app/api/sources/post");
+const { deleteSourceHandler } = require("@/app/api/sources/delete");
+
+const {
+  createRoleHandler,
+  addUserToRoleHandler,
+  removeUserFromRoleHandler,
+} = require("@/app/api/roles/post");
+const { getRolesHandler, getRoleHandler } = require("@/app/api/roles/get");
+const { updateRoleHandler } = require("@/app/api/roles/put");
+const { deleteRoleHandler } = require("@/app/api/roles/delete");
+
+const { getQueryResultsHandler } = require("@/app/api/search/post");
+const { setUserDisplayFieldsHandler } = require("./user-display-fields/post");
+
+routers.use(
+  bodyParser({ formLimit: "700mb", jsonLimit: "700mb", textLimit: "700mb" })
+);
+
+// search
+routers.post("/search", getQueryResultsHandler);
+
+// users
+routers.get("/users", getUsersHandler);
+routers.get("/users/:kc_id", getUserHandler);
+routers.post("/users", getOrCreateUserHandler);
+routers.delete("/users/:kc_id", deleteUserHandler);
+
+// search-history
+routers.get("/users/:kc_id/history", getHistoryHandler);
+routers.post("/users/:kc_id/history", addSearchHistoryToUserHandler);
+routers.delete("/users/:kc_id/history", deleteAllHistoryByUserHandler);
+routers.delete("/users/:kc_id/history/:id", deleteHistoryHandler);
+
+// user requests
+routers.get("/user-requests", getAllRequestsHandler);
+routers.get("/user-requests/pending", getAllPendingRequestsHandler);
+routers.get("/users/:kc_id/requests", getAllRequestsHandler);
+routers.get("/users/:kc_id/requests/pending", getAllUserRequestsHandler);
+routers.post("/users/:kc_id/requests", createRequestHandler);
+routers.post("/user-requests/:id", updateRequestHandler);
+routers.delete("/user-requests/:id", deleteRequestHandler);
+
+// user display fields
+routers.get("/users/:kc_id/fields", getUserDisplayFieldsHandler);
+routers.post("/users/:kc_id/fields", setUserDisplayFieldsHandler);
+
+// groups
+routers.get("/groups", getAllGroupsHandler);
+routers.get("/groups/:id", getGroupHandler);
+routers.post("/groups", createGroupHandler);
+routers.put("/groups/:id", updateGroupHandler);
+routers.delete("/groups/:id", deleteGroupHandler);
+
+// groups users
+routers.post("/groups/:id/users", addUserToGroupHandler);
+routers.delete("/groups/:id/users/:kc_id", removeUserFromGroupHandler);
+
+// groups policies
+routers.post("/groups/:id/policies", addPolicyToGroupHandler);
+routers.delete("/groups/:id/policies/:policy_id", removePolicyFromGroupHandler);
+
+// policy
+routers.get("/policies", getAllPoliciesHandler);
+routers.get("/policies/:id", getPolicyHandler);
+routers.post("/policies", createPolicyHandler);
+routers.put("/policy/update", updatePolicyHandler);
+routers.delete("/policies/:id", deletePolicyHandler);
+
+// policy std_fields
+routers.post("/policies/:id/std_fields", addFieldToPolicyHandler);
+routers.delete(
+  "/policies/:id/std_fields/:field_id",
+  removeFieldFromPolicyHandler
+);
+
+// policy sources
+routers.post("/policies/:id/sources", addSourceToPolicyHandler);
+routers.delete(
+  "/policies/:id/sources/:source_id",
+  removeSourceFromPolicyHandler
+);
+
+// std_fields
+routers.get("/std_fields", getStdFieldsHandler);
+routers.get("/public_std_fields", getPublicStdFieldsHandler);
+routers.get("/std_fields/:id", getStdFieldHandler);
+routers.post("/std_fields", createOrUpdateStdFieldHandler);
+routers.put("/std_fields/:id", createOrUpdateStdFieldHandler);
+routers.delete("/std_fields", deleteAllStdFieldsHandler);
+
+// sources
+routers.get("/sources", getSourcesHandler);
+routers.get("/sources/:kc_id", getSourcesByProviderHandler);
+routers.post("/sources", createSourceHandler);
+routers.get("/indexed-sources", getIndexedSourcesHandler);
+routers.get("/indexed-sources/:kc_id", getIndexedSourcesByProviderHandler);
+routers.delete("/sources/:id", deleteSourceHandler);
+
+// roles
+routers.get("/roles", getRolesHandler);
+routers.get("/roles/:id", getRoleHandler);
+routers.post("/roles", createRoleHandler);
+routers.put("/roles/:id", updateRoleHandler);
+routers.delete("/roles/:id", deleteRoleHandler);
+
+// role users
+routers.post("/roles/:id/users", addUserToRoleHandler);
+routers.delete("/roles/:id/users/:kc_id", removeUserFromRoleHandler);
 
 module.exports = routers;
diff --git a/app/api/policies/delete.js b/app/api/policies/delete.js
new file mode 100644
index 0000000000000000000000000000000000000000..ab36df35a405093651d1ac2830aaac0a58a97835
--- /dev/null
+++ b/app/api/policies/delete.js
@@ -0,0 +1,25 @@
+"use strict";
+
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+const { deletePolicy } = require("@/app/dal/policyService");
+
+async function deletePolicyHandler(ctx) {
+  const { id } = ctx.params;
+  if (!id) {
+    handleMissingParameters(["id"], ctx);
+  } else {
+    try {
+      ctx.body = await deletePolicy(id);
+      ctx.status = 204;
+    } catch (err) {
+      handleInternalError(err, ctx);
+    }
+  }
+}
+
+module.exports = {
+  deletePolicyHandler,
+};
diff --git a/app/api/policies/get.js b/app/api/policies/get.js
new file mode 100644
index 0000000000000000000000000000000000000000..560e0ad26fa368d8cc5158c65a17b2561752f940
--- /dev/null
+++ b/app/api/policies/get.js
@@ -0,0 +1,35 @@
+"use strict";
+
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+const { getAllPolicies, getPolicy } = require("@/app/dal/policyService");
+
+async function getAllPoliciesHandler(ctx) {
+  try {
+    ctx.body = await getAllPolicies();
+    ctx.status = 200;
+  } catch (error) {
+    handleInternalError(error, ctx);
+  }
+}
+
+async function getPolicyHandler(ctx) {
+  const { id } = ctx.params;
+  if (!id) {
+    handleMissingParameters(["id"], ctx);
+  } else {
+    try {
+      ctx.body = await getPolicy(id);
+      ctx.status = 200;
+    } catch (error) {
+      handleInternalError(error, ctx);
+    }
+  }
+}
+
+module.exports = {
+  getAllPoliciesHandler,
+  getPolicyHandler,
+};
diff --git a/app/api/policies/post.js b/app/api/policies/post.js
new file mode 100644
index 0000000000000000000000000000000000000000..13bfd4354b9f945b5fc7edcd958b9717b1b0fa63
--- /dev/null
+++ b/app/api/policies/post.js
@@ -0,0 +1,28 @@
+"use strict";
+
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+const { createPolicy } = require("@/app/dal/policyService");
+
+async function createPolicyHandler(ctx) {
+  const { name, kc_id } = ctx.request.body;
+  if (!name || !kc_id) {
+    const missingParameters = [];
+    if (!name) missingParameters.push("name");
+    if (!kc_id) missingParameters.push("kc_id");
+    handleMissingParameters(missingParameters, ctx);
+  } else {
+    try {
+      ctx.body = await createPolicy(name, kc_id);
+      ctx.status = 201;
+    } catch (err) {
+      handleInternalError(err, ctx);
+    }
+  }
+}
+
+module.exports = {
+  createPolicyHandler,
+};
diff --git a/app/api/policies/update.js b/app/api/policies/update.js
new file mode 100644
index 0000000000000000000000000000000000000000..d81d803faaa9e198152fc674af79395f979c9004
--- /dev/null
+++ b/app/api/policies/update.js
@@ -0,0 +1,110 @@
+"use strict";
+
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+const {
+  updatePolicy,
+  addFieldToPolicy,
+  removeFieldFromPolicy,
+  addSourceToPolicy,
+  removeSourceFromPolicy,
+} = require("@/app/dal/policyService");
+
+async function updatePolicyHandler(ctx) {
+  const { id } = ctx.params;
+  const { name, isDefault } = ctx.request.body;
+  if (!id || !name || !isDefault) {
+    const missingParameters = [];
+    if (!id) missingParameters.push("id");
+    if (!name) missingParameters.push("name");
+    if (!isDefault) missingParameters.push("isDefault");
+    handleMissingParameters(missingParameters, ctx);
+  } else {
+    try {
+      ctx.body = await updatePolicy(id, name, isDefault);
+      ctx.status = 204;
+    } catch (error) {
+      handleInternalError(error, ctx);
+    }
+  }
+}
+
+async function addFieldToPolicyHandler(ctx) {
+  const { id } = ctx.params;
+  const { field_id } = ctx.request.body;
+  if (!id || !field_id) {
+    const missingParameters = [];
+    if (!id) missingParameters.push("id");
+    if (!field_id) missingParameters.push("field_id");
+    handleMissingParameters(missingParameters, ctx);
+  } else {
+    try {
+      ctx.body = await addFieldToPolicy(field_id, id);
+      ctx.status = 201;
+    } catch (error) {
+      handleInternalError(error, ctx);
+    }
+  }
+}
+
+async function removeFieldFromPolicyHandler(ctx) {
+  const { id, field_id } = ctx.params;
+  if (!id || !field_id) {
+    const missingParameters = [];
+    if (!id) missingParameters.push("id");
+    if (!field_id) missingParameters.push("field_id");
+    handleMissingParameters(missingParameters, ctx);
+  } else {
+    try {
+      ctx.body = await removeFieldFromPolicy(field_id, id);
+      ctx.status = 204;
+    } catch (err) {
+      handleInternalError(err, ctx);
+    }
+  }
+}
+
+async function addSourceToPolicyHandler(ctx) {
+  const { id } = ctx.params;
+  const { source_id } = ctx.request.body;
+  if (!id || !source_id) {
+    const missingParameters = [];
+    if (!id) missingParameters.push("id");
+    if (!source_id) missingParameters.push("source_id");
+    handleMissingParameters(missingParameters, ctx);
+  } else {
+    try {
+      ctx.body = await addSourceToPolicy(source_id, id);
+      ctx.status = 201;
+    } catch (error) {
+      handleInternalError(error, ctx);
+    }
+  }
+}
+
+async function removeSourceFromPolicyHandler(ctx) {
+  const { id, source_id } = ctx.params;
+  if (!id || !source_id) {
+    const missingParameters = [];
+    if (!id) missingParameters.push("id");
+    if (!source_id) missingParameters.push("source_id");
+    handleMissingParameters(missingParameters, ctx);
+  } else {
+    try {
+      await removeSourceFromPolicy(source_id, id);
+      ctx.status = 204;
+    } catch (err) {
+      handleInternalError(err, ctx);
+    }
+  }
+}
+
+module.exports = {
+  updatePolicyHandler,
+  addFieldToPolicyHandler,
+  removeFieldFromPolicyHandler,
+  addSourceToPolicyHandler,
+  removeSourceFromPolicyHandler,
+};
diff --git a/app/api/policy/delete.js b/app/api/policy/delete.js
deleted file mode 100644
index 4a75dceb9babc969419b910195765a0bd9badcaa..0000000000000000000000000000000000000000
--- a/app/api/policy/delete.js
+++ /dev/null
@@ -1,31 +0,0 @@
-'use strict'
-
-const policyService = require('../../dal/policyService');
-const logger = require('../../utils/logger');
-
-const Policy = {
-    async deletePolicy(ctx) {
-        try {
-            ctx.body = await policyService.deletePolicy(ctx.request.body);
-            ctx.status = 201;
-            logger.info('Policy deleted.');
-        } catch (error) {
-            throw error;
-        }
-    },
-
-    async deletePolicyField(ctx) {
-        try {
-            ctx.body = await policyService.deletePolicyField(ctx.request.body);
-            ctx.status = 201;
-            logger.info('PolicyField deleted.');
-        } catch (error) {
-            throw error;
-        }
-    }
-};
-
-module.exports = {
-    deletePolicy: Policy.deletePolicy,
-    deletePolicyField: Policy.deletePolicyField
-};
diff --git a/app/api/policy/get.js b/app/api/policy/get.js
deleted file mode 100644
index 61abfad228e78a6f2b9cd79b852c89c809b82455..0000000000000000000000000000000000000000
--- a/app/api/policy/get.js
+++ /dev/null
@@ -1,64 +0,0 @@
-'use strict'
-
-const policyService = require('../../dal/policyService');
-const logger = require('../../utils/logger');
-
-const Policy = {
-    async policies(ctx) {
-        try {
-            ctx.body = await policyService.policies();
-            ctx.status = 201;
-            logger.info('Policies fetched.');
-        } catch (error) {
-            throw error;
-        }
-    },
-
-    async policyFields(ctx) {
-        try {
-            ctx.body = await policyService.policyFields();
-            ctx.status = 201;
-            logger.info('Policy fields fetched.');
-        } catch (error) {
-            throw error;
-        }
-    },
-
-    async assignedPolicies(ctx) {
-        try {
-            ctx.body = await policyService.getAssignedPolicies(ctx.request.body);
-            ctx.status = 201;
-            logger.info('Assigned policies fetched.');
-        } catch (error) {
-            throw error;
-        }
-    },
-
-    async getPoliciesWithSources(ctx) {
-        try {
-            ctx.body = await policyService.getPoliciesWithSources();
-            ctx.status = 201;
-            logger.info('Policies with sources fetched.');
-        } catch (error) {
-            throw error;
-        }
-    },
-
-    async getGroupDetailsByPolicy(ctx) {
-        try {
-            ctx.body = await policyService.getGroupDetailsByPolicy(ctx.request.body);
-            ctx.status = 201;
-            logger.info('Group details by policy fetched.');
-        } catch (error) {
-            throw error;
-        }
-    }
-};
-
-module.exports = {
-    policies: Policy.policies,
-    policyFields: Policy.policyFields,
-    assignedPolicies: Policy.assignedPolicies,
-    getPoliciesWithSources: Policy.getPoliciesWithSources,
-    getGroupDetailsByPolicy: Policy.getGroupDetailsByPolicy
-};
diff --git a/app/api/policy/index.js b/app/api/policy/index.js
deleted file mode 100644
index 7eb03f9d4059f9981b63aca9cc7bc3da3ec13c21..0000000000000000000000000000000000000000
--- a/app/api/policy/index.js
+++ /dev/null
@@ -1,25 +0,0 @@
-'use strict'
-
-const { createPolicy, createPolicyField, createPolicySource, policiesByUser, getPoliciesWithSourcesByUser } = require('./post')
-const { updatePolicy, updatePolicyField } = require('./update')
-const { deletePolicy, deletePolicyField } = require('./delete')
-const { policies, policyFields, assignedPolicies, getPoliciesWithSources, getGroupDetailsByPolicy } = require('./get')
-
-const PolicyHandler = {
-    createPolicy,
-    createPolicyField,
-    updatePolicy,
-    updatePolicyField,
-    deletePolicy,
-    deletePolicyField,
-    policies,
-    policiesByUser,
-    policyFields,
-    assignedPolicies,
-    getPoliciesWithSources,
-    getPoliciesWithSourcesByUser,
-    getGroupDetailsByPolicy,
-    createPolicySource
-}
-
-module.exports = PolicyHandler
\ No newline at end of file
diff --git a/app/api/policy/post.js b/app/api/policy/post.js
deleted file mode 100644
index a04c6bb89819b12671c987d64ade4acbfd4227ce..0000000000000000000000000000000000000000
--- a/app/api/policy/post.js
+++ /dev/null
@@ -1,64 +0,0 @@
-'use strict'
-
-const policyService = require('../../dal/policyService');
-const logger = require('../../utils/logger');
-
-const Policy = {
-    async createPolicy(ctx) {
-        try {
-            ctx.body = await policyService.createPolicy(ctx.request.body);
-            ctx.status = 201;
-            logger.info('Policy created.');
-        } catch (error) {
-            throw error;
-        }
-    },
-
-    async createPolicyField(ctx) {
-        try {
-            ctx.body = await policyService.createPolicyField(ctx.request.body);
-            ctx.status = 201;
-            logger.info('PolicyField created.');
-        } catch (error) {
-            throw error;
-        }
-    },
-
-    async createPolicySource(ctx) {
-        try {
-            ctx.body = await policyService.createPolicySource(ctx.request.body);
-            ctx.status = 201;
-            logger.info('PolicySource created.');
-        } catch (error) {
-            throw error;
-        }
-    },
-
-    async policiesByUser(ctx) {
-        try {
-            ctx.body = await policyService.policiesByUser(ctx.request.body);
-            ctx.status = 201;
-            logger.info('Policies by user listed.');
-        } catch (error) {
-            throw error;
-        }
-    },
-
-    async getPoliciesWithSourcesByUser(ctx) {
-        try {
-            ctx.body = await policyService.getPoliciesWithSourcesByUser(ctx.request.body);
-            ctx.status = 201;
-            logger.info('Policies with sources by user listed.');
-        } catch (error) {
-            throw error;
-        }
-    }
-};
-
-module.exports = {
-    policiesByUser: Policy.policiesByUser,
-    getPoliciesWithSourcesByUser: Policy.getPoliciesWithSourcesByUser,
-    createPolicy: Policy.createPolicy,
-    createPolicyField: Policy.createPolicyField,
-    createPolicySource: Policy.createPolicySource
-};
diff --git a/app/api/policy/update.js b/app/api/policy/update.js
deleted file mode 100644
index 9afd22e22505a37b71d206401f834ab46214f897..0000000000000000000000000000000000000000
--- a/app/api/policy/update.js
+++ /dev/null
@@ -1,31 +0,0 @@
-'use strict'
-
-const policyService = require('../../dal/policyService');
-const logger = require('../../utils/logger');
-
-const Policy = {
-    async updatePolicy(ctx) {
-        try {
-            ctx.body = await policyService.updatePolicy(ctx.request.body);
-            ctx.status = 201;
-            logger.info('Policy updated.');
-        } catch (error) {
-            throw error;
-        }
-    },
-
-    async updatePolicyField(ctx) {
-        try {
-            ctx.body = await policyService.updatePolicyField(ctx.request.body);
-            ctx.status = 201;
-            logger.info('Policy field updated.');
-        } catch (error) {
-            throw error;
-        }
-    }
-};
-
-module.exports = {
-    updatePolicy: Policy.updatePolicy,
-    updatePolicyField: Policy.updatePolicyField,
-};
diff --git a/app/api/realm/delete.js b/app/api/realm/delete.js
deleted file mode 100644
index b6b49bad17c9eb71451b1252fa04993bba14246f..0000000000000000000000000000000000000000
--- a/app/api/realm/delete.js
+++ /dev/null
@@ -1,24 +0,0 @@
-'use strict'
-
-const realmService = require('../../dal/realmService')
-const logger = require('../../utils/logger')
-const util = require('util')
-
-const DeleteRealm = {
-    async deleteRealm(ctx) {
-        try {
-            ctx.body = await realmService.delete(ctx.request.body)
-            ctx.status = 201
-            logger.info('realm is deleted successfully!')
-        } catch (error) {
-            ctx.body = err || 'Error occurred!'
-            ctx.status = 500;
-            logger.error(`Caught error: ${JSON.stringify(util.inspect(err, { compact: false, depth: 1, breakLength: 80 }))}`)
-        }
-    }
-}
-
-module.exports = {
-    deleteRealm: DeleteRealm.deleteRealm,
-    DeleteRealm
-}
diff --git a/app/api/realm/get.js b/app/api/realm/get.js
deleted file mode 100644
index cdef5b9cde4033ecb73d9ef0c08fb45a525915fb..0000000000000000000000000000000000000000
--- a/app/api/realm/get.js
+++ /dev/null
@@ -1,38 +0,0 @@
-'use strict'
-
-const realmService = require('../../dal/realmService')
-const logger = require('../../utils/logger')
-const util = require('util')
-
-const GetRealm = {
-    async find(ctx) {
-        try {
-            ctx.body = await realmService.realms()
-            ctx.status = 201
-            logger.info('realms are listed successfully!')
-        } catch (error) {
-            ctx.body = err || 'Error occurred!'
-            ctx.status = 500;
-            logger.error(`Caught error: ${JSON.stringify(util.inspect(error, { compact: false, depth: 1, breakLength: 80 }))}`)
-        }
-    },
-
-    async findOne(ctx) {
-        try {
-            ctx.body = await realmService.realm(ctx.request.body)
-            ctx.status = 201
-            logger.info('realm is found successfully!')
-        } catch (error) {
-            ctx.body = err || 'Error occurred!'
-            ctx.status = 500;
-            logger.error(`Caught error: ${JSON.stringify(util.inspect(error, { compact: false, depth: 1, breakLength: 80 }))}`)
-        }
-    }
-
-}
-
-module.exports = {
-    realms: GetRealm.find,
-    realm: GetRealm.findOne,
-    GetRealm
-}
diff --git a/app/api/realm/index.js b/app/api/realm/index.js
deleted file mode 100644
index 923d096404201b13de0011586d5ea3e658327324..0000000000000000000000000000000000000000
--- a/app/api/realm/index.js
+++ /dev/null
@@ -1 +0,0 @@
-'use strict'
\ No newline at end of file
diff --git a/app/api/realm/post.js b/app/api/realm/post.js
deleted file mode 100644
index d60ac09e9aa97dc6515144c78537054423dd2399..0000000000000000000000000000000000000000
--- a/app/api/realm/post.js
+++ /dev/null
@@ -1,24 +0,0 @@
-"use strict"
-
-const realmService = require("../../dal/realmService")
-const logger = require("../../utils/logger")
-const util = require('util')
-
-const AddRealm = {
-    async AddNewRealm(ctx) {
-        try {
-            ctx.body = await realmService.create(ctx.request.body)
-            ctx.status = 201
-            logger.info('realm is created successfully!')
-        } catch (error) {
-            ctx.body = err.response.data || 'Error occurred!'
-            ctx.status = 500
-            logger.error(`Caught error: ${JSON.stringify(util.inspect(error, { compact: false, depth: 1, breakLength: 80 }))}`)
-        }
-    }
-}
-
-module.exports = {
-    addRealm: AddRealm.AddNewRealm,
-    AddRealm
-}
diff --git a/app/api/realm/put.js b/app/api/realm/put.js
deleted file mode 100644
index adfa37c0db7a55484b8b04cdf3abfbead842f79e..0000000000000000000000000000000000000000
--- a/app/api/realm/put.js
+++ /dev/null
@@ -1,24 +0,0 @@
-'use strict'
-
-const realmService = require("../../dal/realmService");
-const logger = require('../../utils/logger')
-const util = require('util')
-
-const UpdateRealm = {
-    async update(ctx) {
-        try {
-            ctx.body = await realmService.update(ctx.request.body);
-            ctx.status = 201
-            logger.info('realm is updated successfully!')
-        } catch (error) {
-            ctx.body = err || 'Error occurred!'
-            ctx.status = 500
-            logger.error(`Caught error: ${JSON.stringify(util.inspect(err, { compact: false, depth: 1, breakLength: 80 }))}`)
-        }
-    }
-}
-
-module.exports = {
-    update: UpdateRealm.update,
-    UpdateRealm
-}
diff --git a/app/api/role-user/delete.js b/app/api/role-user/delete.js
deleted file mode 100644
index ef7c9d1fbea7f49c0129c3aaa800ec056464c0f9..0000000000000000000000000000000000000000
--- a/app/api/role-user/delete.js
+++ /dev/null
@@ -1,21 +0,0 @@
-'use strict'
-
-const roleAllocationService = require("../../dal/roleAllocationService");
-const logger = require("../../utils/logger");
-
-const DeleteAllocatedRole = {
-    async delete(ctx) {
-        try {
-            ctx.body = await roleAllocationService.delete(ctx.request.body);
-            ctx.status = 201;
-            logger.info('Role allocated to user deleted.');
-        } catch (error) {
-            throw error;
-        }
-    }
-};
-
-module.exports = {
-    deleteAllocatedRole: DeleteAllocatedRole.delete,
-    DeleteAllocatedRole
-};
diff --git a/app/api/role-user/get.js b/app/api/role-user/get.js
deleted file mode 100644
index 993607610fa5e184058bce9e87dfdd521f9bbb14..0000000000000000000000000000000000000000
--- a/app/api/role-user/get.js
+++ /dev/null
@@ -1,21 +0,0 @@
-'use strict'
-
-const roleAllocationService = require("../../dal/roleAllocationService");
-const logger = require("../../utils/logger");
-
-const GetAllocatedRole = {
-    async find(ctx) {
-        try {
-            ctx.body = await roleAllocationService.allocatedRoles(ctx.request.body);
-            ctx.status = 201;
-            logger.info('User allocated roles fetched.');
-        } catch (error) {
-            throw error;
-        }
-    }
-};
-
-module.exports = {
-    allocatedRoles: GetAllocatedRole.find,
-    GetAllocatedRole
-};
diff --git a/app/api/role-user/index.js b/app/api/role-user/index.js
deleted file mode 100644
index 19a8e5234a324a09dbb05cc6a480ae7a4d0ddc4a..0000000000000000000000000000000000000000
--- a/app/api/role-user/index.js
+++ /dev/null
@@ -1,15 +0,0 @@
-'use strict'
-
-const { create } = require("./post");
-const { allocatedRoles } = require('./get');
-const { update } = require('./put');
-const { deleteAllocatedRole } = require('./delete');
-
-const AllocationRoleHandler = {
-    create,
-    allocatedRoles,
-    update,
-    deleteAllocatedRole,
-};
-
-module.exports = AllocationRoleHandler;
diff --git a/app/api/role-user/post.js b/app/api/role-user/post.js
deleted file mode 100644
index 0e1c04b94222162d4f5e0b76cc0c1d095578387a..0000000000000000000000000000000000000000
--- a/app/api/role-user/post.js
+++ /dev/null
@@ -1,21 +0,0 @@
-'use strict'
-
-const roleAllocationService = require("../../dal/roleAllocationService");
-const logger = require("../../utils/logger");
-
-const AllocateRoleToUser = {
-    async create(ctx) {
-        try {
-            ctx.body = await roleAllocationService.create(ctx.request.body);
-            ctx.status = 201;
-            logger.info('Role allocated to user.');
-        } catch (error) {
-            throw error;
-        }
-    }
-};
-
-module.exports = {
-    create: AllocateRoleToUser.create,
-    AllocateRoleToUser
-};
diff --git a/app/api/role-user/put.js b/app/api/role-user/put.js
deleted file mode 100644
index 9cebeaec1d0499290f9b10fb19cee14c046867ae..0000000000000000000000000000000000000000
--- a/app/api/role-user/put.js
+++ /dev/null
@@ -1,21 +0,0 @@
-'use strict'
-
-const roleAllocationService = require("../../dal/roleAllocationService");
-const logger = require("../../utils/logger");
-
-const UpdateAllocatedRole = {
-    async update(ctx) {
-        try {
-            ctx.body = await roleAllocationService.update(ctx.request.body);
-            ctx.status = 201;
-            logger.info('Role allocated to user updated.');
-        } catch (error) {
-            throw error;
-        }
-    }
-};
-
-module.exports = {
-    update: UpdateAllocatedRole.update,
-    UpdateAllocatedRole
-};
diff --git a/app/api/roles/delete.js b/app/api/roles/delete.js
index cd637740aace15ec2a9ebf4b5b575a61cb94d946..bdc9772f24fdcc8af26ab322938570dc46d0a082 100644
--- a/app/api/roles/delete.js
+++ b/app/api/roles/delete.js
@@ -1,21 +1,25 @@
-'use strict'
+"use strict";
 
-const roleService = require('../../dal/roleService');
-const logger = require('../../utils/logger');
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+const { deleteRole } = require("@/app/dal/roleService");
 
-const DeleteRole = {
-    async deleteRole(ctx) {
-        try {
-            ctx.body = await roleService.delete(ctx.request.body);
-            ctx.status = 201;
-            logger.info('Role deleted.');
-        } catch (error) {
-            throw error;
-        }
+async function deleteRoleHandler(ctx) {
+  const { id } = ctx.params;
+  if (!id) {
+    handleMissingParameters(["id"], ctx);
+  } else {
+    try {
+      ctx.body = await deleteRole(id);
+      ctx.status = 204;
+    } catch (err) {
+      handleInternalError(err, ctx);
     }
-};
+  }
+}
 
 module.exports = {
-    deleteRole: DeleteRole.deleteRole,
-    DeleteRole,
+  deleteRoleHandler,
 };
diff --git a/app/api/roles/get.js b/app/api/roles/get.js
index 9ae5a0ffd9545e5d9b92ea98fb194b56136909c1..ab85ed4df675907c7249d6883c79e4721b7d93d3 100644
--- a/app/api/roles/get.js
+++ b/app/api/roles/get.js
@@ -1,32 +1,50 @@
-'use strict'
+"use strict";
 
-const roleService = require("../../dal/roleService");
-const logger = require('../../utils/logger');
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("../../utils/errorHandler");
+const { getRoles, getRole, getUserRoles } = require("../../dal/roleService");
 
-const GetRole = {
-    async find(ctx) {
-        try {
-            ctx.body = await roleService.roles();
-            ctx.status = 201;
-            logger.info('Roles fetched.');
-        } catch (error) {
-            throw error;
-        }
-    },
+async function getRolesHandler(ctx) {
+  try {
+    ctx.body = await getRoles();
+    ctx.status = 200;
+  } catch (err) {
+    handleInternalError(err, ctx);
+  }
+}
 
-    async findOne(ctx) {
-        try {
-            ctx.body = await roleService.role(ctx.request.body);
-            ctx.status = 201;
-            logger.info('Role fetched.');
-        } catch (error) {
-            throw error;
-        }
+async function getRoleHandler(ctx) {
+  const { id } = ctx.params;
+  if (!id) {
+    handleMissingParameters(["id"], ctx);
+  } else {
+    try {
+      ctx.body = await getRole(id);
+      ctx.status = 200;
+    } catch (err) {
+      handleInternalError(err, ctx);
     }
-};
+  }
+}
+
+async function getUserRolesHandler(ctx) {
+  const { kc_id } = ctx.request.body;
+  if (!kc_id) {
+    handleMissingParameters(["kc_id"], ctx);
+  } else {
+    try {
+      ctx.body = await getUserRoles(kc_id);
+      ctx.status = 200;
+    } catch (err) {
+      handleInternalError(err, ctx);
+    }
+  }
+}
 
 module.exports = {
-    roles: GetRole.find,
-    role: GetRole.findOne,
-    GetRole
+  getRolesHandler,
+  getRoleHandler,
+  getUserRolesHandler,
 };
diff --git a/app/api/roles/index.js b/app/api/roles/index.js
deleted file mode 100644
index 0cc31dacb696235b5678fab18893b90008e6186c..0000000000000000000000000000000000000000
--- a/app/api/roles/index.js
+++ /dev/null
@@ -1,17 +0,0 @@
-'use strict'
-
-const { createRole } = require('./post');
-const { roles } = require('./get');
-const { role } = require('./get');
-const { deleteRole } = require('./delete');
-const { update } = require('./put');
-
-const RoleHandler = {
-    createRole,
-    roles,
-    role,
-    deleteRole,
-    update,
-};
-
-module.exports = RoleHandler;
diff --git a/app/api/roles/post.js b/app/api/roles/post.js
index 58c83a55f52d3a8438f3535c117cbf6f745f4f12..02353882a1bb24a30418b6f6e32e693270739f5a 100644
--- a/app/api/roles/post.js
+++ b/app/api/roles/post.js
@@ -1,21 +1,77 @@
-'use strict'
+"use strict";
 
-const roleService = require("../../dal/roleService");
-const logger = require('../../utils/logger');
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+const {
+  createRole,
+  addUserToRole,
+  removeUserFromRole,
+} = require("@/app/dal/roleService");
 
-const AddRole = {
-    async create(ctx) {
-        try {
-            ctx.body = await roleService.create(ctx.request.body);
-            ctx.status = 201;
-            logger.info('Role created.');
-        } catch (error) {
-            throw error;
-        }
+async function createRoleHandler(ctx) {
+  const { name, description } = ctx.request.body;
+  if (!name || !description) {
+    const missingParameters = [];
+    if (!name) {
+      missingParameters.push("name");
     }
-};
+    if (!description) {
+      missingParameters.push("description");
+    }
+    handleMissingParameters(missingParameters, ctx);
+  } else {
+    try {
+      ctx.body = await createRole(name, description);
+      ctx.status = 201;
+    } catch (err) {
+      handleInternalError(err, ctx);
+    }
+  }
+}
+
+async function addUserToRoleHandler(ctx) {
+  const { id } = ctx.params;
+  const { kc_id } = ctx.request.body;
+  if (!id || !kc_id) {
+    const missingParameters = [];
+    if (!id) {
+      missingParameters.push("id");
+    }
+    if (!kc_id) {
+      missingParameters.push("kc_id");
+    }
+    handleMissingParameters(missingParameters, ctx);
+  } else {
+    try {
+      ctx.body = await addUserToRole(kc_id, id);
+      ctx.status = 201;
+    } catch (err) {
+      handleInternalError(err, ctx);
+    }
+  }
+}
+
+async function removeUserFromRoleHandler(ctx) {
+  const { id, kc_id } = ctx.params;
+  if (!kc_id || !id) {
+    const missingParameters = [];
+    if (!kc_id) missingParameters.push("kc_id");
+    if (!id) missingParameters.push("id");
+    handleMissingParameters(missingParameters, ctx);
+  } else {
+    try {
+      ctx.body = await removeUserFromRole(kc_id, id);
+      ctx.status = 204;
+    } catch (error) {
+      handleInternalError(error, ctx);
+    }
+  }
+}
 
 module.exports = {
-    createRole: AddRole.create,
-    AddRole
+  createRoleHandler,
+  addUserToRoleHandler,
+  removeUserFromRoleHandler,
 };
diff --git a/app/api/roles/put.js b/app/api/roles/put.js
index 9ed289b9aab7c1e26b04ea1ec4883bb655d79e5f..94ab26eec5a72424fd536a1d8eee8b1f217f6086 100644
--- a/app/api/roles/put.js
+++ b/app/api/roles/put.js
@@ -1,21 +1,36 @@
-'use strict'
+"use strict";
 
-const roleService = require('../../dal/roleService');
-const logger = require('../../utils/logger');
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("../../utils/errorHandler");
+const { updateRole } = require("../../dal/roleService");
 
-const UpdateRole = {
-    async update(ctx) {
-        try {
-            ctx.body = await roleService.update(ctx.request.body);
-            ctx.status = 201;
-            logger.info('Role updated.');
-        } catch (error) {
-            throw error;
-        }
+async function updateRoleHandler(ctx) {
+  const { id } = ctx.params;
+  const { name, description } = ctx.request.body;
+  if (!id || !name || !description) {
+    const missingParameters = [];
+    if (!id) {
+      missingParameters.push("id");
     }
-};
+    if (!name) {
+      missingParameters.push("name");
+    }
+    if (!description) {
+      missingParameters.push("description");
+    }
+    handleMissingParameters(missingParameters, ctx);
+  } else {
+    try {
+      ctx.body = await updateRole(id, name, description);
+      ctx.status = 204;
+    } catch (err) {
+      handleInternalError(err, ctx);
+    }
+  }
+}
 
 module.exports = {
-    update: UpdateRole.update,
-    UpdateRole
+  updateRoleHandler,
 };
diff --git a/app/api/search/post.js b/app/api/search/post.js
new file mode 100644
index 0000000000000000000000000000000000000000..c7c9f07f7834eca6310cf04ab352a23fe3153b07
--- /dev/null
+++ b/app/api/search/post.js
@@ -0,0 +1,63 @@
+const {
+    handleInternalError,
+    handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+const {search} = require("@/app/dal/elasticService");
+const logger = require("@/app/utils/format");
+
+async function getQueryResultsHandler(ctx) {
+    logger.debug("getQueryResultsHandler");
+    const {
+        query,
+        sourcesId,
+        fieldsId,
+        scroll_id,
+        advancedQuery = false,
+    } = ctx.request.body;
+    if (!query || !sourcesId || !fieldsId) {
+        const missingParams = [];
+        if (!query) missingParams.push("query");
+        if (!sourcesId) missingParams.push("sourcesId");
+        if (!fieldsId) missingParams.push("fieldsId");
+        handleMissingParameters(missingParams, ctx);
+    } else {
+        try {
+            logger.debug(`query: ${JSON.stringify(query)}`);
+            logger.debug(`sourcesId: ${sourcesId}`);
+            if (!Array.isArray(sourcesId)) {
+                handleInternalError(new Error("Invalid sourcesId"), ctx);
+            }
+            const allNumbers = sourcesId.every((id) => typeof id === "number");
+            if (!allNumbers) {
+                handleInternalError(new Error("Invalid sourcesId"), ctx);
+            } else {
+                const result = await search({
+                    query,
+                    sourcesId,
+                    scroll_id,
+                    advancedQuery,
+                });
+                logger.debug(`result: ${JSON.stringify(result)}`);
+                let hits = [];
+                for (let record of result?.hits?.hits) {
+                    const {_source, _index, _id} = record;
+                    logger.debug(`_source: ${JSON.stringify(_source)}`);
+                    logger.debug(`_index: ${_index}`);
+                    logger.debug(`_id: ${_id}`);
+                    hits.push({
+                        id: `${_index}_${_id}`,
+                        ..._source,
+                    });
+                }
+                ctx.body = hits;
+                ctx.status = 200;
+            }
+        } catch (err) {
+            handleInternalError(err, ctx);
+        }
+    }
+}
+
+module.exports = {
+    getQueryResultsHandler,
+};
diff --git a/app/api/sources/delete.js b/app/api/sources/delete.js
new file mode 100644
index 0000000000000000000000000000000000000000..758ff98abba67e5a3aa3263108e153b9b2cc4ebe
--- /dev/null
+++ b/app/api/sources/delete.js
@@ -0,0 +1,25 @@
+"use strict";
+
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+const { deleteSource } = require("@/app/dal/sourceService");
+
+async function deleteSourceHandler(ctx) {
+  const { id } = ctx.params;
+  if (!id) {
+    handleMissingParameters(["id"], ctx);
+  } else {
+    try {
+      await deleteSource(id);
+      ctx.status = 204;
+    } catch (err) {
+      handleInternalError(err, ctx);
+    }
+  }
+}
+
+module.exports = {
+  deleteSourceHandler,
+};
diff --git a/app/api/sources/get.js b/app/api/sources/get.js
new file mode 100644
index 0000000000000000000000000000000000000000..4d9da467c1a16728b9c51bd7b6c7a8202e871ac2
--- /dev/null
+++ b/app/api/sources/get.js
@@ -0,0 +1,81 @@
+"use strict";
+
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+const {
+  getSources,
+  getSource,
+  getSourcesByProvider,
+  getIndexedSourcesByProvider,
+  getIndexedSources,
+} = require("@/app/dal/sourceService");
+
+async function getSourcesHandler(ctx) {
+  try {
+    ctx.body = await getSources();
+    ctx.status = 200;
+  } catch (err) {
+    handleInternalError(err, ctx);
+  }
+}
+
+async function getSourceHandler(ctx) {
+  const { id } = ctx.params;
+  if (!id) {
+    handleMissingParameters(["id"], ctx);
+  } else {
+    try {
+      ctx.body = await getSource(id);
+      ctx.status = 200;
+    } catch (err) {
+      handleInternalError(err, ctx);
+    }
+  }
+}
+
+async function getSourcesByProviderHandler(ctx) {
+  const { kc_id } = ctx.params;
+  if (!kc_id) {
+    handleMissingParameters(["kc_id"], ctx);
+  } else {
+    try {
+      ctx.body = await getSourcesByProvider(kc_id);
+      ctx.status = 200;
+    } catch (err) {
+      handleInternalError(err, ctx);
+    }
+  }
+}
+
+async function getIndexedSourcesByProviderHandler(ctx) {
+  const { kc_id } = ctx.params;
+  if (!kc_id) {
+    handleMissingParameters(["kc_id"], ctx);
+  } else {
+    try {
+      ctx.body = await getIndexedSourcesByProvider(kc_id);
+      ctx.status = 200;
+    } catch (err) {
+      handleInternalError(err, ctx);
+    }
+  }
+}
+
+async function getIndexedSourcesHandler(ctx) {
+  try {
+    ctx.body = await getIndexedSources();
+    ctx.status = 200;
+  } catch (err) {
+    handleInternalError(err, ctx);
+  }
+}
+
+module.exports = {
+  getSourcesHandler,
+  getSourceHandler,
+  getSourcesByProviderHandler,
+  getIndexedSourcesByProviderHandler,
+  getIndexedSourcesHandler,
+};
diff --git a/app/api/sources/post.js b/app/api/sources/post.js
new file mode 100644
index 0000000000000000000000000000000000000000..7f1c72ca9e08025a3b8aa66fbdfa787591fa7460
--- /dev/null
+++ b/app/api/sources/post.js
@@ -0,0 +1,38 @@
+"use strict";
+
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+const { createSource } = require("@/app/dal/sourceService");
+
+async function createSourceHandler(ctx) {
+  const { name, description, metaUrfms, kc_id } = ctx.request.body;
+  if (!name || !description || !kc_id || !metaUrfms) {
+    const missingParams = [];
+    if (!name) {
+      missingParams.push("name");
+    }
+    if (!description) {
+      missingParams.push("description");
+    }
+    if (!kc_id) {
+      missingParams.push("kc_id");
+    }
+    if (!metaUrfms) {
+      missingParams.push("metaUrfms");
+    }
+    handleMissingParameters(missingParams, ctx);
+  } else {
+    try {
+      ctx.body = await createSource(name, description, metaUrfms, kc_id);
+      ctx.status = 201;
+    } catch (err) {
+      handleInternalError(err, ctx);
+    }
+  }
+}
+
+module.exports = {
+  createSourceHandler,
+};
diff --git a/app/api/std_fields/delete.js b/app/api/std_fields/delete.js
new file mode 100644
index 0000000000000000000000000000000000000000..ef98db62f460395607988a4b446bfdfa4b4cebf8
--- /dev/null
+++ b/app/api/std_fields/delete.js
@@ -0,0 +1,17 @@
+"use strict";
+
+const { handleInternalError } = require("@/app/utils/errorHandler");
+const { deleteAllStdFields } = require("@/app/dal/stdFieldService");
+
+async function deleteAllStdFieldsHandler(ctx) {
+  try {
+    ctx.body = await deleteAllStdFields();
+    ctx.status = 204;
+  } catch (error) {
+    handleInternalError(error, ctx);
+  }
+}
+
+module.exports = {
+  deleteAllStdFieldsHandler,
+};
diff --git a/app/api/std_fields/get.js b/app/api/std_fields/get.js
new file mode 100644
index 0000000000000000000000000000000000000000..35b649b353c4f44866379a894408ae19adc7f880
--- /dev/null
+++ b/app/api/std_fields/get.js
@@ -0,0 +1,49 @@
+"use strict";
+
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+const {
+  getStdFields,
+  getStdField,
+  getPublicStdFields,
+} = require("@/app/dal/stdFieldService");
+
+async function getStdFieldsHandler(ctx) {
+  try {
+    ctx.body = await getStdFields();
+    ctx.status = 200;
+  } catch (err) {
+    handleInternalError(err, ctx);
+  }
+}
+
+async function getPublicStdFieldsHandler(ctx) {
+  try {
+    ctx.body = await getPublicStdFields();
+    ctx.status = 200;
+  } catch (err) {
+    handleInternalError(err, ctx);
+  }
+}
+
+async function getStdFieldHandler(ctx) {
+  const { id } = ctx.params;
+  if (!id) {
+    handleMissingParameters(["id"], ctx);
+  } else {
+    try {
+      ctx.body = await getStdField(id);
+      ctx.status = 200;
+    } catch (err) {
+      handleInternalError(err, ctx);
+    }
+  }
+}
+
+module.exports = {
+  getStdFieldsHandler,
+  getPublicStdFieldsHandler,
+  getStdFieldHandler,
+};
diff --git a/app/api/std_fields/post.js b/app/api/std_fields/post.js
new file mode 100644
index 0000000000000000000000000000000000000000..2bdaa39acb63cc620979725604814ad02e88c4f6
--- /dev/null
+++ b/app/api/std_fields/post.js
@@ -0,0 +1,17 @@
+"use strict";
+
+const {handleInternalError} = require("@/app/utils/errorHandler");
+const {createOrUpdateStdField} = require("@/app/dal/stdFieldService");
+
+async function createOrUpdateStdFieldHandler(ctx) {
+    try {
+        ctx.body = await createOrUpdateStdField(ctx.request.body);
+        ctx.status = 201;
+    } catch (error) {
+        handleInternalError(error, ctx);
+    }
+}
+
+module.exports = {
+    createOrUpdateStdFieldHandler,
+};
diff --git a/app/api/std_fields/update.js b/app/api/std_fields/update.js
new file mode 100644
index 0000000000000000000000000000000000000000..295e4bc10064bc5bb054b1f13289d77c1ffa31ea
--- /dev/null
+++ b/app/api/std_fields/update.js
@@ -0,0 +1,27 @@
+"use strict";
+
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+const { createOrUpdateStdField } = require("@/app/dal/stdFieldService");
+
+async function updateStdFieldHandler(ctx) {
+  const { id } = ctx.params;
+  if (!id) {
+    const missingParameters = [];
+    if (!id) missingParameters.push("id");
+    handleMissingParameters(missingParameters, ctx);
+  } else {
+    try {
+      ctx.body = await createOrUpdateStdField(ctx.request.body);
+      ctx.status = 204;
+    } catch (error) {
+      handleInternalError(error, ctx);
+    }
+  }
+}
+
+module.exports = {
+  updateStdFieldHandler,
+};
diff --git a/app/api/user-display-fields/get.js b/app/api/user-display-fields/get.js
new file mode 100644
index 0000000000000000000000000000000000000000..7081b7bf3753f0fbf61bee554bd170a675277e46
--- /dev/null
+++ b/app/api/user-display-fields/get.js
@@ -0,0 +1,25 @@
+const { getUserDisplayFields } = require("../../dal/userDisplayFieldsService");
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("../../utils/errorHandler");
+
+async function getUserDisplayFieldsHandler(ctx) {
+  const { kc_id } = ctx.params;
+  if (!kc_id) {
+    const missingParams = [];
+    if (!kc_id) missingParams.push("kc_id");
+    handleMissingParameters(missingParams, ctx);
+  } else {
+    try {
+      ctx.body = await getUserDisplayFields(kc_id);
+      ctx.status = 200;
+    } catch (err) {
+      handleInternalError(err, ctx);
+    }
+  }
+}
+
+module.exports = {
+  getUserDisplayFieldsHandler,
+};
diff --git a/app/api/user-display-fields/post.js b/app/api/user-display-fields/post.js
new file mode 100644
index 0000000000000000000000000000000000000000..b2f61cd9b780fc3e1fb188c693f8495fc0c0204e
--- /dev/null
+++ b/app/api/user-display-fields/post.js
@@ -0,0 +1,27 @@
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("../../utils/errorHandler");
+const { setUserDisplayFields } = require("../../dal/userDisplayFieldsService");
+
+async function setUserDisplayFieldsHandler(ctx) {
+  const { kc_id } = ctx.params;
+  const { fields_id } = ctx.request.body;
+  if (!kc_id || !fields_id) {
+    const missingParams = [];
+    if (!kc_id) missingParams.push("kc_id");
+    if (!fields_id) missingParams.push("fields_id");
+    handleMissingParameters(missingParams, ctx);
+  } else {
+    try {
+      ctx.body = await setUserDisplayFields(kc_id, fields_id);
+      ctx.status = 201;
+    } catch (err) {
+      handleInternalError(err, ctx);
+    }
+  }
+}
+
+module.exports = {
+  setUserDisplayFieldsHandler,
+};
diff --git a/app/api/user-fields-display-settings/delete.js b/app/api/user-fields-display-settings/delete.js
deleted file mode 100644
index 743ae4aade7245b26ce447b3d3992c6eefb6671a..0000000000000000000000000000000000000000
--- a/app/api/user-fields-display-settings/delete.js
+++ /dev/null
@@ -1,21 +0,0 @@
-'use strict'
-
-const userFieldsDisplaySettingsService = require("../../dal/userFieldsDisplaySettingsService");
-const logger = require('../../utils/logger');
-
-const UserFieldsDisplaySettings = {
-    async delete(ctx) {
-        try {
-            ctx.body = await userFieldsDisplaySettingsService.delete(ctx.request.params);
-            ctx.status = 201;
-            logger.info('User fields display settings deleted.');
-        } catch (error) {
-            throw error;
-        }
-    }
-}
-
-module.exports = {
-    deleteUserFieldsDisplaySettings: UserFieldsDisplaySettings.delete,
-    UserFieldsDisplaySettings
-};
diff --git a/app/api/user-fields-display-settings/get.js b/app/api/user-fields-display-settings/get.js
deleted file mode 100644
index e8b08ef97ebddbac2443428f7bc7b4c08d134b33..0000000000000000000000000000000000000000
--- a/app/api/user-fields-display-settings/get.js
+++ /dev/null
@@ -1,32 +0,0 @@
-"use strict";
-
-const logger = require('../../utils/logger')
-const userFieldsDisplaySettingsService = require("../../dal/userFieldsDisplaySettingsService");
-
-const GetUserFieldsDisplaySettings = {
-    async find(ctx) {
-        try {
-            ctx.body = await userFieldsDisplaySettingsService.usersFieldsDisplaySettings();
-            ctx.status = 201;
-            logger.info('Users fields display settings retrieved.');
-        } catch (error) {
-            throw error;
-        }
-    },
-
-    async findOne(ctx) {
-        try {
-            ctx.body = await userFieldsDisplaySettingsService.userFieldsDisplaySettings(ctx.request.params);
-            ctx.status = 201;
-            logger.info('User fields display settings retrieved.');
-        } catch (error) {
-            throw error;
-        }
-    },
-};
-
-module.exports = {
-    findUsersFieldsDisplaySettings: GetUserFieldsDisplaySettings.find,
-    findUserFieldsDisplaySettings: GetUserFieldsDisplaySettings.findOne,
-    GetUserFieldsDisplaySettings
-};
diff --git a/app/api/user-fields-display-settings/index.js b/app/api/user-fields-display-settings/index.js
deleted file mode 100644
index 338b10b3732a4bc49181e93e3dc136b3092d33fa..0000000000000000000000000000000000000000
--- a/app/api/user-fields-display-settings/index.js
+++ /dev/null
@@ -1,16 +0,0 @@
-"use strict";
-
-const { createUserFieldsDisplaySettings } = require('./post');
-const { findUsersFieldsDisplaySettings, findUserFieldsDisplaySettings } = require('./get');
-const { updateUserFieldsDisplaySettings } = require('./put');
-const { deleteUserFieldsDisplaySettings } = require('./delete');
-
-const UserFieldsDisplaySettingsHandler = {
-    createUserFieldsDisplaySettings,
-    findUsersFieldsDisplaySettings,
-    findUserFieldsDisplaySettings,
-    updateUserFieldsDisplaySettings,
-    deleteUserFieldsDisplaySettings
-}
-
-module.exports = UserFieldsDisplaySettingsHandler
diff --git a/app/api/user-fields-display-settings/post.js b/app/api/user-fields-display-settings/post.js
deleted file mode 100644
index 2b0075bac46cba7991f6bca121ccbecbc2e4efa9..0000000000000000000000000000000000000000
--- a/app/api/user-fields-display-settings/post.js
+++ /dev/null
@@ -1,21 +0,0 @@
-'use strict'
-
-const userFieldsDisplaySettingsService = require("../../dal/userFieldsDisplaySettingsService");
-const logger = require('../../utils/logger')
-
-const CreateUserFieldsDisplaySettings = {
-    async create(ctx) {
-        try {
-            ctx.body = await userFieldsDisplaySettingsService.create(ctx.request.body);
-            ctx.status = 201;
-            logger.info('User fields display settings created.');
-        } catch (error) {
-            throw error;
-        }
-    },
-}
-
-module.exports = {
-    createUserFieldsDisplaySettings: CreateUserFieldsDisplaySettings.create,
-    CreateUserFieldsDisplaySettings
-}
diff --git a/app/api/user-fields-display-settings/put.js b/app/api/user-fields-display-settings/put.js
deleted file mode 100644
index 066f5939c2fc0713635c7adfe7e394b53c2204d2..0000000000000000000000000000000000000000
--- a/app/api/user-fields-display-settings/put.js
+++ /dev/null
@@ -1,21 +0,0 @@
-'use strict'
-
-const userFieldsDisplaySettingsService = require("../../dal/userFieldsDisplaySettingsService");
-const logger = require('../../utils/logger');
-
-const UpdateUserFieldsDisplaySettings = {
-    async update(ctx) {
-        try {
-            ctx.body = await userFieldsDisplaySettingsService.update(ctx.request.body);
-            ctx.status = 201;
-            logger.info('User fields display settings updated.');
-        } catch (error) {
-            throw error;
-        }
-    }
-}
-
-module.exports = {
-    updateUserFieldsDisplaySettings: UpdateUserFieldsDisplaySettings.update,
-    UpdateUserFieldsDisplaySettings
-};
diff --git a/app/api/user-profile/index.js b/app/api/user-profile/index.js
deleted file mode 100644
index ccacec309b04adc8798a903f2edbe61bf70e5213..0000000000000000000000000000000000000000
--- a/app/api/user-profile/index.js
+++ /dev/null
@@ -1 +0,0 @@
-'use strict'
diff --git a/app/api/user-requests/delete.js b/app/api/user-requests/delete.js
index d1be7f915ac21a520c869ca9c1666f32bd41dd57..983c56f93dfd4ad964d10dd98298992918924822 100644
--- a/app/api/user-requests/delete.js
+++ b/app/api/user-requests/delete.js
@@ -1,21 +1,24 @@
-'use strict'
+"use strict";
 
-const userRequestService = require('../../dal/userRequestService');
-const logger = require('../../utils/logger');
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("../../utils/errorHandler");
+const { deleteRequest } = require("../../dal/userRequestService");
 
-const UserRequest = {
-    async delete(ctx) {
-        try {
-            ctx.body = await userRequestService.delete(ctx.request.body);
-            ctx.status = 201;
-            logger.info('User request deleted.');
-        } catch (error) {
-            throw error;
-        }
+async function deleteRequestHandler(ctx) {
+  const { id } = ctx.params;
+  if (!id) {
+    handleMissingParameters(["id"], ctx);
+  } else {
+    try {
+      await deleteRequest(id);
+      ctx.status = 204;
+    } catch (err) {
+      handleInternalError(err, ctx);
     }
-};
-
+  }
+}
 module.exports = {
-    deleteRequest: UserRequest.delete,
-    UserRequest
+  deleteRequestHandler,
 };
diff --git a/app/api/user-requests/get.js b/app/api/user-requests/get.js
index b62ee084f955adc7859774cb0d02cc3e053a996c..00d849ff3045cca98d0a7e6ccfc860c75c355e16 100644
--- a/app/api/user-requests/get.js
+++ b/app/api/user-requests/get.js
@@ -1,32 +1,64 @@
-'use strict'
+"use strict";
 
-const userRequestService = require('../../dal/userRequestService');
-const logger = require('../../utils/logger');
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+const {
+  getAllRequests,
+  getAllPendingRequests,
+} = require("@/app/dal/userRequestService");
 
-const UserRequest = {
-    async list(ctx) {
-        try {
-            ctx.body = await userRequestService.fetch();
-            ctx.status = 201;
-            logger.info('User requests fetched.');
-        } catch (error) {
-            throw error;
-        }
-    },
+async function getAllRequestsHandler(ctx) {
+  try {
+    ctx.body = await getAllRequests();
+    ctx.status = 200;
+  } catch (err) {
+    handleInternalError(err, ctx);
+  }
+}
 
-    async listPending(ctx) {
-        try {
-            ctx.body = await userRequestService.fetchPending();
-            ctx.status = 201;
-            logger.info('Pending user requests fetched.');
-        } catch (error) {
-            throw error;
-        }
+async function getAllPendingRequestsHandler(ctx) {
+  try {
+    ctx.body = await getAllPendingRequests();
+    ctx.status = 200;
+  } catch (err) {
+    handleInternalError(err, ctx);
+  }
+}
+
+async function getAllUserRequestsHandler(ctx) {
+  const { kc_id } = ctx.params;
+  if (!kc_id) {
+    handleMissingParameters(["kc_id"], ctx);
+  } else {
+    try {
+      ctx.body = await getAllRequests(kc_id);
+      ctx.status = 200;
+    } catch (err) {
+      handleInternalError(err, ctx);
     }
-};
+  }
+}
+
+async function getAllPendingUserRequestsHandler(ctx) {
+  const { kc_id } = ctx.params;
+  if (!kc_id) {
+    handleMissingParameters(["kc_id"], ctx);
+  } else {
+    try {
+      const kc_id = ctx.params.kc_id;
+      ctx.body = await getAllPendingRequests(kc_id);
+      ctx.status = 200;
+    } catch (err) {
+      handleInternalError(err, ctx);
+    }
+  }
+}
 
 module.exports = {
-    fetchRequests: UserRequest.list,
-    fetchPendingRequests: UserRequest.listPending,
-    UserRequest
+  getAllRequestsHandler,
+  getAllPendingRequestsHandler,
+  getAllUserRequestsHandler,
+  getAllPendingUserRequestsHandler,
 };
diff --git a/app/api/user-requests/index.js b/app/api/user-requests/index.js
deleted file mode 100644
index 8d0a9ea6c5d9c8d58065f1a22c317a3ab3419c4b..0000000000000000000000000000000000000000
--- a/app/api/user-requests/index.js
+++ /dev/null
@@ -1,16 +0,0 @@
-'use strict'
-
-const { createRequest, processRequest, fetchRequestsByUser } = require('./post');
-const { fetchRequests, fetchPendingRequests } = require('./get');
-const { deleteRequest } = require('./delete');
-
-const UserRequestHandler = {
-    createRequest,
-    processRequest,
-    fetchRequests,
-    fetchPendingRequests,
-    fetchRequestsByUser,
-    deleteRequest
-};
-
-module.exports = UserRequestHandler;
diff --git a/app/api/user-requests/post.js b/app/api/user-requests/post.js
index d0b90afd9d8b76444d773602e703cf1cf4ed4577..ffffef4714716bf12782458b2335d2acb0af1220 100644
--- a/app/api/user-requests/post.js
+++ b/app/api/user-requests/post.js
@@ -1,43 +1,65 @@
-'use strict'
+"use strict";
 
-const userRequestService = require('../../dal/userRequestService');
-const logger = require('../../utils/logger');
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+const {
+  createRequest,
+  updateRequest,
+} = require("@/app/dal/userRequestService");
 
-const UserRequest = {
-    async create(ctx) {
-        try {
-            ctx.body = await userRequestService.create(ctx.request.body);
-            ctx.status = 201;
-            logger.info('User request created.');
-        } catch (error) {
-            throw error;
-        }
-    },
-
-    async process(ctx) {
-        try {
-            ctx.body = await userRequestService.process(ctx.request.body);
-            ctx.status = 201;
-            logger.info('User request processed.');
-        } catch (error) {
-            throw error;
-        }
-    },
+async function createRequestHandler(ctx) {
+  const { kc_id } = ctx.params;
+  const { message } = ctx.request.body;
+  if (!kc_id || !message) {
+    const missingParameters = [];
+    if (!kc_id) {
+      missingParameters.push("kc_id");
+    }
+    if (!message) {
+      missingParameters.push("message");
+    }
+    handleMissingParameters(missingParameters, ctx);
+    console.log("missingParameters", missingParameters);
+  } else {
+    try {
+      ctx.body = await createRequest(kc_id, message);
+      ctx.status = 201;
+    } catch (err) {
+      handleInternalError(err, ctx);
+    }
+  }
+}
 
-    async listByUser(ctx) {
-        try {
-            ctx.body = await userRequestService.fetchByUser(ctx.request.body);
-            ctx.status = 201;
-            logger.info('User requests fetched by user.');
-        } catch (error) {
-            throw error;
-        }
+async function updateRequestHandler(ctx) {
+  const { id } = ctx.params;
+  const { is_processed } = ctx.request.body;
+  if (!id || is_processed === undefined) {
+    const missingParameters = [];
+    if (!id) {
+      missingParameters.push("id");
     }
-};
+    if (is_processed === undefined) {
+      missingParameters.push("is_processed");
+    }
+    await handleMissingParameters(missingParameters, ctx);
+  } else {
+    if (typeof is_processed !== "boolean") {
+      await handleMissingParameters(["is_processed must be a boolean"], ctx);
+      console.log("is_processed must be a boolean");
+    } else {
+      try {
+        ctx.body = await updateRequest(id, is_processed);
+        ctx.status = 201;
+      } catch (err) {
+        await handleInternalError(err, ctx);
+      }
+    }
+  }
+}
 
 module.exports = {
-    createRequest: UserRequest.create,
-    processRequest: UserRequest.process,
-    fetchRequestsByUser: UserRequest.listByUser,
-    UserRequest
+  createRequestHandler,
+  updateRequestHandler,
 };
diff --git a/app/api/user-search-history/delete.js b/app/api/user-search-history/delete.js
index a1f7ef94d879154fbeaab488dc4c18d6f926e8d5..52f562101fd39729ff05e65dcf5e5551198f0860 100644
--- a/app/api/user-search-history/delete.js
+++ b/app/api/user-search-history/delete.js
@@ -1,21 +1,44 @@
-'use strict'
+"use strict";
 
-const searchHistoryService = require('../../dal/searchHistoryService');
-const logger = require('../../utils/logger');
+const {
+  deleteHistory,
+  deleteAllHistoryByUser,
+} = require("@/app/dal/searchHistoryService");
 
-const SearchHistory = {
-    async delete(ctx) {
-        try {
-            ctx.body = await searchHistoryService.delete(ctx.request.body);
-            ctx.status = 201;
-            logger.info('User search history deleted.');
-        } catch (error) {
-            throw error;
-        }
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+
+async function deleteHistoryHandler(ctx) {
+  const { id } = ctx.params;
+  if (!id) {
+    handleMissingParameters(["id"], ctx);
+  } else {
+    try {
+      await deleteHistory(id);
+      ctx.status = 204;
+    } catch (error) {
+      handleInternalError(error, ctx);
     }
-};
+  }
+}
+
+async function deleteAllHistoryByUserHandler(ctx) {
+  const { kc_id } = ctx.params;
+  if (!kc_id) {
+    handleMissingParameters(["kc_id"], ctx);
+  } else {
+    try {
+      await deleteAllHistoryByUser(kc_id);
+      ctx.status = 204;
+    } catch (error) {
+      handleInternalError(error, ctx);
+    }
+  }
+}
 
 module.exports = {
-    deleteUserSearchHistory: SearchHistory.delete,
-    SearchHistory
+  deleteHistoryHandler,
+  deleteAllHistoryByUserHandler,
 };
diff --git a/app/api/user-search-history/get.js b/app/api/user-search-history/get.js
index e8cc7b7ef103903119a8a6b72f64484ed4b88c43..681fe78ebb6c0ae149837712d2d54a5469c94b64 100644
--- a/app/api/user-search-history/get.js
+++ b/app/api/user-search-history/get.js
@@ -1,21 +1,25 @@
-'use strict'
+"use strict";
 
-const searchHistoryService = require('../../dal/searchHistoryService');
-const logger = require('../../utils/logger');
+const { getSearchHistoryByUser } = require("@/app/dal/searchHistoryService");
+const {
+  handleMissingParameters,
+  handleInternalError,
+} = require("@/app/utils/errorHandler");
 
-const SearchHistory = {
-    async list(ctx) {
-        try {
-            ctx.body = await searchHistoryService.fetch(ctx.request.body);
-            ctx.status = 201;
-            logger.info('User search history fetched.');
-        } catch (error) {
-            throw error;
-        }
+async function getHistoryHandler(ctx) {
+  const { kc_id } = ctx.params;
+  if (!kc_id) {
+    handleMissingParameters(["kc_id"], ctx);
+  } else {
+    try {
+      ctx.body = await getSearchHistoryByUser(kc_id);
+      ctx.status = 200;
+    } catch (error) {
+      handleInternalError(error, ctx);
     }
-};
+  }
+}
 
 module.exports = {
-    fetch: SearchHistory.list,
-    SearchHistory
+  getHistoryHandler,
 };
diff --git a/app/api/user-search-history/index.js b/app/api/user-search-history/index.js
deleted file mode 100644
index 7dab2705e3ccbf2eff1784bb2a8ef61dc3e17a03..0000000000000000000000000000000000000000
--- a/app/api/user-search-history/index.js
+++ /dev/null
@@ -1,13 +0,0 @@
-'use strict'
-
-const { create } = require('./post');
-const { fetch } = require('./get');
-const { deleteUserSearchHistory } = require('./delete');
-
-const SearchHistoryHandler = {
-    create,
-    fetch,
-    deleteUserSearchHistory
-};
-
-module.exports = SearchHistoryHandler;
diff --git a/app/api/user-search-history/post.js b/app/api/user-search-history/post.js
index 5739977c7ecee96509bf12e28c2c084369919b26..152cb3826eea180190e014e39b86272b40a47299 100644
--- a/app/api/user-search-history/post.js
+++ b/app/api/user-search-history/post.js
@@ -1,21 +1,48 @@
-'use strict'
+"use strict";
 
-const searchHistoryService = require('../../dal/searchHistoryService');
-const logger = require('../../utils/logger');
+const { addSearchHistoryToUser } = require("@/app/dal/searchHistoryService");
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
 
-const SearchHistory = {
-    async create(ctx) {
-        try {
-            ctx.body = await searchHistoryService.create(ctx.request.body);
-            ctx.status = 201;
-            logger.info('Search history created.');
-        } catch (error) {
-           throw error;
-        }
+async function addSearchHistoryToUserHandler(ctx) {
+  const { kc_id } = ctx.params;
+  const { query, name, ui_structure, description } = ctx.request.body;
+  if (!kc_id || !query || !name || !ui_structure || !description) {
+    const missingParameters = [];
+    if (!kc_id) {
+      missingParameters.push("kc_id");
     }
-};
+    if (!query) {
+      missingParameters.push("query");
+    }
+    if (!name) {
+      missingParameters.push("name");
+    }
+    if (!ui_structure) {
+      missingParameters.push("ui_structure");
+    }
+    if (!description) {
+      missingParameters.push("description");
+    }
+    handleMissingParameters(missingParameters, ctx);
+  } else {
+    try {
+      ctx.body = await addSearchHistoryToUser(
+        kc_id,
+        query,
+        name,
+        ui_structure,
+        description
+      );
+      ctx.status = 201;
+    } catch (error) {
+      handleInternalError(error, ctx);
+    }
+  }
+}
 
 module.exports = {
-    create: SearchHistory.create,
-    SearchHistory
+  addSearchHistoryToUserHandler,
 };
diff --git a/app/api/users/delete.js b/app/api/users/delete.js
index ebe5496e9988441975d3a083c0f32bbff612b14b..f4294578ca274ccb9b53d625240ee1b758b3b79c 100644
--- a/app/api/users/delete.js
+++ b/app/api/users/delete.js
@@ -1,21 +1,25 @@
-'use strict'
+"use strict";
 
-const userService = require("../../dal/userService");
-const logger = require('../../utils/logger');
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+const { deleteUser } = require("@/app/dal/userService");
 
-const DeleteUser = {
-    async deleteUser(ctx) {
-        try {
-            ctx.body = await userService.delete(ctx.request.body);
-            ctx.status = 201;
-            logger.info('User deleted.');
-        } catch (error) {
-            throw error;
-        }
+async function deleteUserHandler(ctx) {
+  const { kc_id } = ctx.params;
+  if (!kc_id) {
+    handleMissingParameters(["kc_id"], ctx);
+  } else {
+    try {
+      ctx.body = await deleteUser(kc_id);
+      ctx.status = 204;
+    } catch (err) {
+      handleInternalError(err, ctx);
     }
-};
+  }
+}
 
 module.exports = {
-    deleteUser: DeleteUser.deleteUser,
-    DeleteUser
+  deleteUserHandler,
 };
diff --git a/app/api/users/get.js b/app/api/users/get.js
index f35efd235a7a917ba1dfa4cccd891a3069d0d43d..cfe8e86d531e40f30711ac1e49682440715420e0 100644
--- a/app/api/users/get.js
+++ b/app/api/users/get.js
@@ -1,76 +1,42 @@
 "use strict";
 
-const userService = require("../../dal/userService");
-const logger = require('../../utils/logger');
-
-const GetUser = {
-  async find(ctx) {
-    try {
-      ctx.body = await userService.users();
-      ctx.status = 201;
-      logger.info('Users fetched.');
-    } catch (error) {
-      throw error;
-    }
-  },
-
-  async findOne(ctx) {
-    try {
-      ctx.body = await userService.user(ctx.request.body);
-      ctx.status = 201;
-      logger.info('User fetched.');
-    } catch (error) {
-      throw error;
-    }
-  },
-
-  async kcId(ctx) {
-    try {
-      ctx.body = await userService.kcId(ctx.request.body);
-      ctx.status = 201;
-      logger.info('User kc_id fetched.');
-    } catch (error) {
-      throw error;
-    }
-  },
-
-  async detail(ctx) {
-    try {
-      ctx.body = await userService.detail(ctx.request.body);
-      ctx.status = 201;
-      logger.info('User details fetched.');
-    } catch (error) {
-      throw error;
-    }
-  },
-
-  async getAssignedUserByRole(ctx) {
-    try {
-      ctx.body = await userService.getAssignedUserByRole(ctx.request.body);
-      ctx.status = 201;
-      logger.info('Users fetched by role.');
-    } catch (error) {
-      throw error;
-    }
-  },
-
-  async usersWithGroupAndRole(ctx) {
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
+const { getUsers, getUser } = require("@/app/dal/userService");
+
+async function getUsersHandler(ctx) {
+  try {
+    ctx.body = await getUsers();
+    ctx.status = 200;
+  } catch (err) {
+    handleInternalError(err, ctx);
+  }
+}
+
+async function getUserHandler(ctx) {
+  const { params } = ctx;
+  const { kc_id } = params;
+  if (!kc_id) {
+    handleMissingParameters(["kc_id"], ctx);
+  } else {
     try {
-      ctx.body = await userService.usersWithGroupAndRole();
-      ctx.status = 201;
-      logger.info('Users with groups and roles fetched.');
-    } catch (error) {
-      throw error;
+      const user = await getUser(kc_id);
+      if (!user) {
+        ctx.status = 404;
+        ctx.body = { message: "User not found" };
+      } else {
+        ctx.body = user;
+        ctx.status = 200;
+      }
+    } catch (err) {
+      handleInternalError(err, ctx);
     }
   }
-};
+}
 
 module.exports = {
-  users: GetUser.find,
-  user: GetUser.findOne,
-  kcId: GetUser.kcId,
-  detail: GetUser.detail,
-  getAssignedUserByRole: GetUser.getAssignedUserByRole,
-  usersWithGroupAndRole: GetUser.usersWithGroupAndRole,
-  GetUser
+  getUsersHandler,
+  getUserHandler,
 };
diff --git a/app/api/users/index.js b/app/api/users/index.js
deleted file mode 100644
index c228799292cf848ea6366fbc73174140c87a6ac5..0000000000000000000000000000000000000000
--- a/app/api/users/index.js
+++ /dev/null
@@ -1,24 +0,0 @@
-"use strict";
-
-const { create, createSystemUser, sendMail, userWithGroupAndRole, resetPassword } = require('./post');
-const { user, users, kcId, detail, getAssignedUserByRole, usersWithGroupAndRole } = require('./get');
-const { deleteUser } = require('./delete');
-const { update } = require('./put');
-
-const UserHandler = {
-    create,
-    user,
-    users,
-    deleteUser,
-    update,
-    kcId,
-    detail,
-    createSystemUser,
-    getAssignedUserByRole,
-    usersWithGroupAndRole,
-    userWithGroupAndRole,
-    sendMail,
-    resetPassword
-};
-
-module.exports = UserHandler;
diff --git a/app/api/users/post.js b/app/api/users/post.js
index 87e5d64192bcdfffa52b5ed1bf85681d65cd8e81..619d2f6b4b4fe5fb2f043cdcdfb53df854616deb 100644
--- a/app/api/users/post.js
+++ b/app/api/users/post.js
@@ -1,65 +1,39 @@
-'use strict'
+"use strict";
 
-const userService = require("../../dal/userService");
-const logger = require('../../utils/logger');
+const {
+  handleInternalError,
+  handleMissingParameters,
+} = require("@/app/utils/errorHandler");
 
-const AddUser = {
-    async create(ctx) {
-        try {
-            ctx.body = await userService.create(ctx.request.body);
-            ctx.status = 201;
-            logger.info('User created.');
-        } catch (error) {
-            throw error;
-        }
-    },
+const { createUser, getUser } = require("@/app/dal/userService");
 
-    async createSystemUser(ctx) {
-        try {
-            ctx.body = await userService.createSystemUser();
-            ctx.status = 201;
-            logger.info('System user (admin) created.');
-        } catch (error) {
-            throw error;
-        }
-    },
-
-    async sendMail(ctx) {
-        try {
-            ctx.body = await userService.sendMail(ctx.request.body);
-            ctx.status = 201;
-            logger.info('Mail sent.');
-        } catch (error) {
-            throw error;
-        }
-    },
-
-    async userWithGroupAndRole(ctx) {
-        try {
-            ctx.body = await userService.userWithGroupAndRole(ctx.request.body);
-            ctx.status = 201;
-            logger.info('User with groups and roles fetched.');
-        } catch (error) {
-            throw error;
-        }
-    },
-
-    async resetPassword(ctx) {
-        try {
-            ctx.body = await userService.resetPassword(ctx.request.body);
-            ctx.status = 201;
-            logger.info('Password reset.');
-        } catch (error) {
-            throw error;
-        }
+async function getOrCreateUserHandler(ctx) {
+  const { kc_id, email } = ctx.request.body;
+  if (!kc_id || !email) {
+    const missingParameters = [];
+    if (!kc_id) {
+      missingParameters.push("kc_id");
     }
+    if (!email) {
+      missingParameters.push("email");
+    }
+    handleMissingParameters(missingParameters, ctx);
+  } else {
+    try {
+      const user = await getUser(kc_id);
+      if (user) {
+        ctx.body = user;
+        ctx.status = 200;
+      } else {
+        ctx.body = await createUser(kc_id, email);
+        ctx.status = 201;
+      }
+    } catch (err) {
+      handleInternalError(err, ctx);
+    }
+  }
 }
 
 module.exports = {
-    create: AddUser.create,
-    createSystemUser: AddUser.createSystemUser,
-    sendMail: AddUser.sendMail,
-    userWithGroupAndRole: AddUser.userWithGroupAndRole,
-    resetPassword: AddUser.resetPassword,
-    AddUser
-}
+  getOrCreateUserHandler,
+};
diff --git a/app/api/users/put.js b/app/api/users/put.js
deleted file mode 100644
index 3d5db10b86daf5eb4f91bf2300c317bbc20fc543..0000000000000000000000000000000000000000
--- a/app/api/users/put.js
+++ /dev/null
@@ -1,21 +0,0 @@
-'use strict'
-
-const userService = require("../../dal/userService");
-const logger = require('../../utils/logger');
-
-const UpdateUser = {
-    async update(ctx) {
-        try {
-            ctx.body = await userService.update(ctx.request.body);
-            ctx.status = 201;
-            logger.info('User updated.');
-        } catch (error) {
-            throw error;
-        }
-    }
-};
-
-module.exports = {
-    update: UpdateUser.update,
-    UpdateUser
-};
diff --git a/app/config/db.js b/app/config/db.js
deleted file mode 100644
index 7c5396fbe42edd9ec4d8955ac61e677ee5f20f0a..0000000000000000000000000000000000000000
--- a/app/config/db.js
+++ /dev/null
@@ -1,54 +0,0 @@
-'use strict'
-
-const path = require('path')
-const joi = require('@hapi/joi')
-const Sequelize = require('sequelize')
-
-const envVarsSchema = joi.object({
-    DB_HOST: joi.string().required(),
-    DB_USER: joi.string().required(),
-    DB_PASSWORD: joi.string().allow('').required(),
-    DB_DATABASE: joi.string().required(),
-    DB_PORT: joi.number().required(),
-    DB_POOL_MIN: joi.number().default(1),
-    DB_POOL_MAX: joi.number().default(20),
-    DB_DEBUG: joi.bool().default(false)
-}).unknown()
-    .required()
-
-const envVars = joi.attempt(process.env, envVarsSchema)
-
-const config = {
-    client: 'pg',
-    connection: {
-        host: process.env.DB_HOST,
-        user: process.env.DB_USER,
-        password: process.env.DB_PASSWORD,
-        database: process.env.DB_DATABASE,
-        port: process.env.DB_PORT
-    },
-    pool: {
-        min: envVars.DB_POOL_MIN,
-        max: envVars.DB_POOL_MAX
-    },
-    migrations: {
-        directory: path.join(__dirname, '../migrations')
-    },
-    debug: envVars.DB_DEBUG
-}
-
-const clientPgSeq = new Sequelize(config.connection.database, config.connection.user, config.connection.password, {
-    host: config.connection.host,
-    port: config.connection.port,
-    pool: config.pool,
-    dialect: 'postgres',
-    define: {
-        createdAt: "createdat",
-        updatedAt: "updatedat"
-    },
-})
-
-module.exports = {
-    configPg: config,
-    postgresSeq: clientPgSeq,
-}
\ No newline at end of file
diff --git a/app/config/elk.js b/app/config/elk.js
new file mode 100644
index 0000000000000000000000000000000000000000..7daa58c42cfc35b1e9ef645522300b6d4cfafb92
--- /dev/null
+++ b/app/config/elk.js
@@ -0,0 +1,17 @@
+"use strict";
+const joi = require("@hapi/joi");
+
+const envVarsSchema = joi
+  .object({
+    ELK_URL: joi.string().required(),
+    ELK_USERNAME: joi.string().required(),
+    ELK_PASSWORD: joi.string().required(),
+  })
+  .unknown()
+  .required();
+
+const configElk = joi.attempt(process.env, envVarsSchema);
+
+module.exports = {
+  configElk,
+};
diff --git a/app/config/mongo.js b/app/config/mongo.js
new file mode 100644
index 0000000000000000000000000000000000000000..0b1eaa3b631d8f73e849c8464e5c952b20ce8a6e
--- /dev/null
+++ b/app/config/mongo.js
@@ -0,0 +1,25 @@
+"use strict";
+const joi = require("@hapi/joi");
+
+const envVarsSchema = joi
+  .object({
+    MONGO_PORT: joi.number().required(),
+    MONGO_HOST: joi.string().required(),
+    MONGO_DB_NAME: joi.string().required(),
+    MONGO_USERNAME: joi.string().required(),
+    MONGO_PASSWORD: joi.string().required(),
+  })
+  .unknown()
+  .required();
+
+const env = joi.attempt(process.env, envVarsSchema);
+
+const MongoClient = require("mongodb").MongoClient;
+const authMechanism = "DEFAULT";
+const url = `mongodb://${env.MONGO_USERNAME}:${env.MONGO_PASSWORD}@${env.MONGO_HOST}:${env.MONGO_PORT}/?authMechanism=${authMechanism}`;
+const mongoClient = new MongoClient(url);
+
+module.exports = {
+  mongoClient,
+  dbName: env.MONGO_DB_NAME,
+};
diff --git a/app/config/postgres.js b/app/config/postgres.js
new file mode 100644
index 0000000000000000000000000000000000000000..86273050d7c045bd4f4d14780ddad9ea06db077d
--- /dev/null
+++ b/app/config/postgres.js
@@ -0,0 +1,12 @@
+"use strict";
+
+const joi = require("@hapi/joi");
+
+const envVarsSchema = joi
+  .object({
+    DATABASE_URL: joi.string().required(),
+  })
+  .unknown()
+  .required();
+
+joi.attempt(process.env, envVarsSchema);
diff --git a/app/dal/authService.js b/app/dal/authService.js
new file mode 100644
index 0000000000000000000000000000000000000000..5c8eff622631830450546bffd664dbf0983d54c2
--- /dev/null
+++ b/app/dal/authService.js
@@ -0,0 +1,31 @@
+const logger = require("@/app/utils/format");
+
+async function isAccessTokenValid(accessToken) {
+  if (!accessToken) {
+    return false;
+  }
+
+  const issuerUrl = process.env.KEYCLOAK_BASE_URL;
+  const realm = process.env.KEYCLOAK_REALM;
+  const userEndpoint =
+    issuerUrl + "/realms/" + realm + "/protocol/openid-connect/userinfo";
+
+  const response = await fetch(userEndpoint, {
+    headers: {
+      Authorization: `Bearer ${accessToken}`,
+    },
+  });
+  switch (response.status) {
+    case 401:
+      return false;
+    case 200:
+      return true;
+    default:
+      logger.error(`Error validating access token: ${response.statusText}`);
+      return false;
+  }
+}
+
+module.exports = {
+  isAccessTokenValid,
+};
diff --git a/app/dal/elasticService.js b/app/dal/elasticService.js
new file mode 100644
index 0000000000000000000000000000000000000000..f7d9b9dcd1ea22d4a47ec4a25fb67a3674792aef
--- /dev/null
+++ b/app/dal/elasticService.js
@@ -0,0 +1,153 @@
+const {Client} = require("@elastic/elasticsearch");
+const prisma = require("@/prisma/client");
+const {configElk} = require("@/app/config/elk");
+const logger = require("@/app/utils/format");
+
+async function getClientInstance() {
+    logger.debug(`Connecting to ${configElk.ELK_URL}`);
+    const client = new Client({
+        node: configElk.ELK_URL,
+        maxRetries: 5,
+        requestTimeout: 60000,
+        sniffOnStart: false,
+        auth: {
+            username: configElk.ELK_USERNAME,
+            password: configElk.ELK_PASSWORD,
+        },
+    });
+    if (!(await client.ping())) {
+        logger.error("Failed to connect to ElasticSearch");
+    }
+    logger.debug("Connected to ElasticSearch");
+    return client;
+}
+
+async function prepareForBulk(metaUrfms, elkIndex) {
+    const client = await getClientInstance();
+    const response = await client.indices.create(
+        {
+            index: elkIndex,
+        },
+        {ignore: [400]}
+    );
+
+    if (!response.acknowledged) {
+        logger.error(`Index ${elkIndex} not created`);
+        throw new Error(`Index ${elkIndex} not created`);
+    }
+    logger.debug(`Index ${elkIndex} created`);
+
+    const body = metaUrfms.flatMap((doc) => [
+        {index: {_index: elkIndex}},
+        doc,
+    ]);
+    return body;
+}
+
+async function bulk(body) {
+    const client = await getClientInstance();
+    logger.debug("Indexing documents");
+    const {errors, items} = await client.bulk({body, refresh: true});
+    if (errors) {
+        logger.error("Error while bulk indexing", errors);
+        return false;
+    }
+    logger.debug("Documents indexed :" + items.length);
+    return true;
+}
+
+async function search({query, sourcesId, scroll_id, advancedQuery}) {
+    const client = await getClientInstance();
+    logger.debug(`Elasticsearch query: ${JSON.stringify(query)}`);
+    logger.debug("Advanced query: " + advancedQuery);
+    if (scroll_id) {
+        const {body} = await client.scroll({
+            index,
+            scroll_id,
+            scroll: "10s",
+        });
+        return body;
+    } else {
+        let queryBuilder;
+        if (!advancedQuery) {
+            queryBuilder = {
+                query: {
+                    query_string: {
+                        query: query,
+                        default_operator: "or",
+                    },
+                },
+            };
+        } else {
+            try {
+                // remove trailing and leading whitespaces, tabs, newlines, commas, and semicolons
+                query = query.replace(/(^[,\s\n\t]+)|([,\s\n\t]+$)/g, "");
+                logger.debug("Advanced query: " + query);
+                query = JSON.parse(query);
+                queryBuilder = {
+                    query: query
+                };
+            } catch (error) {
+                logger.error("Invalid query", error);
+                return {hits: {hits: []}};
+            }
+        }
+        let indices = [];
+        for (let sourceId of sourcesId) {
+            const source = await prisma.source.findUnique({
+                where: {
+                    id: +sourceId,
+                },
+                include: {
+                    source_indices: true,
+                },
+            });
+            if (!source) {
+                logger.error(`Source ${sourceId} not found`);
+                continue;
+            }
+            for (let index of source.source_indices) {
+                indices.push(index.index_id);
+            }
+        }
+        logger.debug(`Searching in indices: ${indices.join(",")}`);
+        if (indices.length === 0) {
+            logger.error("No indices found for the given sources");
+            return {hits: {hits: []}};
+        }
+        logger.debug("Query : " + JSON.stringify(queryBuilder));
+        const response = await client.search({
+            index: indices.join(","),
+            body: queryBuilder,
+            scroll: "10s",
+        });
+        logger.debug(`Search results: ${response.hits.total.value}`);
+        return response;
+    }
+}
+
+async function countByIndex(index) {
+    const client = await getClientInstance();
+    const {body: count} = await client.count({index});
+    return count;
+}
+
+async function deleteIndex(index) {
+    const client = await getClientInstance();
+    logger.debug(`Deleting index ${index}`);
+    try {
+        await client.indices.delete({index});
+    } catch (error) {
+        logger.error(`Error while deleting index ${index}`, error);
+        return false;
+    }
+    return true;
+}
+
+module.exports = {
+    prepareForBulk,
+    bulk,
+    countByIndex,
+    deleteIndex,
+    search,
+};
diff --git a/app/dal/groupService.js b/app/dal/groupService.js
index d2a6b17fd241cd5c0103e3194758c33234364bb2..c95d5e6631394ff2f9bd12039c12f56db761a487 100644
--- a/app/dal/groupService.js
+++ b/app/dal/groupService.js
@@ -1,215 +1,312 @@
-'use strict'
-
-const { Group, GroupUser, GroupsPolicy } = require('../models/Group')
-const userService = require('./userService')
-const db = require('../../db')
-
-const GroupService = {
-    async createGroup(ctx) {
-        if (!ctx || !ctx.kcId) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        const user = await userService.detail({ kcId: ctx.kcId });
-        if (!user) {
-            const error = new Error("User account not found.");
-            error.status = 400;
-            throw error;
-        }
-        const [newGroup, isCreated] = await Group.findOrCreate(
-            {
-            where: {
-                name: ctx.name,
-                user_id: user.id,
-            },
-            defaults: {
-                description: ctx.description,
-            },
-        });
-        if (!isCreated) {
-            const error = new Error(`Group:${ctx.name} already exists.`);
-            error.status = 400;
-            throw error;
-        }
-        return newGroup;
-    },
-
-    async createGroupPolicy(ctx) {
-        if (!ctx || !ctx.groupId || !ctx.policyId) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        const groupPolicy = await GroupsPolicy.findOne({
-            where: {
-                group_id: ctx.groupId,
-                policy_id: ctx.policyId
-            }
-        });
-        if (groupPolicy) {
-            const error = new Error(`GroupId:${ctx.groupId} and policyId:${ctx.policyId} already assigned to each other.`);
-            error.status = 400;
-            throw error;
-        } else {
-            return await GroupsPolicy.create({
-                group_id: ctx.groupId,
-                policy_id: ctx.policyId
-            });
-        }
-    },
-
-    async createGroupUser(ctx) {
-        if (!ctx || !ctx.kcId) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        const user = await userService.detail({ kcId: ctx.kcId });
-        if (user) {
-            const groupUser = await GroupUser.findOne({
-                where: {
-                    group_id: ctx.groupId,
-                    user_id: user.id
-                }
-            });
-            if (groupUser) {
-                const error = new Error(`GroupId:${ctx.groupId} and userId:${user.id} already assigned to each other.`);
-                error.status = 400;
-                throw error;
-            } else {
-                return await GroupUser.create({
-                    group_id: ctx.groupId,
-                    user_id: user.id
-                });
-            }
-        } else {
-            const error = new Error('User account not found.');
-            error.status = 400;
-            throw error;
-        }
-    },
-
-    async updateGroup(ctx) {
-        if (!ctx || !ctx.name || !ctx.description || !ctx.id || !ctx.userId) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        return await Group.update({
-            name: ctx.name,
-            description: ctx.description,
-        }, {
-            where: {id: ctx.id, user_id: ctx.userId}
-        });
-    },
-
-    async updateGroupPolicy(ctx) {
-        if (!ctx || !ctx.groupId || !ctx.policyId || !ctx.id) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        return await GroupsPolicy.update({
-            group_id: ctx.groupId,
-            policy_id: ctx.policyId
-        }, {where: {id: ctx.id}});
-    },
-
-    async updateGroupUser(ctx) {
-        if (!ctx || !ctx.kcId) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        const user = await userService.detail({ kcId: ctx.kcId });
-        if (!user) {
-            const error = new Error("User account not found.");
-            error.status = 400;
-            throw error;
-        }
-        return await GroupUser.update({
-            group_id: ctx.groupId,
-            user_id: user.id
-        }, {where: {id: ctx.id}});
-    },
-
-    async deleteGroup(ctx) {
-        if (!ctx || !ctx.id) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        return await Group.destroy({
-            where: {
-                id: ctx.id
-            }
-        });
-    },
-
-    async deleteGroupPolicy(ctx) {
-        if (!ctx || !ctx.id) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        return await GroupsPolicy.destroy({
-            where: {
-                id: ctx.id
-            }
-        });
-    },
-
-    async deleteGroupUser(ctx) {
-        if (!ctx || !ctx.groupId || !ctx.userId) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        const params = { groupId: ctx.groupId, userId: ctx.userId };
-        return db.raw(`delete from group_users where group_id = :groupId and user_id = :userId`, params);
-    },
-
-    async groups() {
-        return await Group.findAll({});
-    },
-
-    async groupPolicies() {
-        return await GroupsPolicy.findAll({});
-    },
-
-    async groupUsers(ctx) {
-        if (!ctx || !ctx.groupId) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        const params = { groupId: ctx.groupId };
-        const groupUsers = await db.raw(`
-              select g.id as groupId, u.id as userId, u.username, g.name, g.description from group_users gu
-              inner join users u on u.id = gu.user_id
-              inner join groups g on gu.group_id = g.id
-              where g.id = :groupId
-        `, params);
-        return groupUsers.rows;
-    }
+"use strict";
+const prisma = require("../../prisma/client");
+
+async function createGroup(name, description, kc_id) {
+  if (!name || !description || !kc_id) {
+    throw Error("The request body is empty!");
+  }
+  const user = await prisma.user.findFirst({
+    where: {
+      kc_id: kc_id,
+    },
+  });
+
+  if (!user) {
+    throw Error("The user account could not be found.");
+  }
+
+  const group = await prisma.group.findFirst({
+    where: {
+      name: name,
+    },
+  });
+  if (group) {
+    throw Error(`A group named '${group.name}' already exists.`);
+  }
+
+  const newGroup = await prisma.group.create({
+    data: {
+      name: name,
+      description: description,
+      admin: {
+        connect: {
+          id: user.id,
+        },
+      },
+    },
+  });
+
+  return newGroup;
 }
 
+async function addPolicyToGroup(policyId, groupId) {
+  if (!groupId || !policyId) {
+    throw Error("The request body is empty!");
+  }
 
-module.exports = {
-    createGroup: GroupService.createGroup,
-    createGroupPolicy: GroupService.createGroupPolicy,
-    createGroupUser: GroupService.createGroupUser,
+  const group = await prisma.group.findFirst({
+    where: {
+      id: +groupId,
+    },
+  });
+
+  if (!group) {
+    throw Error("The group could not be found.");
+  }
+
+  const policy = await prisma.policy.findFirst({
+    where: {
+      id: +policyId,
+    },
+  });
+
+  if (!policy) {
+    throw Error("The policy could not be found.");
+  }
+
+  const groupPolicy = await prisma.group.findFirst({
+    where: {
+      id: +groupId,
+      policies: {
+        some: {
+          policy_id: +policyId,
+        },
+      },
+    },
+  });
+
+  if (groupPolicy) {
+    throw Error("The policy is already assigned to the group.");
+  }
+
+  const newGroupPolicy = await prisma.groupPolicy.create({
+    data: {
+      group_id: +groupId,
+      policy_id: +policyId,
+    },
+  });
+
+  return newGroupPolicy;
+}
+
+async function updateGroup(id, name, description) {
+  if (!name || !description || !id) {
+    throw Error("The request body is empty!");
+  }
+
+  const group = await prisma.group.findFirst({
+    where: {
+      id: +id,
+    },
+  });
+
+  if (!group) {
+    throw Error("The group could not be found.");
+  }
+
+  const updated = await prisma.group.update({
+    where: {
+      id: +id,
+    },
+    data: {
+      name: name,
+      description: description,
+    },
+  });
+
+  return updated;
+}
+
+async function deleteGroup(id) {
+  if (!id) {
+    throw Error("The request body is empty!");
+  }
+  const group = await prisma.group.findFirst({
+    where: {
+      id: +id,
+    },
+  });
+
+  if (!group) {
+    throw Error("The group could not be found.");
+  }
+  const deleted = await prisma.group.delete({
+    where: {
+      id: +id,
+    },
+  });
+
+  return deleted;
+}
+
+async function removePolicyFromGroup(policyId, groupId) {
+  if (!groupId || !policyId) {
+    throw Error("The request body is empty!");
+  }
+
+  const policy = await prisma.policy.findFirst({
+    where: {
+      id: +policyId,
+    },
+  });
+
+  if (!policy) {
+    throw Error("The policy could not be found.");
+  }
+
+  const group = await prisma.group.findFirst({
+    where: {
+      id: +groupId,
+    },
+  });
+
+  if (!group) {
+    throw Error("The group could not be found.");
+  }
+
+  const groupPolicy = await prisma.groupPolicy.delete({
+    where: {
+      group_id_policy_id: {
+        group_id: +groupId,
+        policy_id: +policyId,
+      },
+    },
+  });
 
-    updateGroup: GroupService.updateGroup,
-    updateGroupPolicy: GroupService.updateGroupPolicy,
-    updateGroupUser: GroupService.updateGroupUser,
+  return groupPolicy;
+}
+
+async function addUserToGroup(kc_id, groupId) {
+  if (!kc_id || !groupId) {
+    throw Error("The request body is empty!");
+  }
+
+  const user = await prisma.user.findFirst({
+    where: {
+      kc_id: kc_id,
+    },
+  });
+  if (!user) {
+    throw Error("The user account could not be found.");
+  }
+
+  const group = await prisma.group.findFirst({
+    where: {
+      id: +groupId,
+    },
+  });
+
+  if (!group) {
+    throw Error(
+      "The group could not be found. Please ensure the group exists."
+    );
+  }
+  const newGroupUser = await prisma.groupUser.create({
+    data: {
+      group_id: +groupId,
+      user_id: user.id,
+    },
+  });
+  return newGroupUser;
+}
 
-    deleteGroup: GroupService.deleteGroup,
-    deleteGroupPolicy: GroupService.deleteGroupPolicy,
-    deleteGroupUser: GroupService.deleteGroupUser,
+async function removeUserFromGroup(kc_id, groupId) {
+  if (!groupId || !kc_id) {
+    throw Error("The request body is empty!");
+  }
 
-    groups: GroupService.groups,
-    groupPolicies: GroupService.groupPolicies,
-    groupUsers: GroupService.groupUsers,
+  const user = await prisma.user.findFirst({
+    where: {
+      kc_id: kc_id,
+    },
+  });
+  if (!user) {
+    throw Error("The user account could not be found.");
+  }
+
+  const group = await prisma.group.findFirst({
+    where: {
+      id: +groupId,
+    },
+  });
+
+  if (!group) {
+    throw Error("The group could not be found.");
+  }
+
+  const groupUser = await prisma.groupUser.delete({
+    where: {
+      group_id_user_id: {
+        group_id: +groupId,
+        user_id: user.id,
+      },
+    },
+  });
+
+  return groupUser;
+}
+
+async function getGroup(id) {
+  if (!id) {
+    throw Error("The request body is empty!");
+  }
+  return await prisma.group.findFirst({
+    where: {
+      id: +id,
+    },
+    include: {
+      users: {
+        include: {
+          user: true,
+        },
+      },
+      policies: {
+        include: {
+          policy: {
+            include: {
+              std_fields: {
+                include: {
+                  std_field: true,
+                },
+              },
+              sources: {
+                include: {
+                  source: true,
+                },
+              },
+            },
+          },
+        },
+      },
+    },
+  });
+}
+
+async function getAllGroups() {
+  return await prisma.group.findMany({
+    include: {
+      users: {
+        include: {
+          user: true,
+        },
+      },
+      policies: {
+        include: {
+          policy: true,
+        },
+      },
+    },
+  });
+}
+
+module.exports = {
+  createGroup,
+  addPolicyToGroup,
+  addUserToGroup,
+  updateGroup,
+  deleteGroup,
+  removePolicyFromGroup,
+  removeUserFromGroup,
+  getAllGroups,
+  getGroup,
 };
diff --git a/app/dal/keycloakService.js b/app/dal/keycloakService.js
new file mode 100644
index 0000000000000000000000000000000000000000..d9922befa62db140c9ec263cd2beb6b538f92cf5
--- /dev/null
+++ b/app/dal/keycloakService.js
@@ -0,0 +1,52 @@
+"use strict";
+
+const KcAdminClient = require("keycloak-admin").default;
+
+const keycloakAdmin = new KcAdminClient({
+  baseUrl: process.env.KEYCLOAK_BASE_URL,
+  realmName: "master",
+});
+
+async function auth() {
+  await keycloakAdmin.auth({
+    username: process.env.KEYCLOAK_USER,
+    password: process.env.KEYCLOAK_PASSWORD,
+    grantType: "password",
+    clientId: "admin-cli",
+  });
+}
+
+async function getAllKeycloakUsers() {
+  try {
+    await auth();
+    const users = await keycloakAdmin.users.find({
+      realm: process.env.KEYCLOAK_REALM,
+    });
+
+    return users;
+  } catch (err) {
+    throw Error(err);
+  }
+}
+
+async function deleteKeycloakUser({ kc_id }) {
+  try {
+    if (!kc_id) {
+      throw Error("The kc_id is missing!");
+    }
+
+    await auth();
+
+    return await keycloakAdmin.users.del({
+      id: kc_id,
+      realm: process.env.KEYCLOAK_REALM,
+    });
+  } catch (error) {
+    throw Error(error);
+  }
+}
+
+module.exports = {
+  getAllKeycloakUsers,
+  deleteKeycloakUser,
+};
\ No newline at end of file
diff --git a/app/dal/mongoService.js b/app/dal/mongoService.js
new file mode 100644
index 0000000000000000000000000000000000000000..b022ea1134b637b4ed2daad30b4634c41ee23dbc
--- /dev/null
+++ b/app/dal/mongoService.js
@@ -0,0 +1,32 @@
+const { mongoClient, dbName } = require("@/app/config/mongo");
+const logger = require("../utils/format");
+const { ObjectId } = require("mongodb");
+
+async function addSourceToMongoDB(metadata) {
+  await mongoClient.connect();
+  const db = mongoClient.db(dbName);
+
+  const result = await db.collection("metaurfm").insertOne(metadata);
+  return result;
+}
+
+async function removeSourceFromMongoDB(id) {
+  logger.debug(`Removing source from mongo with id: ${id}`);
+  await mongoClient.connect();
+  const db = mongoClient.db(dbName);
+
+  const result = await db
+    .collection("metaurfm")
+    .deleteOne({ _id: new ObjectId(id) });
+  if (result.deletedCount === 0) {
+    logger.error(`Source with id: ${id} not found`);
+    return false;
+  }
+  logger.debug(`Source with id: ${id} removed`);
+  return true;
+}
+
+module.exports = {
+  addSourceToMongoDB,
+  removeSourceFromMongoDB,
+};
diff --git a/app/dal/policyService.js b/app/dal/policyService.js
index a101a67dfe4f4bc82cfc382465a39437ec928aa3..788d6c369d4c4669508edecca6a3e57835f338f5 100644
--- a/app/dal/policyService.js
+++ b/app/dal/policyService.js
@@ -1,280 +1,418 @@
-'use strict'
-
-const { Policy, PolicyField, PolicySource } = require('../models/Policy')
-const db = require('../../db');
-const userService = require('./userService')
-
-const PolicyService = {
-    async createPolicy(ctx) {
-        if (!ctx || !ctx.kcId) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        const user = await userService.detail({ kcId: ctx.kcId });
-        if (!user) {
-            const error = new Error("User account not found.");
-            error.status = 400;
-            throw error;
-        }
-        const [newPolicy, isCreated] = await Policy.findOrCreate(
-            {
-                where: {
-                    name: ctx.name,
-                    user_id: user.id,
-                },
-                defaults: {
-                    is_default: false
-                },
-            });
-        if (!isCreated) {
-            const error = new Error(`Policy:${ctx.name} already exists.`);
-            error.status = 400;
-            throw error;
-        }
-        return newPolicy;
+"use strict";
+
+const prisma = require("@/prisma/client");
+
+async function createPolicy(name, kc_id) {
+  if (!name || !kc_id) {
+    throw Error("The request body is empty!");
+  }
+
+  const user = await prisma.user.findFirst({
+    where: {
+      kc_id: kc_id,
     },
+  });
 
-    async createPolicyField(ctx) {
-        if (!ctx || !ctx.policyId || !ctx.stdFieldId) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        const [newPolicyField, isCreated] = await PolicyField.findOrCreate(
-            {
-                where: {
-                    policy_id: ctx.policyId,
-                    std_field_id: ctx.stdFieldId,
-                },
-            });
-        if (!isCreated) {
-            const error = new Error("Policy and stdField already assigned to each other.");
-            error.status = 400;
-            throw error;
-        }
-        return newPolicyField;
+  if (!user) {
+    throw Error("The user account could not be found.");
+  }
+
+  const policy = await prisma.policy.findFirst({
+    where: {
+      name: name,
     },
+  });
 
-    async createPolicySource(ctx) {
-        if (!ctx || !ctx.policyId || !ctx.sourceId) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        const [newPolicySource, isCreated] = await PolicySource.findOrCreate(
-            {
-                where: {
-                    policy_id: ctx.policyId,
-                    source_id: ctx.sourceId,
-                },
-            });
-        if (!isCreated) {
-            const error = new Error("Policy and source already assigned to each other.");
-            error.status = 400;
-            throw error;
-        }
-        return newPolicySource;
+  if (policy) {
+    throw Error(`The policy named '${name} already inserted to database!`);
+  }
+
+  const newPolicy = await prisma.policy.create({
+    data: {
+      name: name,
+      user: {
+        connect: {
+          id: user.id,
+        },
+      },
+      is_default: false,
     },
+  });
+
+  return newPolicy;
+}
+
+async function addFieldToPolicy(stdFieldId, policyId) {
+  if (!policyId || !stdFieldId) {
+    throw Error("The request body is empty!");
+  }
+
+  const policy = await prisma.policy.findFirst({
+    where: {
+      id: +policyId,
+    },
+  });
+
+  if (!policy) {
+    throw Error(
+      `This policyId:${policyId} could not be found in the database!`
+    );
+  }
 
-    async updatePolicySource(ctx) {
-        if (!ctx || !ctx.id || !ctx.sourceId) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        return await PolicySource.update({
-            source_id: ctx.sourceId,
-        }, {
-            where: {
-                id: ctx.id
-            }
-        })
+  const stdField = await prisma.stdField.findFirst({
+    where: {
+      id: +stdFieldId,
     },
+  });
+  if (!stdField) {
+    throw Error(
+      `This stdFieldId:${stdFieldId} could not be found in the database!`
+    );
+  }
 
-    async deletePolicySource(ctx) {
-        if (!ctx || !ctx.id) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        return await PolicySource.destroy({
-            where: {
-                id: ctx.id
-            }
-        })
+  const stdFieldPolicy = await prisma.policy.findFirst({
+    where: {
+      id: +policyId,
+      std_fields: {
+        some: {
+          std_field_id: +stdFieldId,
+        },
+      },
     },
+  });
 
-    async updatePolicy(ctx) {
-        if (!ctx || !ctx.id || !ctx.name || !ctx.sourceId || !ctx.isDefault) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        return await Policy.update({
-            name: ctx.name,
-            source_id: ctx.sourceId,
-            is_default: ctx.isDefault
-        }, {
-            where: {
-                id: ctx.id,
-            }
-        })
+  if (stdFieldPolicy) {
+    throw Error(`This stdFieldId:${stdFieldId} already exists in the policy!`);
+  }
+
+  const newPolicyField = await prisma.policyStdField.create({
+    data: {
+      policy: {
+        connect: {
+          id: +policyId,
+        },
+      },
+      std_field: {
+        connect: {
+          id: +stdFieldId,
+        },
+      },
     },
+  });
+
+  return newPolicyField;
+}
 
-    async updatePolicyField(ctx) {
-        if (!ctx || !ctx.id || !ctx.policyId || !ctx.stdFieldId) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        return await PolicyField.update({
-            policy_id: ctx.policyId,
-            std_field_id: ctx.stdFieldId,
-        }, {
-            where: {
-                id: ctx.id
-            }
-        })
+async function addSourceToPolicy(sourceId, policyId) {
+  if (!policyId || !sourceId) {
+    throw Error("The request body is empty!");
+  }
+
+  const policy = await prisma.policy.findFirst({
+    where: {
+      id: +policyId,
     },
+  });
+
+  if (!policy) {
+    throw Error(
+      `This policyId:${policyId} could not be found in the database!`
+    );
+  }
 
-    async deletePolicyField(ctx) {
-        if (!ctx || !ctx.id) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        return await PolicyField.destroy({
-            where: {
-                id: ctx.id
-            }
-        });
+  const source = await prisma.source.findFirst({
+    where: {
+      id: +sourceId,
     },
+  });
+  if (!source) {
+    throw Error(
+      `This sourceId:${sourceId} could not be found in the database!`
+    );
+  }
 
-    async deletePolicy(ctx) {
-        if (!ctx || !ctx.id) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        const policyField = await PolicyField.destroy({
-            where: {
-                policy_id: ctx.id
-            }
-        });
-        await Policy.destroy({
-            where: {
-                id: ctx.id
-            }
-        });
-        return policyField;
+  const sourcePolicy = await prisma.policy.findFirst({
+    where: {
+      id: +policyId,
+      sources: {
+        some: {
+          source_id: +sourceId,
+        },
+      },
     },
+  });
 
-    async policies() {
-        return await Policy.findAll({});
+  if (sourcePolicy) {
+    throw Error(`This sourceId:${sourceId} already exists in the policy!`);
+  }
+
+  const newPolicySource = await prisma.policySource.create({
+    data: {
+      policy_id: +policyId,
+      source_id: +sourceId,
     },
+  });
+  return newPolicySource;
+}
+
+async function removeSourceFromPolicy(sourceId, policyId) {
+  if (!policyId || !sourceId) {
+    throw Error("The request body is empty!");
+  }
 
-    async policiesByUser(ctx) {
-        if (!ctx || !ctx.kcId) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        try {
-            const params = { userId: ctx.kcId };
-            const policiesByUser = await db.raw(`select DISTINCT p.id, p.name, p.user_id, p.source_id, u.kc_id from policies p inner join users u  on p.user_id = u.id where u.kc_id = :userId`, params);
-            return policiesByUser.rows;
-        } catch (error) {
-            throw new Error(error);
-        }
+  const policy = await prisma.policy.findFirst({
+    where: {
+      id: +policyId,
     },
+  });
+
+  if (!policy) {
+    throw Error(
+      `This policyId:${policyId} could not be found in the database!`
+    );
+  }
 
-    async policyFields() {
-        return await PolicyField.findAll({});
+  const source = await prisma.source.findFirst({
+    where: {
+      id: +sourceId,
     },
+  });
 
-    async getAssignedPolicies(ctx) {
-        if (!ctx || !ctx.policyId) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        const params = { policyId: ctx.policyId };
-        const assignedPolicies = await db.raw(`
-            select pf.id, sf.field_name, sf.definition_and_comment, sf.field_type, sf.values from policies p
-            inner join policy_fields pf on p.id = pf.policy_id
-            inner join std_fields sf on pf.std_field_id = sf.id
-            inner join policy_sources ps on p.id = ps.policy_id
-            inner join sources s on ps.source_id = s.id
-            where p.id = :policyId
-        `, params);
-        return assignedPolicies.rows;
+  if (!source) {
+    throw Error(
+      `This sourceId:${sourceId} could not be found in the database!`
+    );
+  }
+
+  const sourcePolicy = await prisma.policy.findFirst({
+    where: {
+      id: +policyId,
+      sources: {
+        some: {
+          source_id: +sourceId,
+        },
+      },
     },
+  });
+
+  if (!sourcePolicy) {
+    throw Error(`This sourceId:${sourceId} does not exist in the policy!`);
+  }
 
-    async getPoliciesWithSources() {
-        const policiesWIthSource = await db.raw(`
-            select p.id, p.name as policyName, s.name as sourceName from policies p
-                left join policy_sources ps on p.id = ps.policy_id
-                left join sources s on ps.source_id = s.id
-        `)
-        return policiesWIthSource.rows
+  const deletedPolicySource = await prisma.policySource.delete({
+    where: {
+      policy_id_source_id: {
+        policy_id: +policyId,
+        source_id: +sourceId,
+      },
     },
+  });
+
+  return deletedPolicySource;
+}
+
+async function updatePolicy(id, name, isDefault) {
+  if (!id || !name || !isDefault) {
+    throw Error("The request body is empty!");
+  }
 
-    async getPoliciesWithSourcesByUser(ctx) {
-        if (!ctx || !ctx.kcId) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        try {
-            const params = { userId: ctx.kcId };
-            const policiesByUser = await db.raw(`
-                select p.id, p.name as policyName, s.name as sourceName, p.user_id, p.source_id, u.kc_id from policies p
-                inner join users u on p.user_id = u.id
-                left join policy_sources ps on p.id = ps.policy_id
-                left join sources s on ps.source_id = s.id
-                where u.kc_id = :userId`, params)
-            return policiesByUser.rows;
-        } catch (error) {
-            throw new Error(error);
-        }
+  const policy = await prisma.policy.update({
+    where: {
+      id: id,
     },
+    data: {
+      name: name,
+      is_default: isDefault,
+    },
+  });
 
-    async getGroupDetailsByPolicy(ctx) {
-        if (!ctx || !ctx.policyId) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        const params = { policyId: ctx.policyId };
-        const groupDetailsByPolicy = await db.raw(`
-            select p.id as policyId, g.id as groupId, gp.id groupPolicyId, g.name as group_name, g.description as group_description, s.name as source_name, s.description as source_description from policies p
-            inner join groups_policies gp on p.id = gp.policy_id
-            inner join groups g on gp.group_id = g.id
-            left join policy_sources ps on p.id = ps.policy_id
-            left join sources s on ps.source_id = s.id
-            where p.id = :policyId
-        `, params);
-        return groupDetailsByPolicy.rows;
-    }
-};
+  return policy;
+}
+
+async function removeFieldFromPolicy(stdFieldId, policyId) {
+  if (!policyId || !stdFieldId) {
+    throw Error("The request body is empty!");
+  }
+
+  const policy = await prisma.policy.findFirst({
+    where: {
+      id: +policyId,
+    },
+  });
+
+  if (!policy) {
+    throw Error(
+      `This policyId:${policyId} could not be found in the database!`
+    );
+  }
+
+  const stdField = await prisma.stdField.findFirst({
+    where: {
+      id: +stdFieldId,
+    },
+  });
+
+  if (!stdField) {
+    throw Error(
+      `This stdFieldId:${stdFieldId} could not be found in the database!`
+    );
+  }
+
+  const stdFieldPolicy = await prisma.policy.findFirst({
+    where: {
+      id: +policyId,
+      std_fields: {
+        some: {
+          std_field_id: +stdFieldId,
+        },
+      },
+    },
+  });
+
+  if (!stdFieldPolicy) {
+    throw Error(`This stdFieldId:${stdFieldId} does not exist in the policy!`);
+  }
+
+  const deletedPolicyField = await prisma.policyStdField.delete({
+    where: {
+      policy_id_std_field_id: {
+        policy_id: +policyId,
+        std_field_id: +stdFieldId,
+      },
+    },
+  });
+
+  return deletedPolicyField;
+}
+
+async function deletePolicy(id) {
+  if (!id) {
+    throw Error("The request body is empty!");
+  }
+
+  const policy = await prisma.policy.findFirst({
+    where: {
+      id: +id,
+    },
+  });
+
+  if (!policy) {
+    throw Error(`This policyId:${id} could
+            not be found in the database!`);
+  }
+
+  const deletedPolicy = await prisma.policy.delete({
+    where: {
+      id: +id,
+    },
+  });
+
+  return deletedPolicy;
+}
+
+async function getAllPolicies() {
+  return await prisma.policy.findMany({
+    include: {
+      std_fields: {
+        include: {
+          std_field: true,
+        },
+      },
+      sources: {
+        include: {
+          source: true,
+        },
+      },
+      groups: {
+        include: {
+          group: {
+            include: {
+              policies: {
+                include: {
+                  policy: {
+                    include: {
+                      std_fields: {
+                        include: {
+                          std_field: true,
+                        },
+                      },
+                      sources: {
+                        include: {
+                          source: true,
+                        },
+                      },
+                    },
+                  },
+                },
+              },
+            },
+          },
+        },
+      },
+    },
+  });
+}
+
+async function getPolicy(policyId) {
+  if (!policyId) {
+    throw Error("The request body is empty!");
+  }
+
+  const assignedPolicies = await prisma.policy.findFirst({
+    where: {
+      id: policyId,
+    },
+    include: {
+      std_fields: {
+        include: {
+          std_field: true,
+        },
+      },
+      sources: {
+        include: {
+          source: true,
+        },
+      },
+      groups: {
+        include: {
+          group: {
+            include: {
+              policies: {
+                include: {
+                  policy: {
+                    include: {
+                      std_fields: {
+                        include: {
+                          std_field: true,
+                        },
+                      },
+                      sources: {
+                        include: {
+                          source: true,
+                        },
+                      },
+                    },
+                  },
+                },
+              },
+            },
+          },
+        },
+      },
+    },
+  });
+
+  return assignedPolicies;
+}
 
 module.exports = {
-    createPolicy: PolicyService.createPolicy,
-    createPolicyField: PolicyService.createPolicyField,
-    createPolicySource: PolicyService.createPolicySource,
-
-    updatePolicy: PolicyService.updatePolicy,
-    updatePolicyField: PolicyService.updatePolicyField,
-
-    deletePolicyField: PolicyService.deletePolicyField,
-    deletePolicy: PolicyService.deletePolicy,
-
-    policies: PolicyService.policies,
-    policiesByUser: PolicyService.policiesByUser,
-    policyFields: PolicyService.policyFields,
-    getAssignedPolicies: PolicyService.getAssignedPolicies,
-    getPoliciesWithSources: PolicyService.getPoliciesWithSources,
-    getPoliciesWithSourcesByUser: PolicyService.getPoliciesWithSourcesByUser,
-    getGroupDetailsByPolicy: PolicyService.getGroupDetailsByPolicy,
+  createPolicy,
+  addFieldToPolicy,
+  addSourceToPolicy,
+  updatePolicy,
+  removeFieldFromPolicy,
+  removeSourceFromPolicy,
+  deletePolicy,
+  getAllPolicies,
+  getPolicy,
 };
diff --git a/app/dal/realmService.js b/app/dal/realmService.js
deleted file mode 100644
index c311b9505d2edbf28a2a620b271c47587a7b9487..0000000000000000000000000000000000000000
--- a/app/dal/realmService.js
+++ /dev/null
@@ -1,37 +0,0 @@
-'use strict'
-
-const db = require('../../db');
-
-const RealmService = {
-    async create(ctx) {
-        return await db('realm').insert({
-            name: ctx.name
-        }).returning('*').then((result) => result[0])
-    },
-
-    async update(ctx) {
-        return db('realm').where('id', ctx.id).update({
-            name: ctx.name
-        });
-    },
-
-    async delete(ctx) {
-        return db.delete().from('realm').where('id', ctx.id).timeout(1000, {cancel: true});
-    },
-
-    async realm(ctx) {
-        return db.select().from('realm').where('id', ctx.id).timeout(1000, {cancel: true});
-    },
-
-    async realms() {
-        return db.select().from('realm').timeout(1000, {cancel: true});
-    }
-}
-
-module.exports = {
-    create: RealmService.create,
-    update: RealmService.update,
-    delete: RealmService.delete,
-    realm: RealmService.realm,
-    realms: RealmService.realms
-}
diff --git a/app/dal/roleAllocationService.js b/app/dal/roleAllocationService.js
deleted file mode 100644
index 09af1515ddf944096b05117599333cd95c1c457f..0000000000000000000000000000000000000000
--- a/app/dal/roleAllocationService.js
+++ /dev/null
@@ -1,77 +0,0 @@
-'use strict'
-
-const db = require('../../db');
-const { RoleUser } = require('../models/Role');
-
-const RoleAllocationService = {
-    // Allocates a role to a user. If a role is already allocated to this user, updates it.
-    async create(ctx) {
-        if (!ctx || !ctx.kc_id) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        const [roleUser, created] = await RoleUser.findOrCreate({
-            where: { kc_id: ctx.kc_id },
-            defaults: { role_id: ctx.role_id }
-        });
-        if (!created) {
-            return await RoleUser.update({ role_id: ctx.role_id, }, {
-                where: {
-                    kc_id: ctx.kc_id
-                }
-            });
-        }
-        return roleUser;
-    },
-
-    // Updates roles allocated to a user.
-    async update(ctx) {
-        if (!ctx || !ctx.kc_id || !ctx.role_id) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        return await RoleUser.update({ role_id: ctx.role_id, }, {
-            where: {
-                kc_id: ctx.kc_id
-            }
-        });
-    },
-
-    // Deletes roles allocated to a user.
-    async delete(ctx) {
-        if (!ctx || !ctx.kc_id) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        return await RoleUser.destroy({
-            where: {
-                kc_id: ctx.kc_id
-            }
-        });
-    },
-
-    // Get allocated roles by user kc_id.
-    async allocatedRolesByKcId(ctx) {
-        if (!ctx || !ctx.kc_id) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        const allocatedRoles = await db.raw(`
-                    select roles.id, u.username as user, roles.name as role , roles.description from roles
-                    inner join roles_users ru on roles.id = ru.role_id
-                    inner join users u on ru.kc_id = u.kc_id
-                    where u.kc_id = ?`, [ctx.kc_id]);
-        return allocatedRoles.rows;
-    },
-};
-
-module.exports = {
-    create: RoleAllocationService.create,
-    allocatedRoles: RoleAllocationService.allocatedRolesByKcId,
-    update: RoleAllocationService.update,
-    delete: RoleAllocationService.delete
-};
diff --git a/app/dal/roleService.js b/app/dal/roleService.js
index 8589381a2d97c7c304a0c25afe6575b19cb0297a..4ef72edce26e987b2bc7fc17d04e62c770f349c7 100644
--- a/app/dal/roleService.js
+++ b/app/dal/roleService.js
@@ -1,69 +1,223 @@
-"use strict"
-
-const db = require('../../db');
-const { Role, RoleUser } = require('../models/Role');
-
-const RoleService = {
-    //  Get all roles
-    async roles() {
-        return await Role.findAll();
-    },
-
-    // Get a role
-    async role(ctx) {
-        if (!ctx || !ctx.id) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        return await Role.findAll({where: {'id': ctx.id}});
-    },
-
-
-    // Update role by id
-    async update(ctx) {
-        if (!ctx || !ctx.id || !ctx.name || !ctx.description) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        return await Role.update({
-            'name': ctx.name,
-            'description': ctx.description
-        }, {
-            where: {'id': ctx.id}
-        });
-    },
-
-    // Create a role
-    async create(ctx) {
-        return await db('roles').insert({
-            name: ctx.name,
-            description: ctx.description
-        }).returning('*').then((result) => result[0]);
-    },
-
-
-    // Delete role
-    async delete(ctx) {
-        if (!ctx || !ctx.id) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        await RoleUser.destroy({
-            where: {
-                role_id: ctx.id
-            }
-        });
-        return await Role.destroy({where: {'id': ctx.id}});
+"use strict";
+
+const prisma = require("@/prisma/client");
+
+async function createRole(name, description) {
+  if (!name || !description) {
+    throw Error("The request body is empty!");
+  }
+
+  const role = await prisma.role.findFirst({
+    where: {
+      name: name,
+    },
+  });
+
+  if (role) {
+    throw Error(`This Role name:${name} already inserted to database!`);
+  } else {
+    const newRole = await prisma.role.create({
+      data: {
+        name: name,
+        description: description,
+      },
+    });
+
+    return newRole;
+  }
+}
+
+async function getRoles() {
+  return await prisma.role.findMany({
+    include: {
+      users: {
+        include: {
+          user: true,
+        },
+      },
+    },
+  });
+}
+
+async function getRole(id) {
+  if (!id) {
+    throw Error("The request body is empty!");
+  }
+  const role = await prisma.role.findFirst({
+    where: {
+      id: +id,
+    },
+    include: {
+      users: {
+        include: {
+          user: true,
+        },
+      },
+    },
+  });
+  return role;
+}
+
+async function getUserRoles(kc_id) {
+  if (!kc_id) {
+    throw Error("The request body is empty!");
+  }
+
+  const user = await prisma.role.findMany({
+    where: {
+      users: {
+        some: {
+          kc_id: kc_id,
+        },
+      },
+    },
+  });
+
+  return user.roles;
+}
+
+async function deleteRole(id) {
+  if (!id) {
+    throw Error("The request body is empty!");
+  }
+
+  const role = await prisma.role.findFirst({
+    where: {
+      id: +id,
     },
+  });
+
+  if (!role) {
+    throw Error("The role could not be found.");
+  }
+
+  const deletedRole = await prisma.role.delete({
+    where: {
+      id: +id,
+    },
+  });
+
+  return deletedRole;
+}
+
+async function updateRole(id, name, description) {
+  if (!id || !name || !description) {
+    throw Error("The request body is empty!");
+  }
+
+  const role = await prisma.role.findFirst({
+    where: {
+      id: +id,
+    },
+  });
+
+  if (!role) {
+    throw Error("The role could not be found.");
+  }
+
+  const updatedRole = await prisma.role.update({
+    where: {
+      id: +id,
+    },
+    data: {
+      name: name,
+      description: description,
+    },
+  });
+
+  return updatedRole;
+}
+
+async function addUserToRole(kc_id, role_id) {
+  if (!kc_id || !role_id) {
+    throw Error("The request body is empty!");
+  }
+
+  const user = await prisma.user.findFirst({
+    where: {
+      kc_id: kc_id,
+    },
+  });
+
+  if (!user) {
+    throw Error("The user account could not be found.");
+  }
+
+  const role = await prisma.role.findFirst({
+    where: {
+      id: +role_id,
+    },
+  });
+
+  if (!role) {
+    throw Error("The role could not be found.");
+  }
+
+  const userRole = await prisma.roleUser.findFirst({
+    where: {
+      user_id: user.id,
+      role_id: role.id,
+    },
+  });
+
+  if (userRole) {
+    throw Error("The user is already assigned to this role.");
+  }
+
+  const updatedRole = await prisma.roleUser.create({
+    data: {
+      role_id: role.id,
+      user_id: user.id,
+    },
+  });
+
+  return updatedRole;
+}
+
+async function removeUserFromRole(kc_id, role_id) {
+  if (!kc_id || !role_id) {
+    throw Error("The request body is empty!");
+  }
+
+  const user = await prisma.user.findFirst({
+    where: {
+      kc_id: kc_id,
+    },
+  });
+
+  if (!user) {
+    throw Error("The user account could not be found.");
+  }
+
+  const role = await prisma.role.findFirst({
+    where: {
+      id: +role_id,
+    },
+  });
+
+  if (!role) {
+    throw Error("The role could not be found.");
+  }
+
+  const updatedRole = await prisma.roleUser.delete({
+    where: {
+      role_id_user_id: {
+        role_id: role.id,
+        user_id: user.id,
+      },
+    },
+  });
+
+  return updatedRole;
 }
 
 module.exports = {
-    create: RoleService.create,
-    roles: RoleService.roles,
-    role: RoleService.role,
-    delete: RoleService.delete,
-    update: RoleService.update,
+  createRole,
+  getRoles,
+  getRole,
+  getUserRoles,
+  deleteRole,
+  updateRole,
+  addUserToRole,
+  removeUserFromRole,
 };
diff --git a/app/dal/searchHistoryService.js b/app/dal/searchHistoryService.js
index 1671d4d5e686409dff0d36c6dd4519e5940994ae..261d58d2c4bbaa8cbb89df0ec6fda4ec53e91a01 100644
--- a/app/dal/searchHistoryService.js
+++ b/app/dal/searchHistoryService.js
@@ -1,69 +1,117 @@
-'use strict'
-
-const userService = require("./userService");
-const { SearchHistory } = require('../models/UserHistory');
-
-const SearchHistoryService = {
-    async create(ctx) {
-        if (!ctx || !ctx.kcId || !ctx.query || !ctx.name || !ctx.uiStructure) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        const user = await userService.detail({ kcId: ctx.kcId });
-        if (!user) {
-            const error = new Error("User account not found.");
-            error.status = 400;
-            throw error;
-        }
-        return await SearchHistory.create({
-            kc_id: user.kc_id,
-            query: ctx.query,
-            name: ctx.name,
-            ui_structure: ctx.uiStructure,
-            description: ctx.description
-        })
+"use strict";
+
+const prisma = require("../../prisma/client");
+
+async function addSearchHistoryToUser(
+  kc_id,
+  query,
+  name,
+  ui_structure,
+  description
+) {
+  if (!query || !name || !ui_structure || !description) {
+    throw Error("The request body is empty!");
+  }
+
+  const user = await prisma.user.findFirst({
+    where: {
+      kc_id: kc_id,
     },
+  });
+  if (!user) {
+    throw Error("The user account could not be found.");
+  }
 
-    async fetchUserSearchHistory(ctx) {
-        if (!ctx || !ctx.kcId) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        return await SearchHistory.findAll({
-            where: {
-                kc_id: ctx.kcId
-            }
-        });
+  const result = prisma.user.update({
+    where: {
+      kc_id: kc_id,
+    },
+    data: {
+      history: {
+        create: {
+          query: query,
+          name: name,
+          ui_structure: ui_structure,
+          description: description,
+        },
+      },
+    },
+    include: {
+      history: true,
     },
+  });
 
-    async update(ctx) {
-        if (!ctx || !ctx.kcId) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        // Not finished ? I don't know why there is no method call to update db.
+  return result;
+}
+
+async function getSearchHistoryByUser(kc_id) {
+  if (!kc_id) {
+    throw Error("The request body is empty!");
+  }
+
+  const user = await prisma.user.findFirst({
+    where: {
+      kc_id: kc_id,
+    },
+  });
+  if (!user) {
+    throw Error("The user account could not be found.");
+  }
+  const result = await prisma.searchHistory.findMany({
+    where: {
+      user_id: user.id,
     },
+  });
 
-    async delete(ctx) {
-        if (!ctx || !ctx.id) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        return await SearchHistory.destroy({
-            where: {
-                id: ctx.id
-            }
-        });
-    }
-};
+  return result;
+}
+
+async function deleteHistory(id) {
+  if (!id) {
+    throw Error("The request body is empty!");
+  }
+
+  const history = await prisma.searchHistory.findFirst({
+    where: {
+      id: +id,
+    },
+  });
+
+  if (!history) {
+    throw Error("The history could not be found.");
+  }
+
+  return await prisma.searchHistory.delete({
+    where: {
+      id: +id,
+    },
+  });
+}
+
+async function deleteAllHistoryByUser(kc_id) {
+  if (!kc_id) {
+    throw Error("The request body is empty!");
+  }
+
+  const user = await prisma.user.findFirst({
+    where: {
+      kc_id: kc_id,
+    },
+  });
+  if (!user) {
+    throw Error("The user account could not be found.");
+  }
+
+  return await prisma.searchHistory.deleteMany({
+    where: {
+      user_id: user.id,
+    },
+  });
+}
 
 module.exports = {
-    create: SearchHistoryService.create,
-    update: SearchHistoryService.update,
-    delete: SearchHistoryService.delete,
-    fetch: SearchHistoryService.fetchUserSearchHistory
+  addSearchHistoryToUser,
+  deleteHistory,
+  getSearchHistoryByUser,
+  deleteAllHistoryByUser,
 };
diff --git a/app/dal/sourceService.js b/app/dal/sourceService.js
new file mode 100644
index 0000000000000000000000000000000000000000..b238810f15b8e3bf1a21b70940ac2fb05c42ac22
--- /dev/null
+++ b/app/dal/sourceService.js
@@ -0,0 +1,295 @@
+"use strict";
+const prisma = require("@/prisma/client");
+const {
+  addSourceToMongoDB,
+  removeSourceFromMongoDB,
+} = require("@/app/dal/mongoService");
+const {
+  prepareForBulk,
+  bulk,
+  countByIndex,
+  deleteIndex,
+} = require("@/app/dal/elasticService");
+const logger = require("@/app/utils/format");
+
+async function getSources() {
+  return await prisma.source.findMany({
+    include: {
+      source_indices: true,
+      providers: {
+        include: {
+          user: true,
+        },
+      },
+    },
+  });
+}
+
+async function getSource(id) {
+  if (!id) {
+    throw new Error("Missing required parameter: id");
+  }
+
+  return await prisma.source.findUnique({
+    where: {
+      id,
+    },
+    include: {
+      source_indices: true,
+      providers: {
+        include: {
+          user: true,
+        },
+      },
+    },
+  });
+}
+
+async function getSourcesByProvider(kc_id) {
+  if (!kc_id) {
+    throw new Error("Missing required parameter: kc_id");
+  }
+
+  return await prisma.source.findMany({
+    where: {
+      providers: {
+        some: {
+          user: {
+            kc_id,
+          },
+        },
+      },
+    },
+    include: {
+      source_indices: true,
+      providers: {
+        include: {
+          user: true,
+        },
+      },
+    },
+  });
+}
+
+async function getIndexedSourcesByProvider(kc_id) {
+  if (!kc_id) {
+    throw new Error("Missing required parameter: kc_id");
+  }
+
+  return await prisma.source.findMany({
+    where: {
+      providers: {
+        some: {
+          user: {
+            kc_id,
+          },
+        },
+      },
+      source_indices: {
+        some: {},
+      },
+    },
+    include: {
+      source_indices: true,
+      providers: {
+        include: {
+          user: true,
+        },
+      },
+    },
+  });
+}
+
+async function getIndexedSources() {
+  return await prisma.source.findMany({
+    where: {
+      source_indices: {
+        some: {},
+      },
+    },
+    include: {
+      source_indices: true,
+      providers: {
+        include: {
+          user: true,
+        },
+      },
+    },
+  });
+}
+
+async function createSource(name, description, metaUrfms, kc_id) {
+  if (!name) {
+    throw new Error("Missing required parameter: name");
+  }
+
+  if (!description) {
+    throw new Error("Missing required parameter: description");
+  }
+
+  if (!kc_id) {
+    throw new Error("Missing required parameter: kc_id");
+  }
+
+  const user = await prisma.user.findUnique({
+    where: {
+      kc_id,
+    },
+  });
+
+  if (!user) {
+    throw new Error("User not found");
+  }
+
+  const existingSource = await prisma.source.findFirst({
+    where: {
+      name,
+    },
+  });
+
+  if (existingSource) {
+    throw new Error("Source already exists");
+  }
+
+  if (!metaUrfms) {
+    throw new Error("Missing required parameter: metaUrfms");
+  }
+
+  const metadata = {
+    name,
+    description,
+    metaUrfms,
+  };
+
+  const result = await addSourceToMongoDB(metadata);
+
+  if (!result) {
+    throw new Error("Failed to create source");
+  }
+  const { insertedId } = result;
+
+  logger.debug(`Inserted source with id: ${insertedId}`);
+  const elkIndex = `${name.split(/\s/).join("").toLowerCase()}-${insertedId}`;
+  logger.debug(`Indexing documents with index: ${elkIndex}`);
+
+  const body = await prepareForBulk(metaUrfms, elkIndex);
+  try {
+    const success = await bulk(body);
+    if (!success) {
+      throw new Error("Failed to index documents");
+    }
+
+    const newSource = await prisma.source.create({
+      data: {
+        name,
+        description,
+        source_indices: {
+          create: {
+            mng_id: insertedId,
+            index_id: elkIndex,
+            is_send: true,
+          },
+        },
+      },
+      include: {
+        source_indices: true,
+        providers: {
+          include: {
+            user: true,
+          },
+        },
+      },
+    });
+
+    logger.debug(`Created source with id: ${newSource.id}`);
+
+    await prisma.sourceUser.create({
+      data: {
+        source_id: newSource.id,
+        user_id: user.id,
+      },
+    });
+
+    logger.debug(
+      `Assigned source with id: ${newSource.id} to provider with id: ${user.id}`
+    );
+
+    return newSource;
+  } catch (error) {
+    logger.error("Error while inserting in elastic", error);
+    await removeSourceFromMongoDB(insertedId);
+    await deleteIndex(elkIndex);
+    const sourceToDelete = await prisma.source.findUnique({
+      where: {
+        source_indices: {
+          some: {
+            mng_id: insertedId,
+          },
+        },
+      },
+    });
+    await prisma.source.deleteMany({
+      where: {
+        id: sourceToDelete.id,
+      },
+    });
+    await prisma.sourceUser.deleteMany({
+      where: {
+        source_id: sourceToDelete.id,
+      },
+    });
+    throw new Error("Failed to create source");
+  }
+}
+
+async function deleteSource(id) {
+  if (!id) {
+    throw new Error("Missing required parameter: id");
+  }
+  id = +id;
+  logger.debug(`Deleting source with id: ${id}`);
+  const source = await prisma.source.findUnique({
+    where: {
+      id,
+    },
+    include: {
+      source_indices: true,
+    },
+  });
+
+  if (!source) {
+    logger.error(`Source with id: ${id} not found`);
+    throw new Error("Source not found");
+  }
+  logger.debug(`Found source with id: ${id}`);
+  const source_indices = source.source_indices.length;
+  if (source_indices > 0) {
+    const { mng_id, index_id } = source.source_indices[0];
+
+    if (mng_id) {
+      await removeSourceFromMongoDB(mng_id);
+    }
+    if (index_id) {
+      await deleteIndex(index_id);
+    }
+  }
+
+  await prisma.source.delete({
+    where: {
+      id,
+    },
+  });
+
+  logger.debug(`Deleted source with id: ${id}`);
+  return true;
+}
+
+module.exports = {
+  getSources,
+  getSource,
+  getSourcesByProvider,
+  getIndexedSourcesByProvider,
+  createSource,
+  deleteSource,
+  getIndexedSources,
+};
diff --git a/app/dal/stdFieldService.js b/app/dal/stdFieldService.js
new file mode 100644
index 0000000000000000000000000000000000000000..c9d0b097dc5b00bbbb6ae416738298da4f99c408
--- /dev/null
+++ b/app/dal/stdFieldService.js
@@ -0,0 +1,166 @@
+"use strict";
+const prisma = require("../../prisma/client");
+const logger = require("@/app/utils/format");
+
+async function getStdFields() {
+    const stdFields = await prisma.stdField.findMany({
+        include: {
+            policies: {
+                include: {
+                    policy: {
+                        include: {
+                            sources: {
+                                include: {
+                                    source: true,
+                                },
+                            },
+                        },
+                    },
+                },
+            },
+        },
+    });
+    return stdFields;
+}
+
+async function getPublicStdFields() {
+    const stdFields = await prisma.stdField.findMany({
+        where: {
+            ispublic: true,
+        },
+        include: {
+            policies: {
+                include: {
+                    policy: {
+                        include: {
+                            sources: {
+                                include: {
+                                    source: true,
+                                },
+                            },
+                        },
+                    },
+                },
+            },
+        },
+    });
+    return stdFields;
+}
+
+async function getStdField(id) {
+    if (!id) {
+        throw Error("The request body is empty!");
+    }
+
+    const stdField = await prisma.stdField.findUnique({
+        where: {
+            id: +id,
+        },
+    });
+
+    if (!stdField) {
+        throw Error(
+            `The stdField with id ${id} could not be found in the database!`
+        );
+    }
+
+    return stdField;
+}
+
+async function createOrUpdateStdField({
+                                          id,
+                                          category,
+                                          field_name,
+                                          definition_and_comment,
+                                          obligation_or_condition,
+                                          cardinality,
+                                          field_type,
+                                          values,
+                                          ispublic,
+                                          isoptional,
+                                          list_url, default_display_fields
+                                      }) {
+    if (!field_name) {
+        throw Error("The request body is empty!");
+    }
+
+    logger.debug(default_display_fields);
+    // Transform string to bool
+    const is_default_display_fields = default_display_fields === "1" ? true : false;
+
+    if (id) {
+        const stdField = await prisma.stdField.findFirst({
+            where: {
+                id: +id,
+            },
+        });
+
+        if (!stdField) {
+            throw Error(`The stdField with id '${id} doesn't exist`);
+        }
+
+        if (!typeof ispublic === "boolean" || !typeof isoptional === "boolean") {
+            throw Error("ispublic and isoptional must be boolean");
+        }
+
+        return await prisma.stdField.update({
+            where: {
+                id: +id,
+            },
+            update: {
+                category,
+                definition_and_comment,
+                obligation_or_condition,
+                cardinality,
+                field_type,
+                values,
+                ispublic,
+                isoptional,
+                list_url,
+                default_display_fields: is_default_display_fields
+            },
+        });
+    } else {
+        // Need to create the std_field
+        const stdField = await prisma.stdField.findFirst({
+            where: {
+                field_name: field_name,
+            },
+        });
+
+        if (stdField) {
+            throw Error(
+                `The stdField named '${field_name} already inserted to database!`
+            );
+        }
+
+        const newStdField = await prisma.stdField.create({
+            data: {
+                category,
+                field_name,
+                definition_and_comment,
+                obligation_or_condition,
+                cardinality,
+                field_type,
+                values,
+                ispublic,
+                isoptional,
+                list_url,
+                default_display_fields: is_default_display_fields
+            },
+        });
+        return newStdField;
+    }
+}
+
+async function deleteAllStdFields() {
+    return await prisma.stdField.deleteMany();
+}
+
+module.exports = {
+    getStdField,
+    getStdFields,
+    getPublicStdFields,
+    createOrUpdateStdField,
+    deleteAllStdFields,
+};
diff --git a/app/dal/userDisplayFieldsService.js b/app/dal/userDisplayFieldsService.js
new file mode 100644
index 0000000000000000000000000000000000000000..a3ad2b6963cc9eaeb9b438b4b374665113e7821b
--- /dev/null
+++ b/app/dal/userDisplayFieldsService.js
@@ -0,0 +1,66 @@
+"use strict";
+
+const prisma = require("@/prisma/client");
+const logger = require("../utils/format");
+
+async function getUserDisplayFields(kc_id) {
+  return await prisma.stdField.findMany({
+    where: {
+      display_fields: {
+        some: {
+          user: {
+            kc_id: kc_id,
+          },
+        },
+      },
+    },
+  });
+}
+
+async function setUserDisplayFields(kc_id, fields_ids) {
+  const user = await prisma.user.findFirst({
+    where: {
+      kc_id: kc_id,
+    },
+  });
+
+  if (!user) {
+    throw new Error("User not found");
+  }
+
+  let ids = [];
+  // Reset the user display fields
+  try {
+    await prisma.displayStdField.deleteMany({
+      where: {
+        user_id: user.id,
+      },
+    });
+  } catch (err) {
+    logger.error("Error while resetting user display fields", {
+      error: err.message,
+    });
+  }
+  for (const field_id of fields_ids) {
+    try {
+      const id = await prisma.displayStdField.create({
+        data: {
+          user_id: user.id,
+          std_field_id: +field_id,
+        },
+      });
+      ids.push(id);
+    } catch (err) {
+      logger.error("Error while adding user display field", {
+        error: err.message,
+      });
+    }
+  }
+  return ids;
+}
+
+module.exports = {
+  getUserDisplayFields,
+  setUserDisplayFields,
+  setUserDisplayFields,
+};
diff --git a/app/dal/userFieldsDisplaySettingsService.js b/app/dal/userFieldsDisplaySettingsService.js
deleted file mode 100644
index 48af77e0444767993b827a60ce0ce0cd360d15d4..0000000000000000000000000000000000000000
--- a/app/dal/userFieldsDisplaySettingsService.js
+++ /dev/null
@@ -1,117 +0,0 @@
-"use strict"
-
-const {UserFieldsDisplaySettings} = require("../models/UserFieldsDisplaySettings");
-
-/*
-  userFieldsDisplaySettingsService
-  Manage all users fields display settings
-  Used in search tool for results table columns
-*/
-const userFieldsDisplaySettingsService = {
-
-  // POST create fields settings for a specific user
-  // userId: id of the user
-  // stdFieldsIds: array of ids of fields selected by user
-  async create(ctx) {
-      if (!ctx || !ctx.userId || !ctx.stdFieldsIds) {
-        const error = new Error("Required parameters are missing.");
-        error.status = 400;
-        throw error;
-      }
-      // Check if all fields ids exists
-      if (!await UserFieldsDisplaySettings.validateStdFieldIds(ctx.stdFieldsIds)) {
-        const error = new Error("One or more std_field_id do not exists.");
-        error.status = 400;
-        throw error;
-      }
-      // Insert new row in user settings table
-      const [newUserFieldsSettings, isCreated] = await UserFieldsDisplaySettings.findOrCreate({
-        where: { user_id: ctx.userId }, // Unique field(s) to check for existence
-        defaults: {
-          std_fields_ids: ctx.stdFieldsIds,
-        },
-      });
-      if (!isCreated) {
-        const error = new Error("User fields display settings already exists.");
-        error.status = 400;
-        throw error;
-      }
-      return { newUserFieldsSettings, status: 201 };
-  },
-
-  // GET all users fields settings
-  async usersFieldsDisplaySettings() {
-    return await UserFieldsDisplaySettings.findAll({});
-  },
-
-  // GET single user settings
-  // userId: id of the user
-  async userFieldsDisplaySettings(ctx) {
-    if (!ctx || !ctx.userId) {
-      const error = new Error("Required parameters are missing.");
-      error.status = 400;
-      throw error;
-    }
-    const result = await UserFieldsDisplaySettings.findOne({ where: { user_id: ctx.userId } });
-    if (!result) {
-      const error = new Error("No settings found for this userId.");
-      error.status = 404;
-      throw error;
-    }
-    return result;
-  },
-
-  // PUT update a user settings
-  // userId: id of the user
-  // stdFieldsIds: new array of all fields ids
-  async update(ctx) {
-    if (!ctx || !ctx.userId || !ctx.stdFieldsIds) {
-      const error = new Error("Required parameters are missing.");
-      error.status = 400;
-      throw error;
-    }
-    // Check if all fields ids exists
-    if (!await UserFieldsDisplaySettings.validateStdFieldIds(ctx.stdFieldsIds)) {
-      const error = new Error("One or more std_field_id do not exists.");
-      error.status = 400;
-      throw error;
-    }
-    const [updatedCount, updatedRows] = await UserFieldsDisplaySettings.update({
-      std_fields_ids: ctx.stdFieldsIds,
-    }, { where: { user_id: ctx.userId }});
-    if (updatedCount === 0) {
-      const error = new Error("No settings found for this userId.");
-      error.status = 404;
-      throw error;
-    }
-    return updatedRows ? updatedRows[0] : { message: 'User fields display settings updated.'};
-  },
-
-  // DELETE the user settings
-  async delete(ctx) {
-    if (!ctx || !ctx.userId) {
-      const error = new Error("Required parameters are missing.");
-      error.status = 400;
-      throw error;
-    }
-    const deletedCount = await UserFieldsDisplaySettings.destroy({
-      where: {
-        user_id: ctx.userId
-      }
-    });
-    if (deletedCount === 0) {
-      const error = new Error("No settings found for this userId.");
-      error.status = 404;
-      throw error;
-    }
-    return {message: 'User fields display settings deleted.'};
-  },
-}
-
-module.exports = {
-  create: userFieldsDisplaySettingsService.create,
-  usersFieldsDisplaySettings: userFieldsDisplaySettingsService.usersFieldsDisplaySettings,
-  userFieldsDisplaySettings: userFieldsDisplaySettingsService.userFieldsDisplaySettings,
-  delete: userFieldsDisplaySettingsService.delete,
-  update: userFieldsDisplaySettingsService.update,
-};
diff --git a/app/dal/userRequestService.js b/app/dal/userRequestService.js
index d0c0c10a657bc222416ab8fc1173dfb06d05b6c9..e3a3b7709e2a4539d5ee7c8949323447711f8765 100644
--- a/app/dal/userRequestService.js
+++ b/app/dal/userRequestService.js
@@ -1,88 +1,145 @@
-'use strict'
-
-const userService = require("./userService");
-const { UserRequest } = require('../models/UserRequest');
-
-const UserRequestService = {
-    async create(ctx) {
-        if (!ctx || !ctx.kcId || !ctx.message) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        const user = await userService.detail({ kcId: ctx.kcId });
-        if (!user) {
-            const error = new Error("User account not found.");
-            error.status = 400;
-            throw error;
-        }
-        return await UserRequest.create({
-            user_id: user.id,
-            request_message: ctx.message,
-            is_processed: false,
-        });
+"use strict";
+
+const prisma = require("@/prisma/client");
+
+async function createRequest(kc_id, message) {
+  if (!kc_id || !message) {
+    throw Error("The request body is empty!");
+  }
+
+  const user = await prisma.user.findFirst({
+    where: {
+      kc_id: kc_id,
     },
+  });
 
-    async getAllRequests() {
-        return await UserRequest.findAll({});
+  if (!user) {
+    throw Error("The user account could not found.");
+  }
+
+  const result = await prisma.userRequest.create({
+    data: {
+      user: {
+        connect: {
+          id: user.id,
+        },
+      },
+      request_message: message,
+      is_processed: false,
     },
+  });
+  return result;
+}
 
-    async getUserRequests(ctx) {
-        if (!ctx || !ctx.kcId) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        const user = await userService.detail({ kcId: ctx.kcId })
-        if (user) {
-            return await UserRequest.findAll({
-                where: {
-                    user_id: user.id
-                }
-            });
-        }
+async function getAllRequests() {
+  return await prisma.userRequest.findMany();
+}
+
+async function getAllPendingRequests() {
+  const requests = await prisma.userRequest.findMany({
+    where: {
+      is_processed: false,
     },
+  });
+
+  return requests;
+}
 
-    async getPendingRequests() {
-        return await UserRequest.findAll({
-            where: {
-                is_processed: false
-            }
-        });
+async function updateRequest(id, isProcessed) {
+  if (!id || isProcessed === undefined) {
+    throw Error("The request body is empty!");
+  }
+
+  const request = await prisma.userRequest.findFirst({
+    where: {
+      id: +id,
     },
+  });
+  if (!request) {
+    throw Error("The request could not found.");
+  }
 
-    async process(ctx) {
-        if (!ctx || !ctx.id) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        return await UserRequest.update({
-            is_processed: true,
-        }, {
-            where: {id: ctx.id}
-        });
+  const result = await prisma.userRequest.update({
+    where: {
+      id: +id,
+    },
+    data: {
+      is_processed: isProcessed,
     },
+  });
 
-    async delete(ctx) {
-        if (!ctx || !ctx.id) {
-            const error = new Error("Required parameters are missing.");
-            error.status = 400;
-            throw error;
-        }
-        return await UserRequest.destroy({
-            where: {
-                id: ctx.id
-            }
-        });
-    }
+  return result;
 }
 
-module.exports = {
-    create: UserRequestService.create,
-    fetch: UserRequestService.getAllRequests,
-    fetchPending: UserRequestService.getPendingRequests,
-    fetchByUser: UserRequestService.getUserRequests,
-    process: UserRequestService.process,
-    delete: UserRequestService.delete,
+async function getUserRequests(kc_id) {
+  if (!kc_id) {
+    throw Error("The request body is empty!");
+  }
+
+  const user = await prisma.user.findFirst({
+    where: {
+      kc_id: kc_id,
+    },
+  });
+
+  if (!user) {
+    throw Error("The user account could not found.");
+  }
+
+  const requests = await prisma.userRequest.findMany({
+    where: {
+      user_id: user.id,
+    },
+  });
+
+  return requests;
+}
+
+async function getPendingRequests(kc_id) {
+  if (!kc_id) {
+    throw Error("The request body is empty!");
+  }
+
+  const user = await prisma.user.findFirst({
+    where: {
+      kc_id: kc_id,
+    },
+  });
+
+  if (!user) {
+    throw Error("The user account could not found.");
+  }
+
+  const requests = await prisma.userRequest.findMany({
+    where: {
+      user_id: user.id,
+      is_processed: false,
+    },
+  });
+
+  return requests;
+}
+
+async function deleteRequest(id) {
+  if (!id) {
+    throw Error("The request body is empty!");
+  }
+
+  const result = await prisma.userRequest.delete({
+    where: {
+      id: +id,
+    },
+  });
+
+  return result;
 }
+
+module.exports = {
+  createRequest,
+  getAllRequests,
+  getUserRequests,
+  getAllPendingRequests,
+  getPendingRequests,
+  updateRequest,
+  deleteRequest,
+};
diff --git a/app/dal/userService.js b/app/dal/userService.js
index 3ffe89eaeec26b27436b01ba180b746e69b19829..fdcd57e738e7bd047893bb9846fd8c3c389d793b 100644
--- a/app/dal/userService.js
+++ b/app/dal/userService.js
@@ -1,394 +1,126 @@
-"use strict"
+"use strict";
 
-const KcAdminClient = require("keycloak-admin").default;
-const db = require('../../db');
-const { User } = require('../models/User');
-const { RoleUser } = require('../models/Role');
-const { postgresSeq } = require('../config/db');
-const { BotService, MailService } = require('@in-sylva/common');
-const { Op } = require("sequelize");
-const bcrypt = require('bcrypt');
+const prisma = require("../../prisma/client");
+const { deleteKeycloakUser } = require("../dal/keycloakService");
 
-const mailService = new MailService();
-mailService.auth_user = process.env.IN_SYLVA_EMAIL;
-mailService.auth_pass = process.env.IN_SYLVA_EMAIL_PASSWORD;
-mailService.smtp_host = process.env.IN_SYLVA_SMTP_HOST;
-mailService.smtp_port = process.env.IN_SYLVA_SMTP_PORT;
-mailService.smtp_secure = true;
-
-const botService = new BotService();
-botService.token = process.env.BOT_SERVICE_TOKEN;
-botService.channel = process.env.BOT_SERVICE_CHANNEL;
-
-const keycloakAdmin = new KcAdminClient({
-  baseUrl: `${process.env.IN_SYLVA_KEYCLOAK_HOST}:${process.env.IN_SYLVA_KEYCLOAK_PORT}/keycloak/auth`,
-  realmName: "master"
-});
-
-const auth = async () => {
-  await keycloakAdmin.auth({
-    username: process.env.KEYCLOAK_USERNAME,
-    password: process.env.KEYCLOAK_PASSWORD,
-    grantType: process.env.KEYCLOAK_GRANT_TYPE,
-    clientId: process.env.KEYCLOAK_CLIENT_ID,
+async function getUsers() {
+  return await prisma.user.findMany({
+    include: {
+      roles: {
+        include: {
+          role: true,
+        },
+      },
+      groups: {
+        include: {
+          group: true,
+        },
+      },
+      group_admin: true,
+    },
   });
 }
 
-const generatePassword = async (length) => {
-  const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", retVal = [];
-  for (let i = 0, n = charset.length; i < length; ++i) {
-    retVal.push(charset.charAt(Math.floor(Math.random() * n)));
+async function getUser(kc_id) {
+  if (!kc_id) {
+    return null;
   }
-  const password = retVal.join("");
-  const salt = bcrypt.genSaltSync();
-  return bcrypt.hashSync(password, salt);
-}
 
-const UserService = {
-  // POST Create a user account
-  async create(ctx) {
-    if (!ctx || !ctx.username || !ctx.email || !ctx.password) {
-      const error = new Error("Required parameters are missing.");
-      error.status = 400;
-      throw error;
-    }
-    // Check roleId or assign to default role "normal-user"
-    const roleId = ctx.roleId || 3;
-    // TODO fetch roles ids and verify that ctx.roleId is included
-    // TODO assign roleId of normal-user dynamically ? instead of hard-coded value 3
-    if (![1, 2, 3].includes(roleId)) {
-      const error = new Error("RoleId must be either 1, 2 or 3.");
-      error.status = 400;
-      throw error;
-    }
-    const t = await postgresSeq.transaction();
-    await auth();
-    const [newUser, isCreated] = await User.findOrCreate({
-      where: {
-        username: ctx.username,
-        email: ctx.email,
+  return await prisma.user.findFirst({
+    where: {
+      kc_id: kc_id,
+    },
+    include: {
+      roles: {
+        include: {
+          role: true,
+        },
       },
-      defaults: {
-        password: ctx.password
+      groups: {
+        include: {
+          group: {
+            include: {
+              policies: true,
+            },
+          },
+        },
       },
-    });
-    if (!isCreated) {
-      const error = new Error(`User ${ctx.email} or ${ctx.username} already exists.`);
-      error.status = 400;
-      throw error;
-    }
-    // Insert new user into keycloak db
-    const kcUser = await keycloakAdmin.users.create({
-      username: ctx.username,
-      email: ctx.email,
-      emailVerified: true,
-      enabled: true,
-      realm: process.env.KEYCLOAK_REALM,
-    });
-    if (!kcUser.id) {
-      await t.rollback();
-    }
-    // Set new user's password in kc
-    await keycloakAdmin.users.resetPassword({
-      id: kcUser.id,
-      credential: {
-        temporary: false,
-        type: 'password',
-        value: ctx.password
+      group_admin: true,
+      requests: true,
+      display_fields: {
+        include: {
+          std_field: true,
+        },
       },
-      realm: process.env.KEYCLOAK_REALM,
-    });
-    // Set user kc_id in db
-    await User.update({
-      kc_id: kcUser.id
-    }, {
-      where: {
-        id: newUser.id
-      }
-    });
-    // User Role allocation, default user is normal-user
-    await RoleUser.create({
-      role_id: roleId,
-      kc_id: kcUser.id
-    })
-    await t.commit();
-    const date = new Date().toLocaleDateString();
-    const message = `[INFO]:[User ${ctx.username} is created with this email address: ${ctx.email} successfully.]:[${date}]`;
-    const subject = "In-Sylva new user added";
-    await mailService.send(process.env.IN_SYLVA_EMAIL_FROM, process.env.IN_SYLVA_EMAIL_TO, subject, "", message);
-    await botService.message(message);
-    return newUser;
-  },
-
-  // GET list users
-  // Backlog: security vulnerability. Realm structure should implement here.
-  async users(){
-      await auth();
-      return await keycloakAdmin.users.find({
-        realm: process.env.KEYCLOAK_REALM
-      });
-  },
-
-  // GET Fetch single user
-  async user(ctx) {
-    if (!ctx || !ctx.id) {
-      const error = new Error("Required parameters are missing.");
-      error.status = 400;
-      throw error;
-    }
-    await auth();
-    return await keycloakAdmin.users.findOne({
-      id: ctx.id, realm: process.env.KEYCLOAK_REALM,
-    });
-  },
+    },
+  });
+}
 
-  // GET kc_id from email
-  async kcId(ctx) {
-    if (!ctx || !ctx.email) {
-      const error = new Error("Required parameters are missing.");
-      error.status = 400;
-      throw error;
-    }
-    const { kc_id } = await db.select('kc_id').from('users').where('email', ctx.email).timeout(1000, { cancel: true }).then((result) => result[0]);
-    const role = await RoleUser.findOne({
-      attributes: ['role_id'],
-      where: {
-        kc_id: kc_id
-      }
-    });
-    return { kcId: kc_id, role: role };
-  },
+async function createUser(kc_id, email) {
+  if (!kc_id || !email) {
+    throw Error("The request body is empty!");
+  }
 
-  // GET user account details
-  // TODO return user details such as roles and policies
-  async detail(ctx) {
-    if (!ctx || !ctx.kcId) {
-      const error = new Error("Required parameters are missing.");
-      error.status = 400;
-      throw error;
-    }
-    return await db.select("*").from('users').where('kc_id', ctx.kcId).timeout(1000, {cancel: true}).then((result) => result[0]);
-  },
+  const user = await prisma.user.findFirst({
+    where: {
+      kc_id: kc_id,
+    },
+  });
 
-  // GET users assigned to a role
-  async getAssignedUserByRole(ctx) {
-    if (!ctx || !ctx.id) {
-      const error = new Error("Required parameters are missing.");
-      error.status = 400;
-      throw error;
-    }
-    const params = { roleId: ctx.id };
-    const assignedUserByRole = await db.raw(`
-      select u.username as username,u.email as useremail, r.name as rolename from roles r
-      inner join roles_users ru on r.id = ru.role_id
-      inner join users u on ru.kc_id = u.kc_id
-      where r.id = :roleId
-    `, params);
-    return assignedUserByRole.rows;
-  },
+  if (user) {
+    throw Error("User already exists!");
+  }
 
-  // PUT update the user.
-  async update(ctx) {
-    if (!ctx || !ctx.id) {
-      const error = new Error("Required parameters are missing.");
-      error.status = 400;
-      throw error;
-    }
-    await auth();
-    const userId = ctx.id
-    keycloakAdmin.setConfig({
-      realmName: process.env.KEYCLOAK_REALM
-    });
-    await keycloakAdmin.users.update(
-        { id: userId },
-        {
-          firstName: ctx.firstName,
-          lastName: ctx.lastName,
-          // email: ctx.email,
-          emailVerified: true,
-        });
-    const user = await keycloakAdmin.users.findOne({
-      id: userId, realm: process.env.KEYCLOAK_REALM,
-    });
-    await db('users').where('kc_id', userId).update({
-          firstname: ctx.firstName,
-          lastname: ctx.lastName
-        }).returning('*').then((result) => result[0]);
-    return user;
-  },
+  const newUser = await prisma.user.create({
+    data: {
+      kc_id: kc_id,
+      email,
+    },
+  });
 
-  // DELETE a user
-  async delete(ctx) {
-    if (!ctx || !ctx.userId) {
-      const error = new Error("Required parameters are missing.");
-      error.status = 400;
-      throw error;
-    }
-    await auth();
-    const deleted = await User.destroy({
-      where: { kc_id: ctx.userId }
-    });
-    if (deleted) {
-      return await keycloakAdmin.users.del({
-        id: ctx.userId,
-        realm: process.env.KEYCLOAK_REALM
-      })
-    }
-  },
+  await prisma.roleUser.create({
+    data: {
+      role_id: 3,
+      user_id: newUser.id,
+    },
+  });
 
-  // POST create the system admin.
-  // It should be used once at system start-up.
-  async createSystemUser() {
-    await auth();
-    const checkUser = await User.findAndCountAll({
-      where: {
-        [Op.or]: [
-          { username: "admin" },
-          { email: "admin@inrae.fr" }
-        ]
-      }
-    });
-    if (checkUser.count) {
-      return { user: null, status: 409 };
-    }
-    // Insert new user into keycloak db
-    const kc_user = await keycloakAdmin.users.create({
-      username: "admin",
-      email: process.env.IN_SYLVA_ADMIN_USERNAME,
-      emailVerified: true,
-      enabled: true,
-      realm: process.env.KEYCLOAK_REALM,
-    });
-    // Set new user's password
-    if (kc_user) {
-      await keycloakAdmin.users.resetPassword({
-        id: kc_user.id,
-        credential: {
-          temporary: false,
-          type: 'password',
-          value: process.env.IN_SYLVA_ADMIN_PASSWORD
-        },
-        realm: process.env.KEYCLOAK_REALM,
-      });
-    }
-    const pg_user = await User.create({
-      kc_id: kc_user.id,
-      username: "admin",
-      email: process.env.IN_SYLVA_ADMIN_USERNAME,
-      password: process.env.IN_SYLVA_ADMIN_PASSWORD
-    });
-    await RoleUser.create({
-      role_id: 1,
-      kc_id: kc_user.id
-    });
-    return { user: pg_user, status: 201 };
-  },
+  return newUser;
+}
 
-  // GET Fetch all users and their group and role
-  async usersWithGroupAndRole() {
-    const usersWithGroupsAndRole = await db.raw(
-        `select DISTINCT u.id, u.kc_id, u.username, u.email, 
-          g.name as groupName, g.description as groupDescription, r.name as roleName, r.description as roleDescription  from users u
-          inner join roles_users ru on u.kc_id = ru.kc_id
-          inner join roles r on ru.role_id = r.id
-          left join group_users gu on u.id = gu.user_id
-          left join groups g on g.id = gu.group_id`);
-    return usersWithGroupsAndRole.rows;
-  },
+async function deleteUser(kc_id) {
+  if (!kc_id) {
+    throw Error("The request body is empty!");
+  }
 
-  // GET Fetch a user and their group and role
-  async userWithGroupAndRole(ctx) {
-    if (!ctx || !ctx.id) {
-      const error = new Error("Required parameters are missing.");
-      error.status = 400;
-      throw error;
-    }
-    const params = { userId: ctx.id };
-    const userWithGroupAndRole = await db.raw(
-        `select DISTINCT u.id, u.kc_id, u.username, u.email, g.id as groupId,
-          g.name as groupName, g.description as groupDescription, r.name as roleName, r.id as roleId, r.description as roleDescription  from users u
-          inner join roles_users ru on u.kc_id = ru.kc_id
-          inner join roles r on ru.role_id = r.id
-          left join group_users gu on u.id = gu.user_id
-          left join groups g on g.id = gu.group_id
-          where u.kc_id = :userId`, params);
-    return userWithGroupAndRole.rows;
-  },
+  const user = await prisma.user.findFirst({
+    where: {
+      kc_id: kc_id,
+    },
+  });
 
-  // POST Email a user
-  async sendMail(ctx) {
-    if (!ctx || !ctx.subject || !ctx.message) {
-      const error = new Error("Required parameters are missing.");
-      error.status = 400;
-      throw error;
-    }
-    await mailService.send(process.env.IN_SYLVA_EMAIL_FROM, ctx.email, ctx.subject, "", ctx.message);
-    await botService.message(ctx.message);
-    return {message: "Mail sent."};
-  },
+  if (!user) {
+    throw Error("User not found");
+  }
 
-  // POST Reset a user password.
-  async resetPassword(ctx) {
-    if (!ctx || !ctx.email) {
-      const error = new Error("Required parameters are missing.");
-      error.status = 400;
-      throw error;
-    }
-    const t = await postgresSeq.transaction();
-    await auth();
-    const users = await keycloakAdmin.users.find({
-      email: ctx.email,
-      realm: process.env.KEYCLOAK_REALM,
-    });
-    if (!users || users.length === 0) {
-      const error = new Error("User account not found.");
-      error.status = 400;
-      throw error;
-    }
-    const user = users[0];
-    const hashedPassword = await generatePassword(10);
-    // Update user in insylva db.
-    const [updatedRowsCount, updatedRows] = await User.update({
-      password: hashedPassword,
-    }, {
-      where: {
-        kc_id: user.id,
-      },
-    });
-    if (!updatedRowsCount || updatedRowsCount <= 0) {
-      t.rollback();
-      const error = new Error("Reset password failed.");
-      error.status = 500;
-      throw error;
-    }
-    // Update user in keycloak db.
-    await keycloakAdmin.users.resetPassword({
-      id: user.id,
-      credential: {
-        temporary: false,
-        type: 'password',
-        value: password,
-      },
-      realm: process.env.KEYCLOAK_REALM,
-    });
-    await this.sendMail({...ctx, subject: "Password reset", message: `Your new password is ${password}`});
-    t.commit();
-    return {message: "Password reset successfully"};
-  },
+  const deleted = await prisma.user.delete({
+    where: {
+      kc_id: kc_id,
+    },
+  });
+  if (!deleted) {
+    throw Error("User not found!");
+  }
+  const kcDeleted = await deleteKeycloakUser({ kc_id: kc_id });
+  if (!kcDeleted) {
+    throw Error("Keycloak user not found!");
+  }
+  return deleted;
 }
 
 module.exports = {
-  create: UserService.create,
-  user: UserService.user,
-  users: UserService.users,
-  kcId: UserService.kcId,
-  update: UserService.update,
-  detail: UserService.detail,
-  delete: UserService.delete,
-  getAssignedUserByRole: UserService.getAssignedUserByRole,
-  createSystemUser: UserService.createSystemUser,
-  usersWithGroupAndRole: UserService.usersWithGroupAndRole,
-  userWithGroupAndRole: UserService.userWithGroupAndRole,
-  sendMail: UserService.sendMail,
-  resetPassword: UserService.resetPassword
+  getUsers,
+  getUser,
+  createUser,
+  deleteUser,
 };
diff --git a/app/middlewares/errorHandler.js b/app/middlewares/errorHandler.js
deleted file mode 100644
index a31ed06c7874d1bf578814a91a9a9ed0baaa2cad..0000000000000000000000000000000000000000
--- a/app/middlewares/errorHandler.js
+++ /dev/null
@@ -1,20 +0,0 @@
-const logger = require("../utils/logger");
-
-/*
- * Global error handler middleware
- *
- * - Catches and handles all errors thrown within services, handlers, and routes.
- * - Logs error details for debugging and monitoring.
- * - Ensures the application does not crash on unhandled errors.
- */
-const errorHandler = async (ctx, next) => {
-    try {
-        await next();
-    } catch (err) {
-        logger.error(err.message);
-        ctx.status = err.status || 500;
-        ctx.body = { error: err.message || "Internal Server Error" };
-    }
-};
-
-module.exports = errorHandler;
diff --git a/app/models/Group.js b/app/models/Group.js
deleted file mode 100644
index 00c3764a9fc91fb0b015eeaa42d7aef42db7cab7..0000000000000000000000000000000000000000
--- a/app/models/Group.js
+++ /dev/null
@@ -1,80 +0,0 @@
-'use strict'
-
-const { postgresSeq } = require('../config/db')
-const Sequelize = require('sequelize')
-const { Policy } = require('./Policy')
-const { User } = require('./User')
-
-class Group extends Sequelize.Model { }
-class GroupsPolicy extends Sequelize.Model { }
-class GroupUser extends Sequelize.Model { }
-
-Group.init({
-    name: { type: Sequelize.STRING, allowNull: false },
-    description: { type: Sequelize.TEXT, allowNull: true },
-    user_id: {
-        type: Sequelize.INTEGER,
-        allowNull: false,
-        references: {
-            model: User,
-            key: "id",
-            deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE,
-        }
-    },
-}, {
-    underscored: true,
-    sequelize: postgresSeq,
-    modelName: "groups"
-})
-
-GroupsPolicy.init({
-    group_id: {
-        type: Sequelize.INTEGER, allowNull: false,
-        references: {
-            model: Group,
-            key: "id",
-            deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE
-        },
-    },
-    policy_id: {
-        type: Sequelize.INTEGER, allowNull: false,
-        references: {
-            model: Policy,
-            key: "id",
-            deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE
-        },
-    }
-}, {
-    underscored: true,
-    sequelize: postgresSeq,
-    modelName: "groups_policies"
-})
-
-GroupUser.init({
-    group_id: {
-        type: Sequelize.INTEGER, allowNull: false, references: {
-            model: Group,
-            key: "id",
-            deferrable: Sequelize.Deferrable.INITIALLY_DEFERRED
-        },
-
-    },
-    user_id: {
-        type: Sequelize.INTEGER, allowNull: false, references: {
-            model: User,
-            key: "id",
-            deferrable: Sequelize.Deferrable.INITIALLY_DEFERRED
-        },
-
-    }
-}, {
-    underscored: true,
-    sequelize: postgresSeq,
-    modelName: "group_users"
-})
-
-module.exports = {
-    Group,
-    GroupsPolicy,
-    GroupUser,
-}
diff --git a/app/models/Policy.js b/app/models/Policy.js
deleted file mode 100644
index 7b2a923a6adc6a84b42e4f2a87f8884cd47d2504..0000000000000000000000000000000000000000
--- a/app/models/Policy.js
+++ /dev/null
@@ -1,97 +0,0 @@
-"use strict";
-
-const { postgresSeq } = require("../config/db");
-const Sequelize = require("sequelize");
-const { StdField } = require("./StdField");
-const { Source } = require("./Source");
-const { User } = require('./User')
-class Policy extends Sequelize.Model { }
-class PolicyField extends Sequelize.Model { }
-class PolicySource extends Sequelize.Model { }
-
-Policy.init(
-  {
-    name: { type: Sequelize.STRING, allowNull: false },
-    is_default: {
-      type: Sequelize.BOOLEAN,
-      allowNull: false,
-      defaultValue: false,
-    },
-    user_id: {
-      type: Sequelize.INTEGER,
-      allowNull: false,
-      references: {
-        model: User,
-        key: "id",
-        deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE,
-      }
-    },
-  },
-  {
-    underscored: true,
-    sequelize: postgresSeq,
-    modelName: "policies"
-  }
-)
-
-PolicyField.init(
-  {
-    policy_id: {
-      type: Sequelize.INTEGER,
-      allowNull: false,
-      references: {
-        model: Policy,
-        key: "id",
-        deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE,
-      },
-      unique: "policy_field_policy_id_fkey"
-    },
-    std_field_id: {
-      type: Sequelize.INTEGER,
-      allowNull: false,
-      references: {
-        model: StdField,
-        key: "id",
-        deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE,
-      },
-      unique: "std_fields_id_fkkey"
-    },
-  },
-  {
-    underscored: true,
-    sequelize: postgresSeq,
-    modelName: "policy_fields",
-  })
-
-PolicySource.init({
-  policy_id: {
-    type: Sequelize.INTEGER,
-    allowNull: false,
-    references: {
-      model: Policy,
-      key: "id",
-      deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE,
-    },
-    unique: "policy_field_policy_id_fkey"
-  },
-  source_id: {
-    type: Sequelize.INTEGER, allowNull: false,
-    references: {
-      model: Source,
-      key: 'id',
-      deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE
-    },
-    unique: "policy_source_source_id_fkkey"
-  }
-},
-  {
-    underscored: true,
-    sequelize: postgresSeq,
-    modelName: "policy_sources",
-})
-
-module.exports = {
-  Policy,
-  PolicyField,
-  PolicySource
-};
diff --git a/app/models/Role.js b/app/models/Role.js
deleted file mode 100644
index 0c2a95ed884215b58dcfe081c2e3b1a9f2087e69..0000000000000000000000000000000000000000
--- a/app/models/Role.js
+++ /dev/null
@@ -1,47 +0,0 @@
-'use strict'
-
-const { postgresSeq } = require('../config/db')
-const Sequelize = require('sequelize')
-const { User } = require('./User')
-
-class Role extends Sequelize.Model { }
-class RoleUser extends Sequelize.Model { }
-
-Role.init({
-    name: { type: Sequelize.STRING, allowNull: false },
-    description: { type: Sequelize.STRING, allowNull: false },
-}, {
-    underscored: true,
-    sequelize: postgresSeq,
-    modelName: "roles"
-})
-
-RoleUser.init({
-    role_id: {
-        type: Sequelize.INTEGER, allowNull: false,
-        references: {
-            model: Role,
-            key: 'id',
-            deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE
-        },
-        unique: false
-    },
-    kc_id: {
-        type: Sequelize.STRING, allowNull: false,
-        references: {
-            model: User,
-            key: 'kc_id',
-            deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE
-        },
-        unique: false
-    }
-}, {
-    underscored: true,
-    sequelize: postgresSeq,
-    modelName: "roles_users"
-})
-
-module.exports = {
-    Role,
-    RoleUser
-}
diff --git a/app/models/Source.js b/app/models/Source.js
deleted file mode 100644
index 615afa8342cc71681c623fb19b35eabb268172d9..0000000000000000000000000000000000000000
--- a/app/models/Source.js
+++ /dev/null
@@ -1,78 +0,0 @@
-'use strict'
-
-const { postgresSeq } = require('../config/db')
-const Sequelize = require('sequelize')
-const { User } = require('./User')
-
-class Source extends Sequelize.Model { }
-
-Source.init({
-    name: { type: Sequelize.TEXT, allowNull: true },
-    description: { type: Sequelize.TEXT, allowNull: true },
-}, {
-    underscored: true,
-    sequelize: postgresSeq,
-    modelName: "sources"
-})
-
-class SourceIndices extends Sequelize.Model { }
-class SourceSharing extends Sequelize.Model { }
-
-SourceIndices.init({
-    source_id: {
-        type: Sequelize.INTEGER, allowNull: false,
-        references: {
-            model: Source,
-            key: 'id',
-            deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE
-        },
-        unique: false
-    },
-    index_id: {
-        type: Sequelize.STRING, allowNull: false
-    },
-    mng_id: {
-        type: Sequelize.STRING, allowNull: false
-    },
-    is_send: {
-        type: Sequelize.BOOLEAN, allowNull: false
-    }
-}, {
-    underscored: true,
-    sequelize: postgresSeq,
-    modelName: "sources_indices"
-})
-
-SourceSharing.init({
-    source_id: {
-        type: Sequelize.INTEGER, allowNull: false,
-        references: {
-            model: Source,
-            key: 'id',
-            deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE
-        },
-        unique: false
-    },
-    user_id: {
-        type: Sequelize.INTEGER, allowNull: false, references: {
-            model: User,
-            key: 'id',
-            deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE
-        },
-        unique: false
-    }
-}, {
-    underscored: true,
-    sequelize: postgresSeq,
-    modelName: "sources_indices"
-})
-
-SourceIndices.belongsTo(Source, {
-    foreignKey: "sources_indices_source_id_fkey"
-})
-
-module.exports = {
-    Source,
-    SourceIndices,
-    SourceSharing
-}
\ No newline at end of file
diff --git a/app/models/StdField.js b/app/models/StdField.js
deleted file mode 100644
index 5ae463c13d4bfeaff48edc1f8494e7ba5d9b87ae..0000000000000000000000000000000000000000
--- a/app/models/StdField.js
+++ /dev/null
@@ -1,34 +0,0 @@
-'use strict'
-
-const { postgresSeq } = require('../config/db')
-const Sequelize = require('sequelize')
-
-class StdField extends Sequelize.Model { }
-
-StdField.init({
-    std_field_id: {
-        type: Sequelize.INTEGER, allowNull: true,
-        references: {
-            model: StdField,
-            key: 'id',
-            deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE
-        }
-    },
-    category: { type: Sequelize.TEXT, allowNull: true },
-    field_name: { type: Sequelize.TEXT, allowNull: true },
-    definition_and_comment: { type: Sequelize.TEXT, allowNull: true },
-    obligation_or_condition: { type: Sequelize.TEXT, allowNull: true },
-    cardinality: { type: Sequelize.TEXT, allowNull: true },
-    field_type: { type: Sequelize.TEXT, allowNull: true },
-    values: { type: Sequelize.TEXT, allowNull: true },
-    ispublic: { type: Sequelize.BOOLEAN, allowNull: true, defaultValue: false },
-    isoptional: { type: Sequelize.BOOLEAN, allowNull: true, defaultValue: false },
-}, {
-    underscored: true,
-    sequelize: postgresSeq,
-    modelName: "std_fields"
-})
-
-module.exports = {
-    StdField
-}
diff --git a/app/models/User.js b/app/models/User.js
deleted file mode 100644
index 14f18e329d7f5afe0a5620f4f9e250a3a9a21ad5..0000000000000000000000000000000000000000
--- a/app/models/User.js
+++ /dev/null
@@ -1,37 +0,0 @@
-'use strict'
-
-const { postgresSeq } = require('../config/db')
-const Sequelize = require('sequelize')
-const bcrypt = require('bcrypt')
-class User extends Sequelize.Model { }
-
-User.init({
-    kc_id: { type: Sequelize.STRING, allowNull: true, unique: 'compositeIndex' },
-    username: { type: Sequelize.STRING, allowNull: false, unique: 'compositeIndex' },
-    name: { type: Sequelize.STRING, allowNull: true },
-    surname: { type: Sequelize.STRING, allowNull: true },
-    email: {
-        type: Sequelize.STRING, allowNull: false, validate: {
-            isEmail: true
-        }
-    },
-    password: { type: Sequelize.STRING, allowNull: false }
-}, {
-    underscored: true,
-    sequelize: postgresSeq,
-    modelName: 'user',
-    instanceMethods: {
-        validPassword: function (password) {
-            return bcrypt.compareSync(password, this.password);
-        }
-    }
-})
-
-User.beforeCreate(async (user, options) => {
-    const salt = bcrypt.genSaltSync()
-    user.password = bcrypt.hashSync(user.password, salt)
-})
-
-module.exports = {
-    User
-}
diff --git a/app/models/UserFieldsDisplaySettings.js b/app/models/UserFieldsDisplaySettings.js
deleted file mode 100644
index 98b7ccbcf1f40bfe21cdcfad5839109a6aa55f26..0000000000000000000000000000000000000000
--- a/app/models/UserFieldsDisplaySettings.js
+++ /dev/null
@@ -1,48 +0,0 @@
-'use strict'
-
-const { Model, DataTypes, Deferrable} = require('sequelize');
-const { postgresSeq } = require('../config/db');
-const { User } = require('./User');
-const {StdField} = require("./StdField");
-
-class UserFieldsDisplaySettings extends Model { }
-
-UserFieldsDisplaySettings.init({
-    user_id: {
-        type: DataTypes.INTEGER,
-        allowNull: false,
-        unique: true,
-        references: {
-            model: User,
-            key: "id",
-            deferrable: Deferrable.INITIALLY_IMMEDIATE,
-        }
-    },
-    std_fields_ids: {
-        type: DataTypes.ARRAY(DataTypes.INTEGER),
-        allowNull: false,
-        references: {
-            model: StdField,
-            key: 'id',
-            deferrable: Deferrable.INITIALLY_IMMEDIATE
-        },
-    }
-}, {
-    underscored: true,
-    sequelize: postgresSeq,
-    modelName: "user_fields_display_settings"
-});
-
-// Verify if all standard fields exists in database
-UserFieldsDisplaySettings.validateStdFieldIds = async (stdFieldIds) => {
-    // Count the number of existing IDs in std_fields
-    const validIds = await StdField.count({
-        where: { id: stdFieldIds },
-    });
-    // Check if it matches the length of stdFieldIds
-    return validIds === stdFieldIds.length;
-};
-
-module.exports = {
-    UserFieldsDisplaySettings,
-};
diff --git a/app/models/UserHistory.js b/app/models/UserHistory.js
deleted file mode 100644
index eb4e685b4906e91e361dc27ee728e222f2862367..0000000000000000000000000000000000000000
--- a/app/models/UserHistory.js
+++ /dev/null
@@ -1,30 +0,0 @@
-'use strict'
-
-const { postgresSeq } = require('../config/db')
-const Sequelize = require('sequelize')
-const { User } = require('./User')
-
-class SearchHistory extends Sequelize.Model { }
-
-SearchHistory.init({
-    kc_id: {
-        type: Sequelize.INTEGER, allowNull: false,
-        references: {
-            model: User,
-            key: 'id',
-            deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE
-        }
-    },
-    query: { type: Sequelize.TEXT, allowNull: false },
-    name: { type: Sequelize.STRING, allowNull: false },
-    ui_structure: { type: Sequelize.TEXT, allowNull: false },
-    description: { type: Sequelize.TEXT, allowNull: false },
-}, {
-    underscored: true,
-    sequelize: postgresSeq,
-    modelName: "user_search_his"
-})
-
-module.exports = {
-    SearchHistory
-}
diff --git a/app/models/UserRequest.js b/app/models/UserRequest.js
deleted file mode 100644
index 4f555153b45295cf501e95f2b73c13ec70d6c1e3..0000000000000000000000000000000000000000
--- a/app/models/UserRequest.js
+++ /dev/null
@@ -1,33 +0,0 @@
-'use strict'
-
-const { postgresSeq } = require('../config/db')
-const Sequelize = require('sequelize')
-const { User } = require('./User')
-
-class UserRequest extends Sequelize.Model { }
-
-UserRequest.init({
-    user_id: {
-        type: Sequelize.INTEGER,
-        allowNull: false,
-        references: {
-            model: User,
-            key: "id",
-            deferrable: Sequelize.Deferrable.INITIALLY_IMMEDIATE,
-        }
-    },
-    request_message: { type: Sequelize.TEXT, allowNull: false },
-    is_processed: {
-        type: Sequelize.BOOLEAN,
-        allowNull: false,
-        defaultValue: false,
-    },
-}, {
-    underscored: true,
-    sequelize: postgresSeq,
-    modelName: "user_requests"
-})
-
-module.exports = {
-    UserRequest
-}
diff --git a/app/utils/cast.js b/app/utils/cast.js
new file mode 100644
index 0000000000000000000000000000000000000000..d5e76dbb7d57ab397a916a4f1b6daf0143b1ad43
--- /dev/null
+++ b/app/utils/cast.js
@@ -0,0 +1,18 @@
+function isBooleanString(value) {
+  if (typeof value !== "string") {
+    return false;
+  }
+  return value.toLowerCase() === "true" || value.toLowerCase() === "false";
+}
+
+function castStringToBoolean(value) {
+  if (isBooleanString(value)) {
+    return value.toLowerCase() === "true";
+  }
+  return value;
+}
+
+module.exports = {
+  isBooleanString,
+  castStringToBoolean,
+};
diff --git a/app/utils/errorHandler.js b/app/utils/errorHandler.js
new file mode 100644
index 0000000000000000000000000000000000000000..a071ce061061d2b41396737692c0fd028e645e8e
--- /dev/null
+++ b/app/utils/errorHandler.js
@@ -0,0 +1,31 @@
+const util = require("util");
+const logger = require("../utils/format");
+
+async function handleInternalError(err, ctx) {
+  const error = JSON.stringify(
+    util.inspect(err, { compact: false, depth: 1, breakLength: 80 })
+  );
+  ctx.body = {
+    error: "Internal server error",
+    statusCode: 500,
+    message: err.message,
+  };
+  ctx.status = 500;
+  logger.error(error);
+}
+
+async function handleMissingParameters(missingParameters, ctx) {
+  ctx.status = 400;
+  ctx.body = {
+    error: "Bad request",
+    statusCode: 400,
+    message: `The following parameters are missing: ${missingParameters.join(
+      ", "
+    )}`,
+  };
+}
+
+module.exports = {
+  handleInternalError,
+  handleMissingParameters,
+};
diff --git a/app/utils/logger.js b/app/utils/format.js
similarity index 90%
rename from app/utils/logger.js
rename to app/utils/format.js
index 9d10265de3c0804835c51c6e2bec19c2a53d582d..6843d08a8e4701f4972bf41ad1e9164cc42115db 100644
--- a/app/utils/logger.js
+++ b/app/utils/format.js
@@ -4,6 +4,7 @@ const { createLogger, format, transports } = require('winston');
 const { combine, timestamp, printf, colorize, splat, label } = format;
 const path = require('path');
 
+
 const mFormat = printf((info) => {
     if (info.meta && info.meta instanceof Error) {
         return `${info.timestamp} ${info.level} ${info.message} : ${info.meta.stack}`;
@@ -11,11 +12,12 @@ const mFormat = printf((info) => {
     return `${info.timestamp} ${info.level} [${info.label}]: ${info.message}`;
 });
 
+const LOG_LEVEL = process.env.LOGGER_LEVEL || 'debug';
 const logger = createLogger({
     transports: [
         new (transports.Console)(
             {
-                level: process.env.LOG_LEVEL || 'debug',
+                level: LOG_LEVEL,
                 format: combine(
                     label({ label: path.basename(process.mainModule.filename) }),
                     colorize(),
@@ -27,5 +29,7 @@ const logger = createLogger({
         )
     ]
 });
-
 module.exports = logger;
+
+
+
diff --git a/db.js b/db.js
deleted file mode 100644
index 076fcbebb32089279dee2816170876dc39da8789..0000000000000000000000000000000000000000
--- a/db.js
+++ /dev/null
@@ -1,6 +0,0 @@
-'use strict'
-
-const { configPg } = require('./app/config/db')
-const knex = require('knex')
-
-module.exports = knex(configPg)
\ No newline at end of file
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000000000000000000000000000000000000..88c8b14a18f48de32f5d4e6da75c1ea62f44ce8f
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,14 @@
+services:
+  postgres:
+    image: registry.forgemia.inra.fr/in-sylva-development/in-sylva.postgres-postgis:1.0.0
+    ports:
+      - "5432:5432"
+    environment:
+      POSTGRES_USER: postgres
+      POSTGRES_PASSWORD: postgres
+      POSTGRES_DB: postgres
+    volumes:
+      - data:/var/lib/postgresql/data
+
+volumes:
+  data:
diff --git a/entrypoint.sh b/entrypoint.sh
new file mode 100755
index 0000000000000000000000000000000000000000..19def7c2b77a0c9319de9ceda59f39101dca33ce
--- /dev/null
+++ b/entrypoint.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+echo -n "Generating Prisma client... "
+yarn prisma generate
+echo "OK"
+
+echo -n "Running migrations... "
+yarn prisma migrate deploy
+echo "OK"
+
+echo -n "Seeding database... "
+yarn prisma db seed
+echo "OK"
+
+exec "$@"
diff --git a/gitlab-ci.yml b/gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..485dc39be8c4e4cf07c072ecef46cc3fc9bd0a94
--- /dev/null
+++ b/gitlab-ci.yml
@@ -0,0 +1,25 @@
+stages:
+  - test
+  - build
+
+test:
+  stage: test
+  image: node:20.16.0
+  script:
+    - npm install
+    - npm test
+
+build:
+  stage: build
+  image: docker:latest
+  services:
+    - docker:dind
+  script:
+    - docker build -t in-sylva/gatekeeper .
+    - version=$(jq -r .version package.json)
+    - docker tag in-sylva/gatekeeper in-sylva/gatekeeper:$version
+    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
+    - docker push in-sylva/gatekeeper:$version
+  only:
+    - master
+  when: manual
diff --git a/index.js b/index.js
index 2a67bf7862adb7a7abb093496f577a38b2d8cc66..b8a0587eeb482ae59dc3a2576fbff0ad3d8e6c5a 100644
--- a/index.js
+++ b/index.js
@@ -1,22 +1,10 @@
-'use strict'
+"use strict";
 
-const dotenv = require('dotenv')
+require("module-alias/register");
 
-if (process.env.NODE_ENV === 'development') {
-    dotenv.config({ silent: true })
+const dotenv = require("dotenv");
+if (process.env.NODE_ENV === "development") {
+  dotenv.config({ silent: true });
 }
 
-const processType = process.env.PROCESS_TYPE
-
-switch (processType) {
-    case 'web':
-        require('./web')
-        break
-    case 'script':
-        require('./migrate')
-        break
-    default:
-        throw new Error(
-            `Invalid process type: ${processType}. It should be one of: 'web', 'script'.`
-        )
-}
\ No newline at end of file
+require("./web");
diff --git a/init-keycloak.js b/init-keycloak.js
deleted file mode 100644
index c0b75b7532be81ec8af441062797a249eb797b2b..0000000000000000000000000000000000000000
--- a/init-keycloak.js
+++ /dev/null
@@ -1,13 +0,0 @@
-'use strict'
-
-const KeycloakConnect = require('@in-sylva/keycloak-koa-connect').default
-const config = require('./keycloak.js')
-
-// If this option is used, it is legal to include the value of jwt in the body
-const bodyStore = require('@in-sylva/keycloak-koa-connect/stores/body-store').default
-// If this option is used, it is also legal to pass a token at http://a.com?jwt=token
-const queryStore = require('@in-sylva/keycloak-koa-connect/stores/query-store').default
-
-const keycloak = new KeycloakConnect({ store: [queryStore, bodyStore]}, config)
-
-module.exports = { keycloak }
diff --git a/jest.config.js b/jest.config.js
new file mode 100644
index 0000000000000000000000000000000000000000..1cd6c68649306163c97bf1d4bd07fa7f4bf1a521
--- /dev/null
+++ b/jest.config.js
@@ -0,0 +1,8 @@
+module.exports = {
+  moduleNameMapper: {
+    "^@/(.*)$": "<rootDir>/$1",
+  },
+  clearMocks: true,
+  testEnvironment: "node",
+  setupFilesAfterEnv: ["<rootDir>/jest.setup.js"],
+};
diff --git a/jest.setup.js b/jest.setup.js
new file mode 100644
index 0000000000000000000000000000000000000000..6ffe91e15b6fc06c59d2d4d147153fd1b4b01fe6
--- /dev/null
+++ b/jest.setup.js
@@ -0,0 +1,17 @@
+jest.mock("@/app/utils/format", () => ({
+  info: jest.fn(),
+  error: jest.fn(),
+  debug: jest.fn(),
+}));
+
+jest.mock("@/app/dal/elasticService", () => ({
+  prepareForBulk: jest.fn(),
+  bulk: jest.fn(),
+  countByIndex: jest.fn(),
+  search: jest.fn(),
+}));
+
+jest.mock("@/app/dal/mongoService", () => ({
+  addSourceToMongoDB: jest.fn(),
+  removeSourceFromMongoDB: jest.fn(),
+}));
diff --git a/jsconfig.json b/jsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..f126305fa59e4ca0750f21195feb20282501c09b
--- /dev/null
+++ b/jsconfig.json
@@ -0,0 +1,9 @@
+{
+  "compilerOptions": {
+    "baseUrl": "./", // Base directory for resolving non-relative module imports
+    "paths": {
+      "@/*": ["./*"] // Alias mapping
+    }
+  },
+  "exclude": ["node_modules"]
+}
diff --git a/keycloak.js b/keycloak.js
deleted file mode 100644
index 2724de971a1a1053c4271d929b1eb97f70379f29..0000000000000000000000000000000000000000
--- a/keycloak.js
+++ /dev/null
@@ -1,15 +0,0 @@
-module.exports = {
-    'realm': process.env.KEYCLOAK_REALM,
-    'auth-server-url': process.env.KEYCLOAK_SERVER_URL,
-    "ssl-required": "none",
-    'resource': process.env.KEYCLOAK_CLIENT_ID,
-    "verify-token-audience": true,
-    "credentials": {
-        "secret": process.env.KEYCLOAK_CREDENTIALS_SECRET
-    },
-    "confidential-port": 0,
-    "policy-enforcer": {},
-    'bearer-only':true,
-    'use-resource-role-mappings': true,
-    'realm-public-key': `${process.env.KEYCLOAK_SERVER_PUBLIC_KEY}`
-}
diff --git a/knexfile.js b/knexfile.js
deleted file mode 100644
index 5491c516f1ee27ede3dbde09d38bb0e9f1280098..0000000000000000000000000000000000000000
--- a/knexfile.js
+++ /dev/null
@@ -1,9 +0,0 @@
-'use strict'
-
-const dbConfig = require('./config/db')
-
-module.exports = {
-    development: dbConfig,
-    staging: dbConfig,
-    production: dbConfig
-}
diff --git a/migrate.js b/migrate.js
deleted file mode 100644
index b71cce0c073a652270a539bfb142b367c45b1e99..0000000000000000000000000000000000000000
--- a/migrate.js
+++ /dev/null
@@ -1,8 +0,0 @@
-const { exec } = require('child_process')
-const logger = require('winston')
-
-exec('./node_modules/.bin/knex migrate:latest',
-    (err, stdout, stderr) => {
-        if (err) throw err
-        logger.info(stdout)
-    })
diff --git a/package.json b/package.json
index 8287ebeab8802ee48e4b6b6fc640276a63968acb..715c2ca9e6738453df92c9534d71b96ec4fe61f7 100644
--- a/package.json
+++ b/package.json
@@ -1,17 +1,19 @@
 {
   "name": "in-sylva.gatekeeper",
-  "version": "1.0.0",
+  "version": "1.1.0",
   "description": "",
   "main": "index.js",
   "scripts": {
     "test": "jest --setupFiles dotenv/config",
-    "db-start": "docker run --rm --name inra-paca-local -e POSTGRES_PASSWORD=root -e POSTGRES_USER=root -e POSTGRES_DB=test-inra-paca-db -p 3001:5432 -d postgres:10",
-    "db-stop": "docker rm -f inra-paca-local || true",
-    "db-migrate": "./node_modules/.bin/knex migrate:latest",
     "start": "node index.js",
     "start:dev": "NODE_ENV=development PROCESS_TYPE=web  ./node_modules/.bin/nodemon ./index.js",
-    "start:prod": "NODE_ENV=production PROCESS_TYPE=web  ./node_modules/.bin/nodemon ./index.js",
-    "docker-build": "../scripts/build \"user\""
+    "start:prod": "NODE_ENV=production PROCESS_TYPE=web  ./node_modules/.bin/nodemon ./index.js"
+  },
+  "_moduleAliases": {
+    "@": "."
+  },
+  "prisma": {
+    "seed": "node prisma/seed.js"
   },
   "repository": {
     "type": "git",
@@ -20,17 +22,15 @@
   "author": "IN-SYLVA DEVELOPMENT TEAM",
   "license": "ISC",
   "dependencies": {
+    "@elastic/elasticsearch": "^8.17.0",
     "@hapi/joi": "17.1.1",
-    "@in-sylva/common": "git+ssh://git@forgemia.inra.fr:in-sylva-development/in-sylva.common.git",
-    "@in-sylva/keycloak-koa-connect": "git+ssh://git@forgemia.inra.fr:in-sylva-development/keycloak-koa-connect.git",
-    "@pixelygroup/keycloak-koa-connect": "^0.9.5",
+    "@prisma/client": "^6.0.1",
     "array.prototype.flatmap": "1.2.4",
     "bcrypt": "^5.1.0",
     "bluebird": "3.7.2",
+    "consul": "^0.37.0",
+    "jest-mock-extended": "^4.0.0-beta1",
     "keycloak-admin": "1.14.8",
-    "keycloak-connect": "12.0.3",
-    "keycloak-koa-connect": "^1.0.5",
-    "knex": "0.21.18",
     "koa": "2.13.1",
     "koa-bodyparser": "4.3.0",
     "koa-compose": "4.1.0",
@@ -38,22 +38,24 @@
     "koa-router": "10.0.0",
     "koa-session": "6.1.0",
     "koa2-cors": "2.0.6",
+    "module-alias": "^2.2.3",
+    "mongodb": "^6.12.0",
     "nodemon": "2.0.7",
-    "openid-client": "4.4.0",
     "pg": "8.5.1",
     "pg-hstore": "^2.3.3",
     "request": "^2.88.0",
-    "sequelize": "^6.3.4",
     "winston": "3.3.3",
     "yarn": "1.22.10"
   },
   "devDependencies": {
     "dotenv": "8.2.0",
+    "dotenv-cli": "^7.4.4",
     "eslint": "^7.6.0",
     "eslint-config-prettier": "^6.11.0",
     "eslint-plugin-prettier": "^3.1.4",
     "jest": "26.6.3",
     "jscs": "^3.0.7",
-    "pretty-format": "^26.2.0"
+    "pretty-format": "^26.2.0",
+    "prisma": "^6.0.1"
   }
 }
diff --git a/prisma/client.js b/prisma/client.js
new file mode 100644
index 0000000000000000000000000000000000000000..6d75495245f14d1f45a180a47b08353b0b057a8e
--- /dev/null
+++ b/prisma/client.js
@@ -0,0 +1,5 @@
+const { PrismaClient } = require("@prisma/client");
+
+const prisma = new PrismaClient();
+
+module.exports = prisma;
diff --git a/prisma/migrations/20241211224745_0_init/migration.sql b/prisma/migrations/20241211224745_0_init/migration.sql
new file mode 100644
index 0000000000000000000000000000000000000000..dcc15e607a3a3020405ffdf724ab17e2472e85ae
--- /dev/null
+++ b/prisma/migrations/20241211224745_0_init/migration.sql
@@ -0,0 +1,186 @@
+-- CreateTable
+CREATE TABLE "users" (
+    "id" SERIAL NOT NULL,
+    "kc_id" TEXT NOT NULL,
+    "email" TEXT NOT NULL,
+
+    CONSTRAINT "users_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "search_history" (
+    "id" SERIAL NOT NULL,
+    "user_id" INTEGER NOT NULL,
+    "query" TEXT NOT NULL,
+    "name" TEXT NOT NULL,
+    "ui_structure" TEXT NOT NULL,
+    "description" TEXT NOT NULL,
+
+    CONSTRAINT "search_history_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "user_requests" (
+    "id" SERIAL NOT NULL,
+    "user_id" INTEGER NOT NULL,
+    "request_message" TEXT NOT NULL,
+    "is_processed" BOOLEAN NOT NULL DEFAULT false,
+
+    CONSTRAINT "user_requests_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "std_fields" (
+    "id" SERIAL NOT NULL,
+    "category" TEXT,
+    "field_name" TEXT,
+    "definition_and_comment" TEXT,
+    "obligation_or_condition" TEXT,
+    "cardinality" TEXT,
+    "field_type" TEXT,
+    "values" TEXT,
+    "ispublic" BOOLEAN NOT NULL DEFAULT false,
+    "isoptional" BOOLEAN NOT NULL DEFAULT false,
+
+    CONSTRAINT "std_fields_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "sources" (
+    "id" SERIAL NOT NULL,
+    "name" TEXT,
+    "description" TEXT,
+
+    CONSTRAINT "sources_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "source_indices" (
+    "id" SERIAL NOT NULL,
+    "source_id" INTEGER NOT NULL,
+    "index_id" TEXT NOT NULL,
+    "mng_id" TEXT NOT NULL,
+    "is_send" BOOLEAN NOT NULL,
+
+    CONSTRAINT "source_indices_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "roles" (
+    "id" SERIAL NOT NULL,
+    "name" TEXT NOT NULL,
+    "description" TEXT NOT NULL,
+
+    CONSTRAINT "roles_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "policies" (
+    "id" SERIAL NOT NULL,
+    "name" TEXT NOT NULL,
+    "is_default" BOOLEAN NOT NULL DEFAULT false,
+    "user_id" INTEGER NOT NULL,
+
+    CONSTRAINT "policies_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "groups" (
+    "id" SERIAL NOT NULL,
+    "name" TEXT NOT NULL,
+    "description" TEXT NOT NULL,
+    "admin_id" INTEGER NOT NULL,
+
+    CONSTRAINT "groups_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateTable
+CREATE TABLE "groups_users" (
+    "group_id" INTEGER NOT NULL,
+    "user_id" INTEGER NOT NULL,
+
+    CONSTRAINT "groups_users_pkey" PRIMARY KEY ("group_id","user_id")
+);
+
+-- CreateTable
+CREATE TABLE "groups_policies" (
+    "group_id" INTEGER NOT NULL,
+    "policy_id" INTEGER NOT NULL,
+
+    CONSTRAINT "groups_policies_pkey" PRIMARY KEY ("group_id","policy_id")
+);
+
+-- CreateTable
+CREATE TABLE "policies_fields" (
+    "policy_id" INTEGER NOT NULL,
+    "std_field_id" INTEGER NOT NULL,
+
+    CONSTRAINT "policies_fields_pkey" PRIMARY KEY ("policy_id","std_field_id")
+);
+
+-- CreateTable
+CREATE TABLE "policies_sources" (
+    "policy_id" INTEGER NOT NULL,
+    "source_id" INTEGER NOT NULL,
+
+    CONSTRAINT "policies_sources_pkey" PRIMARY KEY ("policy_id","source_id")
+);
+
+-- CreateTable
+CREATE TABLE "roles_users" (
+    "role_id" INTEGER NOT NULL,
+    "user_id" INTEGER NOT NULL,
+
+    CONSTRAINT "roles_users_pkey" PRIMARY KEY ("role_id","user_id")
+);
+
+-- CreateIndex
+CREATE UNIQUE INDEX "users_kc_id_key" ON "users"("kc_id");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "users_email_key" ON "users"("email");
+
+-- AddForeignKey
+ALTER TABLE "search_history" ADD CONSTRAINT "search_history_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "user_requests" ADD CONSTRAINT "user_requests_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "source_indices" ADD CONSTRAINT "source_indices_source_id_fkey" FOREIGN KEY ("source_id") REFERENCES "sources"("id") ON DELETE CASCADE ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "policies" ADD CONSTRAINT "policies_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "groups" ADD CONSTRAINT "groups_admin_id_fkey" FOREIGN KEY ("admin_id") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "groups_users" ADD CONSTRAINT "groups_users_group_id_fkey" FOREIGN KEY ("group_id") REFERENCES "groups"("id") ON DELETE CASCADE ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "groups_users" ADD CONSTRAINT "groups_users_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "groups_policies" ADD CONSTRAINT "groups_policies_group_id_fkey" FOREIGN KEY ("group_id") REFERENCES "groups"("id") ON DELETE CASCADE ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "groups_policies" ADD CONSTRAINT "groups_policies_policy_id_fkey" FOREIGN KEY ("policy_id") REFERENCES "policies"("id") ON DELETE CASCADE ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "policies_fields" ADD CONSTRAINT "policies_fields_policy_id_fkey" FOREIGN KEY ("policy_id") REFERENCES "policies"("id") ON DELETE CASCADE ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "policies_fields" ADD CONSTRAINT "policies_fields_std_field_id_fkey" FOREIGN KEY ("std_field_id") REFERENCES "std_fields"("id") ON DELETE CASCADE ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "policies_sources" ADD CONSTRAINT "policies_sources_policy_id_fkey" FOREIGN KEY ("policy_id") REFERENCES "policies"("id") ON DELETE CASCADE ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "policies_sources" ADD CONSTRAINT "policies_sources_source_id_fkey" FOREIGN KEY ("source_id") REFERENCES "sources"("id") ON DELETE CASCADE ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "roles_users" ADD CONSTRAINT "roles_users_role_id_fkey" FOREIGN KEY ("role_id") REFERENCES "roles"("id") ON DELETE CASCADE ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "roles_users" ADD CONSTRAINT "roles_users_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
diff --git a/prisma/migrations/20241211225353_1_cascade_delete_group_when_admin_deleted/migration.sql b/prisma/migrations/20241211225353_1_cascade_delete_group_when_admin_deleted/migration.sql
new file mode 100644
index 0000000000000000000000000000000000000000..a3aeb9442841a35d8d732d258dbbbbfa978f7a2d
--- /dev/null
+++ b/prisma/migrations/20241211225353_1_cascade_delete_group_when_admin_deleted/migration.sql
@@ -0,0 +1,5 @@
+-- DropForeignKey
+ALTER TABLE "groups" DROP CONSTRAINT "groups_admin_id_fkey";
+
+-- AddForeignKey
+ALTER TABLE "groups" ADD CONSTRAINT "groups_admin_id_fkey" FOREIGN KEY ("admin_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
diff --git a/prisma/migrations/20241211235543_2_cascade_delete/migration.sql b/prisma/migrations/20241211235543_2_cascade_delete/migration.sql
new file mode 100644
index 0000000000000000000000000000000000000000..bc87f49ad41b1729c14a33771a96c2adf68e341a
--- /dev/null
+++ b/prisma/migrations/20241211235543_2_cascade_delete/migration.sql
@@ -0,0 +1,17 @@
+-- DropForeignKey
+ALTER TABLE "policies" DROP CONSTRAINT "policies_user_id_fkey";
+
+-- DropForeignKey
+ALTER TABLE "search_history" DROP CONSTRAINT "search_history_user_id_fkey";
+
+-- DropForeignKey
+ALTER TABLE "user_requests" DROP CONSTRAINT "user_requests_user_id_fkey";
+
+-- AddForeignKey
+ALTER TABLE "search_history" ADD CONSTRAINT "search_history_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "user_requests" ADD CONSTRAINT "user_requests_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "policies" ADD CONSTRAINT "policies_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
diff --git a/prisma/migrations/20241212020153_3_std_field_unique_name/migration.sql b/prisma/migrations/20241212020153_3_std_field_unique_name/migration.sql
new file mode 100644
index 0000000000000000000000000000000000000000..cb831adec4d3b207b39cb24e37149aa032a92af7
--- /dev/null
+++ b/prisma/migrations/20241212020153_3_std_field_unique_name/migration.sql
@@ -0,0 +1,12 @@
+/*
+  Warnings:
+
+  - A unique constraint covering the columns `[field_name]` on the table `std_fields` will be added. If there are existing duplicate values, this will fail.
+  - Made the column `field_name` on table `std_fields` required. This step will fail if there are existing NULL values in that column.
+
+*/
+-- AlterTable
+ALTER TABLE "std_fields" ALTER COLUMN "field_name" SET NOT NULL;
+
+-- CreateIndex
+CREATE UNIQUE INDEX "std_fields_field_name_key" ON "std_fields"("field_name");
diff --git a/prisma/migrations/20241212233751_4_nullable_and_default_source_indices/migration.sql b/prisma/migrations/20241212233751_4_nullable_and_default_source_indices/migration.sql
new file mode 100644
index 0000000000000000000000000000000000000000..0e228aff49f7600c84214e62c7c601732c5b865c
--- /dev/null
+++ b/prisma/migrations/20241212233751_4_nullable_and_default_source_indices/migration.sql
@@ -0,0 +1,4 @@
+-- AlterTable
+ALTER TABLE "source_indices" ALTER COLUMN "index_id" DROP NOT NULL,
+ALTER COLUMN "mng_id" DROP NOT NULL,
+ALTER COLUMN "is_send" SET DEFAULT false;
diff --git a/prisma/migrations/20241212234126_5_source_providers/migration.sql b/prisma/migrations/20241212234126_5_source_providers/migration.sql
new file mode 100644
index 0000000000000000000000000000000000000000..c9ca428991a8f9f28f25f0edbf00f12d268cbd84
--- /dev/null
+++ b/prisma/migrations/20241212234126_5_source_providers/migration.sql
@@ -0,0 +1,13 @@
+-- CreateTable
+CREATE TABLE "sources_users" (
+    "source_id" INTEGER NOT NULL,
+    "user_id" INTEGER NOT NULL,
+
+    CONSTRAINT "sources_users_pkey" PRIMARY KEY ("source_id","user_id")
+);
+
+-- AddForeignKey
+ALTER TABLE "sources_users" ADD CONSTRAINT "sources_users_source_id_fkey" FOREIGN KEY ("source_id") REFERENCES "sources"("id") ON DELETE CASCADE ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "sources_users" ADD CONSTRAINT "sources_users_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
diff --git a/prisma/migrations/20241214231527_6_display_fields/migration.sql b/prisma/migrations/20241214231527_6_display_fields/migration.sql
new file mode 100644
index 0000000000000000000000000000000000000000..237f1d7ac550d0906269fd3cdd8497b1667c987d
--- /dev/null
+++ b/prisma/migrations/20241214231527_6_display_fields/migration.sql
@@ -0,0 +1,13 @@
+-- CreateTable
+CREATE TABLE "display_std_fields" (
+    "user_id" INTEGER NOT NULL,
+    "std_field_id" INTEGER NOT NULL,
+
+    CONSTRAINT "display_std_fields_pkey" PRIMARY KEY ("user_id","std_field_id")
+);
+
+-- AddForeignKey
+ALTER TABLE "display_std_fields" ADD CONSTRAINT "display_std_fields_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE CASCADE ON UPDATE CASCADE;
+
+-- AddForeignKey
+ALTER TABLE "display_std_fields" ADD CONSTRAINT "display_std_fields_std_field_id_fkey" FOREIGN KEY ("std_field_id") REFERENCES "std_fields"("id") ON DELETE CASCADE ON UPDATE CASCADE;
diff --git a/prisma/migrations/20250116142811_7_list_url_and_default_fields/migration.sql b/prisma/migrations/20250116142811_7_list_url_and_default_fields/migration.sql
new file mode 100644
index 0000000000000000000000000000000000000000..2de09fd4d37fd9f7ecc08edb6363d8ec6c22678d
--- /dev/null
+++ b/prisma/migrations/20250116142811_7_list_url_and_default_fields/migration.sql
@@ -0,0 +1,3 @@
+-- AlterTable
+ALTER TABLE "std_fields" ADD COLUMN     "default_display_fields" BOOLEAN NOT NULL DEFAULT false,
+ADD COLUMN     "list_url" TEXT;
diff --git a/prisma/migrations/migration_lock.toml b/prisma/migrations/migration_lock.toml
new file mode 100644
index 0000000000000000000000000000000000000000..648c57fd59d83581e928372c012c2073cc0a1158
--- /dev/null
+++ b/prisma/migrations/migration_lock.toml
@@ -0,0 +1,3 @@
+# Please do not edit this file manually
+# It should be added in your version-control system (e.g., Git)
+provider = "postgresql"
\ No newline at end of file
diff --git a/prisma/schema.prisma b/prisma/schema.prisma
new file mode 100644
index 0000000000000000000000000000000000000000..1f9fc9a415fef25cc23342983012f23d1be2e519
--- /dev/null
+++ b/prisma/schema.prisma
@@ -0,0 +1,200 @@
+generator client {
+  provider = "prisma-client-js"
+}
+
+datasource db {
+  provider = "postgresql"
+  url      = env("DATABASE_URL")
+}
+
+model User {
+  id              Int               @id @default(autoincrement())
+  kc_id           String            @unique
+  email           String            @unique
+  history         SearchHistory[]
+  requests        UserRequest[]
+  display_fields  DisplayStdField[]
+  policy_admin    Policy[]
+  source_provider SourceUser[]
+  group_admin     Group[]
+  groups          GroupUser[]
+  roles           RoleUser[]
+
+  @@map("users")
+}
+
+model SearchHistory {
+  id           Int    @id @default(autoincrement())
+  user_id      Int
+  user         User   @relation(fields: [user_id], references: [id], onDelete: Cascade)
+  query        String
+  name         String
+  ui_structure String
+  description  String
+
+  @@map("search_history")
+}
+
+model UserRequest {
+  id              Int     @id @default(autoincrement())
+  user_id         Int
+  user            User    @relation(fields: [user_id], references: [id], onDelete: Cascade)
+  request_message String
+  is_processed    Boolean @default(false)
+
+  @@map("user_requests")
+}
+
+model StdField {
+  id                      Int               @id @default(autoincrement())
+  field_name              String            @unique
+  category                String?
+  definition_and_comment  String?
+  obligation_or_condition String?
+  cardinality             String?
+  field_type              String?
+  values                  String?
+  ispublic                Boolean           @default(false)
+  isoptional              Boolean           @default(false)
+  list_url                String?
+  default_display_fields  Boolean           @default(false)
+  policies                PolicyStdField[]
+  display_fields          DisplayStdField[]
+
+  @@map("std_fields")
+}
+
+model Source {
+  id             Int             @id @default(autoincrement())
+  name           String?
+  description    String?
+  source_indices SourceIndices[]
+  providers      SourceUser[]
+  policies       PolicySource[]
+
+  @@map("sources")
+}
+
+model SourceIndices {
+  id        Int     @id @default(autoincrement())
+  source_id Int
+  source    Source  @relation(fields: [source_id], references: [id], onDelete: Cascade)
+  index_id  String?
+  mng_id    String?
+  is_send   Boolean @default(false)
+
+  @@map("source_indices")
+}
+
+model SourceUser {
+  source_id Int
+  user_id   Int
+
+  source Source @relation(fields: [source_id], references: [id], onDelete: Cascade)
+  user   User   @relation(fields: [user_id], references: [id], onDelete: Cascade)
+
+  @@id([source_id, user_id])
+  @@map("sources_users")
+}
+
+model Role {
+  id          Int    @id @default(autoincrement())
+  name        String
+  description String
+
+  users RoleUser[]
+
+  @@map("roles")
+}
+
+model Policy {
+  id         Int     @id @default(autoincrement())
+  name       String
+  is_default Boolean @default(false)
+  user_id    Int
+  user       User    @relation(fields: [user_id], references: [id], onDelete: Cascade)
+
+  std_fields PolicyStdField[]
+  sources    PolicySource[]
+  groups     GroupPolicy[]
+
+  @@map("policies")
+}
+
+model Group {
+  id          Int           @id @default(autoincrement())
+  name        String
+  description String
+  admin_id    Int
+  admin       User          @relation(fields: [admin_id], references: [id], onDelete: Cascade)
+  users       GroupUser[]
+  policies    GroupPolicy[]
+
+  @@map("groups")
+}
+
+model GroupUser {
+  group_id Int
+  user_id  Int
+
+  group Group @relation(fields: [group_id], references: [id], onDelete: Cascade)
+  user  User  @relation(fields: [user_id], references: [id], onDelete: Cascade)
+
+  @@id([group_id, user_id])
+  @@map("groups_users")
+}
+
+model GroupPolicy {
+  group_id  Int
+  policy_id Int
+
+  group  Group  @relation(fields: [group_id], references: [id], onDelete: Cascade)
+  policy Policy @relation(fields: [policy_id], references: [id], onDelete: Cascade)
+
+  @@id([group_id, policy_id])
+  @@map("groups_policies")
+}
+
+model PolicyStdField {
+  policy_id    Int
+  std_field_id Int
+
+  policy    Policy   @relation(fields: [policy_id], references: [id], onDelete: Cascade)
+  std_field StdField @relation(fields: [std_field_id], references: [id], onDelete: Cascade)
+
+  @@id([policy_id, std_field_id])
+  @@map("policies_fields")
+}
+
+model PolicySource {
+  policy_id Int
+  source_id Int
+
+  policy Policy @relation(fields: [policy_id], references: [id], onDelete: Cascade)
+  source Source @relation(fields: [source_id], references: [id], onDelete: Cascade)
+
+  @@id([policy_id, source_id])
+  @@map("policies_sources")
+}
+
+model RoleUser {
+  role_id Int
+  user_id Int
+
+  role Role @relation(fields: [role_id], references: [id], onDelete: Cascade)
+  user User @relation(fields: [user_id], references: [id], onDelete: Cascade)
+
+  @@id([role_id, user_id])
+  @@map("roles_users")
+}
+
+model DisplayStdField {
+  user_id      Int
+  std_field_id Int
+
+  user      User     @relation(fields: [user_id], references: [id], onDelete: Cascade)
+  std_field StdField @relation(fields: [std_field_id], references: [id], onDelete: Cascade)
+
+  @@id([user_id, std_field_id])
+  @@map("display_std_fields")
+}
diff --git a/prisma/seed.js b/prisma/seed.js
new file mode 100644
index 0000000000000000000000000000000000000000..3d9159e17d2cdc2e120c8979e9e653979c4c2196
--- /dev/null
+++ b/prisma/seed.js
@@ -0,0 +1,49 @@
+const { PrismaClient } = require("@prisma/client");
+const prisma = new PrismaClient();
+
+async function main() {
+  await prisma.role.deleteMany();
+  // Add default roles
+  await prisma.role.upsert({
+    where: {
+      id: 1,
+    },
+    create: {
+      id: 1,
+      name: "admin",
+      description: "Admin role",
+    },
+    update: {},
+  });
+  await prisma.role.upsert({
+    where: {
+      id: 2,
+    },
+    create: {
+      id: 2,
+      name: "source-manager",
+      description: "Source manager role",
+    },
+    update: {},
+  });
+  await prisma.role.upsert({
+    where: {
+      id: 3,
+    },
+    create: {
+      id: 3,
+      name: "policy-manager",
+      description: "Policy manager role",
+    },
+    update: {},
+  });
+}
+main()
+  .then(async () => {
+    await prisma.$disconnect();
+  })
+  .catch(async (e) => {
+    console.error(e);
+    await prisma.$disconnect();
+    process.exit(1);
+  });
diff --git a/scripts/build.sh b/scripts/build.sh
deleted file mode 100644
index 66884adbeb533b7c146f45963dad778b3ef4d80e..0000000000000000000000000000000000000000
--- a/scripts/build.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/usr/bin/env bash
-set -e
-
-app_name=$1
-
-image_name=rs-ms/$app_name
-current_version=$(docker images $image_name --format "{{.Tag}}" | head -2 | tail -1 | grep -o "[0-9]\+" || echo 0)
-next_version=$(( $current_version + 1))
-docker build -t $image_name:v$next_version -t $image_name:latest .
-
-kubectl delete pod -l app=$app_name
\ No newline at end of file
diff --git a/scripts/migrate.sh b/scripts/migrate.sh
deleted file mode 100644
index 571004cb586ae4e939313839cab8a1645777e3b1..0000000000000000000000000000000000000000
--- a/scripts/migrate.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/bash
-
-function get_pod () {
-  kubectl get pods -l app="$1" -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}' | head -1
-}
-
-product_pod_name=$(get_pod product)
-user_pod_name=$(get_pod user)
-
-for pod_name in $user_pod_name $product_pod_name; do
-  kubectl exec $pod_name npm run db-migrate
-done
-
-kubectl exec $product_pod_name npm run db-seed
diff --git a/scripts/up.sh b/scripts/up.sh
deleted file mode 100644
index 3b88979bdaa982d9face55748e59fc85b14db6c9..0000000000000000000000000000000000000000
--- a/scripts/up.sh
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/bash
-
-eval $(minikube docker-env)
-
-script_directory="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-
-for app in "user" "product" "gateway" "front-end"; do
-  echo "cding into: $script_directory/$app"
-  cd "$script_directory/../$app"
-  npm run docker-build
-  kubectl create -f ./k8s
-done
-
-docker-compose up -d
-
-echo 'waiting 30 seconds for postgresql to start...'
-sleep 30
-
-docker exec $(docker ps --format '{{.ID}}' -f name=trainingmicroservicesv3_db) psql -d test-products-db -c "CREATE DATABASE \"test-users-db\""
-
-$script_directory/migrate
diff --git a/scripts/util.sh b/scripts/util.sh
deleted file mode 100644
index 86d3520278aedbe839f1d8b5596cc99fc33a0a42..0000000000000000000000000000000000000000
--- a/scripts/util.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/bash
-
-pid1=$(lsof -t -i:4000)
-
-kill -9 $pid1
diff --git a/server.js b/server.js
index 62fdcb445d794d7468f1234e4ee2d357e1b7fe1f..50fec827da196917dbcc9c055702e4e29de472ad 100644
--- a/server.js
+++ b/server.js
@@ -1,39 +1,62 @@
-'use strict'
-
-const Koa = require('koa');
-const api = require('./app/api');
-const koaLogger = require('koa-logger');
-const cors = require('koa2-cors');
-const { keycloak } = require('./init-keycloak');
-const errorHandler = require('./app/middlewares/errorHandler');
-
-const responseTime = async (ctx, next) => {
-    const start = Date.now();
-    await next();
-    const ms = Date.now() - start;
-    ctx.set('X-Response-Time', `${ms}ms`);
+"use strict";
+
+const Koa = require("koa");
+const logger = require("@/app/utils/format");
+const api = require("./app/api");
+const koaLogger = require("koa-logger");
+const cors = require("koa2-cors");
+const { isAccessTokenValid } = require("./app/dal/authService");
+
+async function responseTime(ctx, next) {
+  const start = Date.now();
+  await next();
+  const ms = Date.now() - start;
+  ctx.set("X-Response-Time", `${ms}ms`);
 }
 
 const app = new Koa();
 
-app.use(errorHandler);
-
-const middlewares = keycloak.middleware({
-    logout: '/logout',
-    admin: '/',
-    protected: '/protected/resource'
-});
-middlewares.forEach(function (middleware) {
-    app.use(middleware);
-})
-
 app.proxy = false;
-app.use(cors({origin: '*'}));
-app.use(koaLogger());
-app.use(responseTime);
 
-// Register routes
-app.use(api.routes());
-app.use(api.allowedMethods());
+app
+  .use(
+    cors({
+      origin: "*",
+    })
+  )
+  .use(koaLogger())
+  .use(async (ctx, next) => {
+    if (ctx.path === "/healthcheck") {
+      ctx.status = 200;
+      ctx.body = { message: "Healthcheck OK" };
+      return;
+    }
+    const { authorization } = ctx.request.headers;
+    if (!authorization) {
+      ctx.status = 401;
+      ctx.body = {
+        message: "Bearer token is required in Authorization header",
+      };
+    } else {
+      const accessToken = authorization.split(" ")[1];
+      const isValid = await isAccessTokenValid(accessToken);
+      if (!isValid) {
+        ctx.status = 401;
+        ctx.body = {
+          message: "Invalid access token",
+        };
+      } else {
+        await next();
+      }
+    }
+  })
+  .use(api.routes())
+  .use(api.allowedMethods())
+  .use(responseTime);
+
+app.on("error", (err) => {
+  logger.error("Server error", { error: err.message });
+  throw err;
+});
 
 module.exports = app;
diff --git a/web.js b/web.js
index 2ed23e27beb96f00f81127637783379998dee7bd..f8502c99ec6d4efb97128ce59041ef80d1e00c13 100644
--- a/web.js
+++ b/web.js
@@ -1,17 +1,31 @@
-'use strict'
+"use strict";
 
-const { promisify } = require('util');
-const http = require('http');
-const app = require('./server');
-const config = require('./app/config/server');
-const logger = require("./app/utils/logger");
+const { promisify } = require("util");
+const http = require("http");
+const logger = require("@/app/utils/format");
+const app = require("@/server");
+require("@/app/config/server");
+require("@/app/config/postgres");
+require("@/app/config/elk");
+require("@/app/config/mongo");
 
-const server = http.createServer(app.callback());
-const serverListen = promisify(server.listen).bind(server);
+logger.level = process.env.LOGGER_LEVEL || "info";
 
-serverListen(config.port).then(() => {
-        logger.info(`in-sylva.gatekeeper service is up and running on localhost:${config.port}`);
-    }).catch((error) => {
-        logger.error(error);
-        process.exit(1);
+try {
+  const server = http.createServer(app.callback());
+  const serverListen = promisify(server.listen).bind(server);
+
+  serverListen(process.env.PORT)
+    .then(() => {
+      logger.info(
+        `in-sylva.gatekeeper service is up and running on localhost:${process.env.PORT}`
+      );
+    })
+    .catch((err) => {
+      logger.error(err);
+      process.exit(1);
     });
+} catch (error) {
+  console.error("Failed to start app:", error);
+  process.exit(1);
+}