diff --git a/src/main/resources/sql/10_runEverytime.sql b/src/dist/sql/10_runEverytime.sql similarity index 89% rename from src/main/resources/sql/10_runEverytime.sql rename to src/dist/sql/10_runEverytime.sql index 5c5c5d3..3e9e4f4 100644 --- a/src/main/resources/sql/10_runEverytime.sql +++ b/src/dist/sql/10_runEverytime.sql @@ -14,8 +14,9 @@ SET client_min_messages = ERROR; -- valid values are: 'UTF8', 'LATIN1', 'WIN1252' \encoding 'UTF8' +\ir drop_tables.sql -- create tables -\ir tables.sql +\ir create_tables.sql -- constraints and indexes diff --git a/src/main/resources/sql/1_reset-database.sql b/src/dist/sql/1_reset-database.sql similarity index 100% rename from src/main/resources/sql/1_reset-database.sql rename to src/dist/sql/1_reset-database.sql diff --git a/src/main/resources/sql/2_setup-database.sql b/src/dist/sql/2_setup-database.sql similarity index 100% rename from src/main/resources/sql/2_setup-database.sql rename to src/dist/sql/2_setup-database.sql diff --git a/src/main/resources/sql/tables.sql b/src/dist/sql/create_tables.sql similarity index 90% rename from src/main/resources/sql/tables.sql rename to src/dist/sql/create_tables.sql index 8434f7e..7b0122e 100644 --- a/src/main/resources/sql/tables.sql +++ b/src/dist/sql/create_tables.sql @@ -8,7 +8,7 @@ CREATE TYPE TRANSACTIONTYPE AS ENUM ( 'compensation' ); -CREATE TABLE IF NOT EXISTS "group" ( +CREATE TABLE "group" ( "id" VARCHAR(50), "name" VARCHAR(50) NOT NULL, "currency" VARCHAR(50) NOT NULL, @@ -17,7 +17,7 @@ CREATE TABLE IF NOT EXISTS "group" ( PRIMARY KEY ("id") ); -CREATE TABLE IF NOT EXISTS "person" ( +CREATE TABLE "person" ( "id" SERIAL, "name" VARCHAR(50) NOT NULL, "group" VARCHAR(50) REFERENCES "group" ON DELETE CASCADE, @@ -26,7 +26,7 @@ CREATE TABLE IF NOT EXISTS "person" ( PRIMARY KEY ("id") ); -CREATE TABLE IF NOT EXISTS "transaction" ( +CREATE TABLE "transaction" ( "id" SERIAL, "title" VARCHAR(50) NOT NULL, "amount" INTEGER NOT NULL, @@ -37,7 +37,7 @@ CREATE TABLE IF NOT EXISTS "transaction" ( PRIMARY KEY ("id") ); -CREATE TABLE IF NOT EXISTS "profiteer" ( +CREATE TABLE "profiteer" ( "person" INTEGER REFERENCES "person" ON DELETE CASCADE, "transaction" INTEGER REFERENCES "transaction", "factor" DECIMAL(5) NOT NULL, diff --git a/src/dist/sql/drop_tables.sql b/src/dist/sql/drop_tables.sql new file mode 100644 index 0000000..eb70d6c --- /dev/null +++ b/src/dist/sql/drop_tables.sql @@ -0,0 +1,8 @@ +-- Order is important +DROP TABLE "profiteer"; +DROP TABLE "transaction"; +DROP TABLE "person"; +DROP TABLE "group"; + +DROP TYPE CURRENCY; +DROP TYPE TRANSACTIONTYPE; diff --git a/src/dist/sql/setup-tables.sh b/src/dist/sql/setup-tables.sh new file mode 100755 index 0000000..c881435 --- /dev/null +++ b/src/dist/sql/setup-tables.sh @@ -0,0 +1,7 @@ +#!/bin/sh +set -e +set -x + +cd "$(dirname "$0")" + +psql -U tylr -f 10_runEverytime.sql diff --git a/src/main/java/io/teiler/server/persistence/repositories/PersonRepository.java b/src/main/java/io/teiler/server/persistence/repositories/PersonRepository.java index 9bb0237..597a0e0 100644 --- a/src/main/java/io/teiler/server/persistence/repositories/PersonRepository.java +++ b/src/main/java/io/teiler/server/persistence/repositories/PersonRepository.java @@ -1,19 +1,15 @@ package io.teiler.server.persistence.repositories; -import java.util.List; - -import javax.persistence.EntityManager; -import javax.transaction.Transactional; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Repository; - import com.querydsl.jpa.impl.JPAQuery; - import io.teiler.server.dto.Person; import io.teiler.server.persistence.entities.GroupEntity; import io.teiler.server.persistence.entities.PersonEntity; import io.teiler.server.persistence.entities.QPersonEntity; +import java.util.List; +import javax.persistence.EntityManager; +import javax.transaction.Transactional; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; /** * Provides database-related operations for Groups. @@ -71,6 +67,7 @@ public List getPeople(String groupId, long limit) { return new JPAQuery(entityManager).from(QPersonEntity.personEntity) .where(QPersonEntity.personEntity.groupId.eq(groupId)) .limit(limit) + .orderBy(QPersonEntity.personEntity.id.asc()) .fetch(); } diff --git a/src/main/java/io/teiler/server/util/AuthorizationChecker.java b/src/main/java/io/teiler/server/util/AuthorizationChecker.java deleted file mode 100644 index ce4dbe1..0000000 --- a/src/main/java/io/teiler/server/util/AuthorizationChecker.java +++ /dev/null @@ -1,33 +0,0 @@ -package io.teiler.server.util; - -import io.teiler.server.persistence.repositories.GroupRepository; -import io.teiler.server.util.exceptions.NotAuthorizedException; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -/** - * Provides checks to ensure proper authorisation before accessing any ressource(s). - * - * @author lroellin - */ -@Service -public class AuthorizationChecker { - - @Autowired - private GroupRepository groupRepository; - - /** - * Checks whether access to this group is to be authorised. - * - * @param uuid Id of the group - * @throws NotAuthorizedException The Group-Id is null or does not exist in the - * database. - */ - public void checkAuthorization(String uuid) throws NotAuthorizedException { - // Java checks from left to right - if (uuid == null || groupRepository.getGroupById(uuid) == null) { - throw new NotAuthorizedException(); - } - } - -} diff --git a/src/main/resources/postman/Postman.json b/src/main/resources/postman/Postman.json new file mode 100644 index 0000000..076bb8e --- /dev/null +++ b/src/main/resources/postman/Postman.json @@ -0,0 +1,322 @@ +{ + "variables": [], + "info": { + "name": "Tylr", + "_postman_id": "cda3acd3-3f94-2c5a-3124-bf3938c12a1c", + "description": "", + "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" + }, + "item": [ + { + "name": "Create new group", + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"Group name is correct\"] = jsonData.name === postman.getGlobalVariable(\"groupname\");", + "tests[\"Contains group ID\"] = 'id' in jsonData;", + "tests[\"Contains update time\"] = 'update-time' in jsonData;", + "tests[\"Contains create time\"] = 'create-time' in jsonData;", + "", + "postman.setGlobalVariable(\"group\", jsonData.id);" + ] + } + } + ], + "request": { + "url": "{{url}}/v1/groups", + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"{{groupname}}\" \n}" + }, + "description": "" + }, + "response": [] + }, + { + "name": "Get group", + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"Group name is correct\"] = jsonData.name === postman.getGlobalVariable(\"groupname\");", + "tests[\"Contains group ID\"] = 'id' in jsonData;", + "tests[\"Contains people\"] = 'people' in jsonData;", + "tests[\"Contains currency\"] = 'currency' in jsonData;", + "tests[\"Contains update time\"] = 'update-time' in jsonData;", + "tests[\"Contains create time\"] = 'create-time' in jsonData;" + ] + } + } + ], + "request": { + "url": "{{url}}/v1/groups/{{group}}", + "method": "GET", + "header": [], + "body": {}, + "description": "" + }, + "response": [] + }, + { + "name": "Create first person", + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"Person name is correct\"] = jsonData.name === postman.getGlobalVariable(\"person1\");", + "tests[\"Contains person id\"] = 'id' in jsonData;", + "tests[\"Contains update time\"] = 'update-time' in jsonData;", + "tests[\"Contains create time\"] = 'create-time' in jsonData;", + "", + "postman.setGlobalVariable(\"person1Id\", jsonData.id);" + ] + } + } + ], + "request": { + "url": "{{url}}/v1/groups/{{group}}/people", + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"{{person1}}\"\n}" + }, + "description": "" + }, + "response": [] + }, + { + "name": "Create second Person", + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"Person name is correct\"] = jsonData.name === postman.getGlobalVariable(\"person2\");", + "tests[\"Contains person id\"] = 'id' in jsonData;", + "tests[\"Contains update time\"] = 'update-time' in jsonData;", + "tests[\"Contains create time\"] = 'create-time' in jsonData;", + "", + "postman.setGlobalVariable(\"person2Id\", jsonData.id);" + ] + } + } + ], + "request": { + "url": "{{url}}/v1/groups/{{group}}/people", + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"{{person2}}\"\n}" + }, + "description": "" + }, + "response": [] + }, + { + "name": "Edit person", + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"Person name is correct\"] = jsonData.name === postman.getGlobalVariable(\"person3\");", + "tests[\"Contains person id\"] = 'id' in jsonData;", + "tests[\"Contains update time\"] = 'update-time' in jsonData;", + "tests[\"Contains create time\"] = 'create-time' in jsonData;" + ] + } + } + ], + "request": { + "url": "{{url}}/v1/groups/{{group}}/people/{{person1Id}}", + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"{{person3}}\"\n}" + }, + "description": "" + }, + "response": [] + }, + { + "name": "Show people", + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"First person is still there and changed\"] = jsonData[0].name === postman.getGlobalVariable(\"person3\");", + "tests[\"Second person is still there\"] = jsonData[1].name === postman.getGlobalVariable(\"person2\");", + "tests[\"Contains update time\"] = 'update-time' in jsonData[0];", + "tests[\"Contains create time\"] = 'create-time' in jsonData[0];" + ] + } + } + ], + "request": { + "url": "{{url}}/v1/groups/{{group}}/people?limit=5", + "method": "GET", + "header": [], + "body": {}, + "description": "" + }, + "response": [] + }, + { + "name": "Delete person", + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;" + ] + } + } + ], + "request": { + "url": "{{url}}/v1/groups/{{group}}/people/{{person1Id}}", + "method": "DELETE", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"fdfdff\"\n}" + }, + "description": "" + }, + "response": [] + }, + { + "name": "Edit group", + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var jsonData = JSON.parse(responseBody);", + "tests[\"Group name is correct\"] = jsonData.name === postman.getGlobalVariable(\"newGroupName\");", + "tests[\"Group currency\"] = jsonData.currency === postman.getGlobalVariable(\"newCurrency\");", + "tests[\"Contains update time\"] = 'update-time' in jsonData;", + "tests[\"Contains create time\"] = 'create-time' in jsonData;" + ] + } + } + ], + "request": { + "url": "{{url}}/v1/groups/{{group}}", + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"{{newGroupName}}\",\n \"currency\": \"{{newCurrency}}\"\n}" + }, + "description": "" + }, + "response": [] + }, + { + "name": "Delete a group", + "event": [ + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;" + ] + } + } + ], + "request": { + "url": "{{url}}/v1/groups/{{group}}", + "method": "DELETE", + "header": [ + { + "key": "Content-Type", + "value": "application/json", + "description": "" + } + ], + "body": { + "mode": "raw", + "raw": " {\n \"name\": \"Hallo Velo\",\n \"currency\": \"chf\"\n }" + }, + "description": "" + }, + "response": [] + } + ] +} \ No newline at end of file