diff --git a/build.gradle.kts b/build.gradle.kts index 7408179..f5ad0de 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,15 +1,16 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + plugins { - id("org.springframework.boot") version "2.2.6.RELEASE" + id("org.springframework.boot") version "2.3.0.RELEASE" id("io.spring.dependency-management") version "1.0.9.RELEASE" kotlin("jvm") version "1.3.71" - kotlin("plugin.spring") version "1.3.71" - kotlin("plugin.jpa") version "1.3.71" + kotlin("plugin.spring") version "1.3.72" + kotlin("plugin.jpa") version "1.3.72" } group = "com.aitrainer" -version = "0.0.4" +version = "0.0.5" java.sourceCompatibility = JavaVersion.VERSION_1_8 repositories { @@ -19,6 +20,8 @@ repositories { dependencies { implementation("org.springframework.boot:spring-boot-starter-data-jpa") implementation("org.springframework.boot:spring-boot-starter-web") + implementation("org.springframework.boot:spring-boot-starter-aop") + implementation("org.springframework.boot:spring-boot-starter-validation") implementation("com.fasterxml.jackson.module:jackson-module-kotlin") implementation("org.jetbrains.kotlin:kotlin-reflect") implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") @@ -33,6 +36,7 @@ dependencies { } testImplementation("junit:junit:4.13") testImplementation("org.jetbrains.kotlin:kotlin-test-junit5:1.3.72") + } tasks.withType { diff --git a/data/db/install.sql b/data/db/install.sql index 91e6e7e..08ac149 100644 --- a/data/db/install.sql +++ b/data/db/install.sql @@ -1,6 +1,6 @@ -- -------------------------------------------------------- -- Host: 127.0.0.1 --- Szerver verzió: 8.0.20 - MySQL Community Server - GPL +-- Szerver verzió: 10.4.11-MariaDB - mariadb.org binary distribution -- Szerver OS: Win64 -- HeidiSQL Verzió: 11.0.0.5919 -- -------------------------------------------------------- @@ -10,91 +10,112 @@ /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; -use aitrainer; - -- Struktúra mentése tábla aitrainer. customer CREATE TABLE IF NOT EXISTS `customer` ( - `customer_id` int NOT NULL AUTO_INCREMENT, - `name` char(100) NOT NULL, - `firstname` char(100) NOT NULL, - `email` char(100) DEFAULT NULL, - `sex` enum('m','w') DEFAULT 'm', - `age` tinyint DEFAULT NULL, - `active` enum('Y','N','D','S') DEFAULT 'N', + `customer_id` int(11) NOT NULL AUTO_INCREMENT, + `name` char(100) COLLATE utf8_hungarian_ci NOT NULL, + `firstname` char(100) COLLATE utf8_hungarian_ci NOT NULL, + `email` char(100) COLLATE utf8_hungarian_ci DEFAULT NULL, + `password` char(100) COLLATE utf8_hungarian_ci DEFAULT NULL, + `sex` enum('m','w') COLLATE utf8_hungarian_ci DEFAULT 'm', + `age` tinyint(4) DEFAULT NULL, + `active` enum('Y','N','D','S') COLLATE utf8_hungarian_ci DEFAULT 'N', + `date_add` datetime DEFAULT NULL, + `date_change` datetime DEFAULT NULL, + `data_policy_allowed` tinyint(4) DEFAULT 1, + `admin` tinyint(4) DEFAULT 0, PRIMARY KEY (`customer_id`) ) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8 COLLATE=utf8_hungarian_ci; --- Tábla adatainak mentése aitrainer.customer: ~15 rows (hozzávetőleg) +-- Tábla adatainak mentése aitrainer.customer: ~13 rows (hozzávetőleg) /*!40000 ALTER TABLE `customer` DISABLE KEYS */; -INSERT INTO `customer` (`customer_id`, `name`, `firstname`, `email`, `sex`, `age`) VALUES - (1, 'Átlag 13 éves fiú', '', NULL, 'm', 13), - (2, 'Átlag 14 éves fiú', '', NULL, 'm', 14), - (3, 'Átlag 15 éves fiú', '', NULL, 'm', 15), - (4, 'Átlag 15 éves fiú', '', NULL, 'm', 15), - (5, 'Átlag 16 éves fiú', '', NULL, 'm', 16), - (6, 'Átlag 17 éves fiú', '', NULL, 'm', 17), - (7, 'Átlag 18 éves fiú', '', NULL, 'm', 18), - (8, 'Átlag 13 éves lány', '', NULL, 'w', 13), - (9, 'Átlag 14 éves lány', '', NULL, 'w', 14), - (10, 'Átlag 15 éves lány', '', NULL, 'w', 15), - (11, 'Átlag 16 éves lány', '', NULL, 'w', 16), - (12, 'Átlag 17 éves lány', '', NULL, 'w', 17), - (13, 'Átlag 18 éves lány', '', NULL, 'w', 18); +INSERT INTO `customer` (`customer_id`, `name`, `firstname`, `email`, `password`, `sex`, `age`, `active`, `date_add`, `date_change`, `data_policy_allowed`, `admin`) VALUES + (1, 'Átlag 13 éves fiú', '', NULL, NULL, 'm', 13, 'N', NULL, NULL, 1, 0), + (2, 'Átlag 14 éves fiú', '', NULL, NULL, 'm', 14, 'N', NULL, NULL, 1, 0), + (3, 'Átlag 15 éves fiú', '', NULL, NULL, 'm', 15, 'N', NULL, NULL, 1, 0), + (4, 'Átlag 15 éves fiú', '', NULL, NULL, 'm', 15, 'N', NULL, NULL, 1, 0), + (5, 'Átlag 16 éves fiú', '', NULL, NULL, 'm', 16, 'N', NULL, NULL, 1, 0), + (6, 'Átlag 17 éves fiú', '', NULL, NULL, 'm', 17, 'N', NULL, NULL, 1, 0), + (7, 'Átlag 18 éves fiú', '', NULL, NULL, 'm', 18, 'N', NULL, NULL, 1, 0), + (8, 'Átlag 13 éves lány', '', NULL, NULL, 'w', 13, 'N', NULL, NULL, 1, 0), + (9, 'Átlag 14 éves lány', '', NULL, NULL, 'w', 14, 'N', NULL, NULL, 1, 0), + (10, 'Átlag 15 éves lány', '', NULL, NULL, 'w', 15, 'N', NULL, NULL, 1, 0), + (11, 'Átlag 16 éves lány', '', NULL, NULL, 'w', 16, 'N', NULL, NULL, 1, 0), + (12, 'Átlag 17 éves lány', '', NULL, NULL, 'w', 17, 'N', NULL, NULL, 1, 0), + (13, 'Átlag 18 éves lány', '', NULL, NULL, 'w', 18, 'N', NULL, NULL, 1, 0); /*!40000 ALTER TABLE `customer` ENABLE KEYS */; +-- Struktúra mentése tábla aitrainer. customer_information +CREATE TABLE IF NOT EXISTS `customer_information` ( + `customer_information_id` int(11) NOT NULL AUTO_INCREMENT, + `title` char(50) COLLATE utf8_hungarian_ci DEFAULT '', + `description` mediumtext COLLATE utf8_hungarian_ci DEFAULT NULL, + `date_add` datetime DEFAULT NULL, + `display_begin` datetime DEFAULT NULL, + `display_end` datetime DEFAULT NULL, + PRIMARY KEY (`customer_information_id`) USING BTREE, + KEY `title` (`title`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_hungarian_ci; + +-- Tábla adatainak mentése aitrainer.customer_information: ~0 rows (hozzávetőleg) +/*!40000 ALTER TABLE `customer_information` DISABLE KEYS */; +/*!40000 ALTER TABLE `customer_information` ENABLE KEYS */; + +INSERT INTO `customer_information` (`customer_information_id`, `title`, `description`, `date_add`, `display_begin`, `display_end`) VALUES (1, 'Fekvőtámasz világcsúcs', 'Világcsúcs fekvőtámasz: KJ Joseph 1 perc alatt 82 szabályos fekvőtámaszt végzett', '2020-06-01 08:00:00', '2020-06-01 08:00:00', '2023-07-01 08:00:00'); +INSERT INTO `customer_information` (`customer_information_id`, `title`, `description`, `date_add`, `display_begin`, `display_end`) VALUES (2, 'Húzódszkodás csúcs', '24 órás csúcstartója Joonas Mäkipelto 5050 gyakorlattal', '2020-06-01 08:00:00', '2020-06-01 08:00:00', '2023-07-01 08:00:00'); +INSERT INTO `customer_information` (`customer_information_id`, `title`, `description`, `date_add`, `display_begin`, `display_end`) VALUES (3, 'Fekvenyomás', '2015-ben a fekvenyomó világbajnokságot Smulter Fredrik finn súlyemelő 401 Kg-al nyerte', '2020-06-01 08:00:00', '2020-05-01 00:00:00', '2020-06-01 08:00:01'); + + -- Struktúra mentése tábla aitrainer. exercises CREATE TABLE IF NOT EXISTS `exercises` ( - `exercise_id` int NOT NULL AUTO_INCREMENT, - `exercise_type_id` int NOT NULL, - `customer_id` int NOT NULL, - `datetime_exercise` datetime NOT NULL, - `quantity` int DEFAULT NULL, - `rest_time` int DEFAULT NULL COMMENT 'in sec', + `exercise_id` int(11) NOT NULL AUTO_INCREMENT, + `exercise_type_id` int(11) NOT NULL, + `customer_id` int(11) NOT NULL, + `date_add` datetime NOT NULL, + `quantity` float DEFAULT NULL, + `unit` enum('kg','meter','repeat','minute') COLLATE utf8_hungarian_ci DEFAULT 'repeat', + `rest_time` int(11) DEFAULT NULL COMMENT 'in sec', PRIMARY KEY (`exercise_id`), - KEY `exercise_type_id` (`exercise_type_id`) + KEY `exercise_type_id` (`exercise_type_id`), + KEY `customer_id` (`customer_id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_hungarian_ci; --- Tábla adatainak mentése aitrainer.exercises: ~1 rows (hozzávetőleg) +-- Tábla adatainak mentése aitrainer.exercises: ~0 rows (hozzávetőleg) /*!40000 ALTER TABLE `exercises` DISABLE KEYS */; -INSERT INTO `exercises` (`exercise_id`, `exercise_type_id`, `customer_id`, `datetime_exercise`, `quantity`, `rest_time`) VALUES - (1, 1, 1, '2020-05-01 00:00:00', 12, NULL); +INSERT INTO `exercises` (`exercise_id`, `exercise_type_id`, `customer_id`, `date_add`, `quantity`, `unit`, `rest_time`) VALUES + (1, 1, 1, '2020-05-01 00:00:00', 12, 'repeat', NULL); /*!40000 ALTER TABLE `exercises` ENABLE KEYS */; --- Struktúra mentése tábla aitrainer. exercise_ages -CREATE TABLE IF NOT EXISTS `exercise_ages` ( - `exercise_age_id` int NOT NULL AUTO_INCREMENT, - `exercise_type_id` int NOT NULL, - `name` char(100) NOT NULL, - `sex` enum('m','w') DEFAULT 'm', - `age` tinyint DEFAULT NULL, - `min_exercises` int DEFAULT NULL, - `avg_exercises` int DEFAULT NULL, - `max_exercises` int DEFAULT NULL, - PRIMARY KEY (`exercise_age_id`), - UNIQUE KEY `exercise_type_id_2` (`exercise_type_id`,`sex`,`age`) -) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8 COLLATE=utf8_hungarian_ci; +-- Struktúra mentése tábla aitrainer. exercise_evaluation +CREATE TABLE IF NOT EXISTS `exercise_evaluation` ( + `evaluation_id` int(11) NOT NULL AUTO_INCREMENT, + `age_min` int(11) DEFAULT 0, + `age_max` int(11) DEFAULT 0, + `value_min` int(11) DEFAULT 0, + `value_max` int(11) DEFAULT 0, + `sex` enum('m','w') COLLATE utf8_hungarian_ci NOT NULL DEFAULT 'm', + `evaluation` enum('excellent','very good','good','average','weak','poor') COLLATE utf8_hungarian_ci NOT NULL DEFAULT 'average', + `description` mediumtext COLLATE utf8_hungarian_ci DEFAULT NULL, + PRIMARY KEY (`evaluation_id`) USING BTREE, + KEY `value_min_value_max` (`value_min`,`value_max`) USING BTREE, + KEY `age_min_age_max` (`age_min`,`age_max`) USING BTREE, + KEY `age_min_age_max_value_min_value_max` (`age_min`,`age_max`,`value_min`,`value_max`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_hungarian_ci; --- Tábla adatainak mentése aitrainer.exercise_ages: ~6 rows (hozzávetőleg) -/*!40000 ALTER TABLE `exercise_ages` DISABLE KEYS */; -INSERT INTO `exercise_ages` (`exercise_age_id`, `exercise_type_id`, `name`, `sex`, `age`, `min_exercises`, `avg_exercises`, `max_exercises`) VALUES - (1, 1, '', 'm', 13, 12, NULL, NULL), - (2, 1, '', 'm', 14, 14, NULL, NULL), - (3, 1, '', 'm', 15, 16, NULL, NULL), - (4, 1, '', 'm', 16, 18, NULL, NULL), - (7, 1, '', 'm', 17, 18, NULL, NULL), - (8, 1, '', 'm', 18, 18, NULL, NULL); -/*!40000 ALTER TABLE `exercise_ages` ENABLE KEYS */; +-- Tábla adatainak mentése aitrainer.exercise_evaluation: ~0 rows (hozzávetőleg) +/*!40000 ALTER TABLE `exercise_evaluation` DISABLE KEYS */; +/*!40000 ALTER TABLE `exercise_evaluation` ENABLE KEYS */; --- Struktúra mentése tábla aitrainer. exercise_types +-- Struktúra mentése tábla aitrainer. exercise_type CREATE TABLE IF NOT EXISTS `exercise_type` ( - `exercise_type_id` int NOT NULL AUTO_INCREMENT, - `name` char(100) NOT NULL, - `description` varchar(1000) DEFAULT NULL, - `video` mediumblob, + `exercise_type_id` int(11) NOT NULL AUTO_INCREMENT, + `name` char(100) COLLATE utf8_hungarian_ci NOT NULL, + `description` varchar(1000) COLLATE utf8_hungarian_ci DEFAULT NULL, + `video` mediumblob DEFAULT NULL, PRIMARY KEY (`exercise_type_id`) ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8 COLLATE=utf8_hungarian_ci; --- Tábla adatainak mentése aitrainer.exercise_types: ~11 rows (hozzávetőleg) +-- Tábla adatainak mentése aitrainer.exercise_type: ~11 rows (hozzávetőleg) /*!40000 ALTER TABLE `exercise_type` DISABLE KEYS */; INSERT INTO `exercise_type` (`exercise_type_id`, `name`, `description`, `video`) VALUES (1, 'Melső fekvőtámasz 1 perc', 'Ezt igazolja a 2016 márciusában beállított guinness rekord is,\r\namelyben KJ Joseph 1 perc alatt 82 szabályos karhajlítás-nyújtást\r\nvégzett.', NULL), diff --git a/data/db/install_0_0_1.sql b/data/db/install_0_0_1.sql new file mode 100644 index 0000000..36f5ee2 --- /dev/null +++ b/data/db/install_0_0_1.sql @@ -0,0 +1,115 @@ +-- -------------------------------------------------------- +-- Host: 127.0.0.1 +-- Szerver verzió: 8.0.20 - MySQL Community Server - GPL +-- Szerver OS: Win64 +-- HeidiSQL Verzió: 11.0.0.5919 +-- -------------------------------------------------------- + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET NAMES utf8 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; + +use aitrainer; + +-- Struktúra mentése tábla aitrainer. customer +CREATE TABLE IF NOT EXISTS `customer` ( + `customer_id` int NOT NULL AUTO_INCREMENT, + `name` char(100) NOT NULL, + `firstname` char(100) NOT NULL, + `email` char(100) DEFAULT NULL, + `sex` enum('m','w') DEFAULT 'm', + `age` tinyint DEFAULT NULL, + `active` enum('Y','N','D','S') DEFAULT 'N', + PRIMARY KEY (`customer_id`) +) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8 COLLATE=utf8_hungarian_ci; + +-- Tábla adatainak mentése aitrainer.customer: ~15 rows (hozzávetőleg) +/*!40000 ALTER TABLE `customer` DISABLE KEYS */; +INSERT INTO `customer` (`customer_id`, `name`, `firstname`, `email`, `sex`, `age`) VALUES + (1, 'Átlag 13 éves fiú', '', NULL, 'm', 13), + (2, 'Átlag 14 éves fiú', '', NULL, 'm', 14), + (3, 'Átlag 15 éves fiú', '', NULL, 'm', 15), + (4, 'Átlag 15 éves fiú', '', NULL, 'm', 15), + (5, 'Átlag 16 éves fiú', '', NULL, 'm', 16), + (6, 'Átlag 17 éves fiú', '', NULL, 'm', 17), + (7, 'Átlag 18 éves fiú', '', NULL, 'm', 18), + (8, 'Átlag 13 éves lány', '', NULL, 'w', 13), + (9, 'Átlag 14 éves lány', '', NULL, 'w', 14), + (10, 'Átlag 15 éves lány', '', NULL, 'w', 15), + (11, 'Átlag 16 éves lány', '', NULL, 'w', 16), + (12, 'Átlag 17 éves lány', '', NULL, 'w', 17), + (13, 'Átlag 18 éves lány', '', NULL, 'w', 18); +/*!40000 ALTER TABLE `customer` ENABLE KEYS */; + +-- Struktúra mentése tábla aitrainer. exercises +CREATE TABLE IF NOT EXISTS `exercises` ( + `exercise_id` int NOT NULL AUTO_INCREMENT, + `exercise_type_id` int NOT NULL, + `customer_id` int NOT NULL, + `datetime_exercise` datetime NOT NULL, + `quantity` float DEFAULT NULL, + `rest_time` int DEFAULT NULL COMMENT 'in sec', + PRIMARY KEY (`exercise_id`), + KEY `exercise_type_id` (`exercise_type_id`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_hungarian_ci; + +-- Tábla adatainak mentése aitrainer.exercises: ~1 rows (hozzávetőleg) +/*!40000 ALTER TABLE `exercises` DISABLE KEYS */; +INSERT INTO `exercises` (`exercise_id`, `exercise_type_id`, `customer_id`, `datetime_exercise`, `quantity`, `rest_time`) VALUES + (1, 1, 1, '2020-05-01 00:00:00', 12, NULL); +/*!40000 ALTER TABLE `exercises` ENABLE KEYS */; + +-- Struktúra mentése tábla aitrainer. exercise_ages +CREATE TABLE IF NOT EXISTS `exercise_ages` ( + `exercise_age_id` int NOT NULL AUTO_INCREMENT, + `exercise_type_id` int NOT NULL, + `name` char(100) NOT NULL, + `sex` enum('m','w') DEFAULT 'm', + `age` tinyint DEFAULT NULL, + `min_exercises` int DEFAULT NULL, + `avg_exercises` int DEFAULT NULL, + `max_exercises` int DEFAULT NULL, + PRIMARY KEY (`exercise_age_id`), + UNIQUE KEY `exercise_type_id_2` (`exercise_type_id`,`sex`,`age`) +) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8 COLLATE=utf8_hungarian_ci; + +-- Tábla adatainak mentése aitrainer.exercise_ages: ~6 rows (hozzávetőleg) +/*!40000 ALTER TABLE `exercise_ages` DISABLE KEYS */; +INSERT INTO `exercise_ages` (`exercise_age_id`, `exercise_type_id`, `name`, `sex`, `age`, `min_exercises`, `avg_exercises`, `max_exercises`) VALUES + (1, 1, '', 'm', 13, 12, NULL, NULL), + (2, 1, '', 'm', 14, 14, NULL, NULL), + (3, 1, '', 'm', 15, 16, NULL, NULL), + (4, 1, '', 'm', 16, 18, NULL, NULL), + (7, 1, '', 'm', 17, 18, NULL, NULL), + (8, 1, '', 'm', 18, 18, NULL, NULL); +/*!40000 ALTER TABLE `exercise_ages` ENABLE KEYS */; + +-- Struktúra mentése tábla aitrainer. exercise_types +CREATE TABLE IF NOT EXISTS `exercise_type` ( + `exercise_type_id` int NOT NULL AUTO_INCREMENT, + `name` char(100) NOT NULL, + `description` varchar(1000) DEFAULT NULL, + `video` mediumblob, + PRIMARY KEY (`exercise_type_id`) +) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8 COLLATE=utf8_hungarian_ci; + +-- Tábla adatainak mentése aitrainer.exercise_types: ~11 rows (hozzávetőleg) +/*!40000 ALTER TABLE `exercise_type` DISABLE KEYS */; +INSERT INTO `exercise_type` (`exercise_type_id`, `name`, `description`, `video`) VALUES + (1, 'Melső fekvőtámasz 1 perc', 'Ezt igazolja a 2016 márciusában beállított guinness rekord is,\r\namelyben KJ Joseph 1 perc alatt 82 szabályos karhajlítás-nyújtást\r\nvégzett.', NULL), + (2, 'Húzódzkodás', 'Ennek a gyakorlatnak a 24 órás csúcstartója Joonas Mäkipelto 5050\r\ngyakorlattal.', NULL), + (3, 'Melső fekvőtámasz 30mp', 'A gyakorlatot 30 másodperc alatt olyan sokszor kell végrehajtani, ahányszor a\r\nfelvételiző képes rá. Azonban törekedni kell a szabályos végrehajtásra, ugyanis csak azokat\r\nszámolják. A nők esetében 20, a férfiak esetében 35 gyakorlatot kell végrehajtani a maximális\r\npont megszerzéséért. A gyakorlat akkor sikeres, ha a női legalább 1, a férfi felvételiző\r\nlegalább 11 gyakorlatot képes végrehajtani.', NULL), + (4, 'Melső fekvőtámasz 2perc', 'Magyar Honvédség: A gyakorlat végrehajtására 2 perc áll rendelkezésre. Ennek során csak a szabályosan a\r\nfentiekben leírt módon végrehajtott gyakorlat értékelhető. Férfiaknál 70 karhajlítás nyújtást\r\nkell végrehajtani a maximális pontért.', NULL), + (5, 'Hajlított karú függés', 'A gyakorlat addig tart, amíg a végrehajtó szemmagassága a kiinduló helyzettől\r\nsüllyedve a keresztvas alá nem kerül. Az értékeléshez stopperórát alkalmaznak, és az\r\neredmény másodperc pontossággal kerül megállapításra. Nők esetében 45, férfiak\r\ntekintetében 73 másodperctől jár a maximális pontszám. A gyakorlat sikeres végrehajtásához\r\nlegalább 8, 10 másodpercig kell megtartaniuk a kiinduló helyzetet a női és a férfi\r\nfelvételizőknek.\r\n\r\nA NKE-RTK-án lévő hallgatók egyéni rekordjai Iván Viktor 90s, Kiss Regina 74s', NULL), + (6, 'Fekvenyomás', '2015-ben a fekvenyomó világbajnokságot Smulter Fredrik finn súlyemelő 401 Kg-al nyerte.\r\nA súlyzó tömege nők esetében 25 kg, a férfiak esetében 60 kg a rúddal együtt. Az\r\nértékelésénél a szabályosan végrehajtott gyakorlatokat értékelik csak.\r\nA legtöbb pontért 25 gyakorlatot kell végezni mind a nőknek, mind a férfiaknak. A minimum:\r\negy gyakorlat mindkét nem esetében.', NULL), + (7, '4x10m-es ingafutás', 'A legjobb pontszámért 9,4 s illetve 8,8s alatt kell teljesíteni a nőknek, férfiaknak. A\r\ngyakorlat sikertelen 11,8 s illetve 11,2 s-on túl.', NULL), + (8, 'Helyből távolugrás', 'Byron Jones 2015-ben a 3,73 méteres ugrásával érte el a világcsúcsot.\r\nA nőknek 220 cm-re, a férfiak 250 cm-re kell ugraniuk a maximális pontért. A\r\nminimális távolság 172cm illetve 198 cm.', NULL), + (9, 'Felülés hanyattfekvésből', 'Az NKE-RTK hallgatói közül Papp Zsófia 66 db-ot, Gál Valentin 80\r\ndb-ot csinált 1 perc leforgása alatt.\r\nElső ütemre megtörténik a felülés, ami akkor szabályos, ha valamelyik könyök érinti a\r\ntérdet. Második ütemre vissza kell térni a kiinduló helyzetbe. A maximális pont eléréséhez 1\r\nperc alatt 45 illetve 55 ismétlést kell végezni a nőknek illetve a férfiaknak. A minimumhoz 7\r\nés 25 ismétlés szükséges.', NULL), + (10, 'Felülés hajlított térddel', 'Magyar Honvédség: A kiinduló helyzet hajlított ülés, ennek során a sarkak a talajon, a térd 90 fokban meghajlítva\r\nvan.\r\nA gyakorlat végrehajtására két perc áll rendelkezésre. Ennek során csak a szabályosan,\r\na fentiekben leírt módon végrehajtott gyakorlat értékelhető. Férfiaknál, nőknél egyaránt 90\r\ngyakorlatot kell végrehajtani a maximális pontért. Amennyiben a megadott időkeret alatt nem\r\nsikerül legalább 25 szabályos gyakorlatot végrehajtani, úgy az sikertelennek minősül.', NULL), + (11, 'Síkfutás 2000m', 'A maximálisan megszerezhető pontot az a felvételiző gyűjtheti be, aki a távot nők\r\nesetében 10:00 perc alatt, férfiak esetében 7:35 perc alatt teljesíti. A gyakorlat sikeres\r\nteljesítésére nők esetében maximum 16:00 perc, férfiak esetében 13:30 perc áll rendelkezésre.', NULL); +/*!40000 ALTER TABLE `exercise_type` ENABLE KEYS */; + +/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */; +/*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; diff --git a/data/db/update_0_0_2.sql b/data/db/update_0_0_2.sql new file mode 100644 index 0000000..0f8d31d --- /dev/null +++ b/data/db/update_0_0_2.sql @@ -0,0 +1,55 @@ +ALTER TABLE `exercises` +ADD COLUMN `unit` ENUM('kg','meter','repeat','minute') NULL DEFAULT 'repeat' AFTER `quantity`, +CHANGE COLUMN `quantity` `quantity` FLOAT NULL DEFAULT NULL AFTER `datetime_exercise`; + +ALTER TABLE `exercises` +CHANGE COLUMN `datetime_exercise` `date_add` DATETIME NOT NULL AFTER `customer_id`, +ADD INDEX `customer_id` (`customer_id`); + +ALTER TABLE `customer` + ADD COLUMN `password` CHAR(100) NULL DEFAULT NULL AFTER `email`, + ADD COLUMN `date_add` DATETIME NULL AFTER `active`, + ADD COLUMN `date_change` DATETIME NULL AFTER `date_add`, + ADD COLUMN `data_policy_allowed` TINYINT NULL DEFAULT '1' AFTER `date_change`, + ADD COLUMN `admin` TINYINT NULL DEFAULT '0' AFTER `data_policy_allowed`; + +CREATE TABLE `exercise_evaluation` ( + `evaluation_id` INT(11) NOT NULL AUTO_INCREMENT, + `age_min` INT(11) NULL DEFAULT '0', + `age_max` INT(11) NULL DEFAULT '0', + `value_min` INT(11) NULL DEFAULT '0', + `value_max` INT(11) NULL DEFAULT '0', + `sex` ENUM('m','w') NOT NULL DEFAULT 'm' COLLATE 'utf8_hungarian_ci', + `evaluation` ENUM('excellent','very good','good','average','weak','poor') NOT NULL DEFAULT 'average' COLLATE 'utf8_hungarian_ci', + `description` TEXT(65535) NULL DEFAULT NULL COLLATE 'utf8_hungarian_ci', + PRIMARY KEY (`evaluation_id`) USING BTREE, + INDEX `value_min_value_max` (`value_min`, `value_max`) USING BTREE, + INDEX `age_min_age_max` (`age_min`, `age_max`) USING BTREE, + INDEX `age_min_age_max_value_min_value_max` (`age_min`, `age_max`, `value_min`, `value_max`) USING BTREE +) +COLLATE='utf8_hungarian_ci' +ENGINE=InnoDB +; + +CREATE TABLE `customer_information` ( + `customer_information_id` INT(11) NOT NULL AUTO_INCREMENT, + `title` CHAR(50) NULL DEFAULT '' COLLATE 'utf8_hungarian_ci', + `description` TEXT(65535) NULL DEFAULT NULL COLLATE 'utf8_hungarian_ci', + `date_add` DATETIME NULL DEFAULT NULL, + `display_begin` DATETIME NULL DEFAULT NULL, + `display_end` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`customer_information_id`) USING BTREE, + INDEX `title` (`title`) USING BTREE +) +COLLATE='utf8_hungarian_ci' +ENGINE=InnoDB +; + +INSERT INTO `customer_information` (`customer_information_id`, `title`, `description`, `date_add`, `display_begin`, `display_end`) VALUES (1, 'Fekvőtámasz világcsúcs', 'Világcsúcs fekvőtámasz: KJ Joseph 1 perc alatt 82 szabályos fekvőtámaszt végzett', '2020-06-01 08:00:00', '2020-06-01 08:00:00', '2023-07-01 08:00:00'); +INSERT INTO `customer_information` (`customer_information_id`, `title`, `description`, `date_add`, `display_begin`, `display_end`) VALUES (2, 'Húzódszkodás csúcs', '24 órás csúcstartója Joonas Mäkipelto 5050 gyakorlattal', '2020-06-01 08:00:00', '2020-06-01 08:00:00', '2023-07-01 08:00:00'); +INSERT INTO `customer_information` (`customer_information_id`, `title`, `description`, `date_add`, `display_begin`, `display_end`) VALUES (3, 'Fekvenyomás', '2015-ben a fekvenyomó világbajnokságot Smulter Fredrik finn súlyemelő 401 Kg-al nyerte', '2020-06-01 08:00:00', '2020-05-01 00:00:00', '2020-06-01 08:00:01'); + +DROP TABLE exercise_ages; + +UPDATE configuration set config_value = "0.0.2" WHERE config_key = "db_version"; + diff --git a/docker-compose_cowmail.yml b/docker-compose_cowmail.yml new file mode 100644 index 0000000..8e424e8 --- /dev/null +++ b/docker-compose_cowmail.yml @@ -0,0 +1,631 @@ +version: '2.1' +services: + + unbound-mailcow: + image: mailcow/unbound:1.12 + environment: + - TZ=${TZ} + volumes: + - ./data/hooks/unbound:/hooks + - ./data/conf/unbound/unbound.conf:/etc/unbound/unbound.conf:ro + restart: always + tty: true + networks: + mailcow-network: + ipv4_address: ${IPV4_NETWORK:-172.22.1}.254 + aliases: + - unbound + + mysql-mailcow: + image: mariadb:10.3 + depends_on: + - unbound-mailcow + stop_grace_period: 45s + volumes: + - mysql-vol-1:/var/lib/mysql/ + - mysql-socket-vol-1:/var/run/mysqld/ + - ./data/conf/mysql/:/etc/mysql/conf.d/:ro + environment: + - TZ=${TZ} + - MYSQL_ROOT_PASSWORD=${DBROOT} + - MYSQL_DATABASE=${DBNAME} + - MYSQL_USER=${DBUSER} + - MYSQL_PASSWORD=${DBPASS} + - MYSQL_INITDB_SKIP_TZINFO=1 + restart: always + ports: + - "${SQL_PORT:-127.0.0.1:13306}:3306" + networks: + mailcow-network: + aliases: + - mysql + + redis-mailcow: + image: redis:5-alpine + volumes: + - redis-vol-1:/data/ + restart: always + ports: + - "${REDIS_PORT:-127.0.0.1:7654}:6379" + environment: + - TZ=${TZ} + networks: + mailcow-network: + ipv4_address: ${IPV4_NETWORK:-172.22.1}.249 + aliases: + - redis + + clamd-mailcow: + image: mailcow/clamd:1.36 + restart: always + dns: + - ${IPV4_NETWORK:-172.22.1}.254 + environment: + - TZ=${TZ} + - SKIP_CLAMD=${SKIP_CLAMD:-n} + volumes: + - ./data/conf/clamav/:/etc/clamav/ + networks: + mailcow-network: + aliases: + - clamd + + rspamd-mailcow: + image: mailcow/rspamd:1.68 + stop_grace_period: 30s + depends_on: + - nginx-mailcow + - dovecot-mailcow + environment: + - TZ=${TZ} + - IPV4_NETWORK=${IPV4_NETWORK:-172.22.1} + - IPV6_NETWORK=${IPV6_NETWORK:-fd4d:6169:6c63:6f77::/64} + - REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-} + - REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-} + volumes: + - ./data/hooks/rspamd:/hooks + - ./data/conf/rspamd/custom/:/etc/rspamd/custom + - ./data/conf/rspamd/override.d/:/etc/rspamd/override.d + - ./data/conf/rspamd/local.d/:/etc/rspamd/local.d + - ./data/conf/rspamd/plugins.d/:/etc/rspamd/plugins.d + - ./data/conf/rspamd/lua/:/etc/rspamd/lua/:ro + - ./data/conf/rspamd/rspamd.conf.local:/etc/rspamd/rspamd.conf.local + - ./data/conf/rspamd/rspamd.conf.override:/etc/rspamd/rspamd.conf.override + - rspamd-vol-1:/var/lib/rspamd + restart: always + dns: + - ${IPV4_NETWORK:-172.22.1}.254 + hostname: rspamd + networks: + mailcow-network: + aliases: + - rspamd + + php-fpm-mailcow: + image: mailcow/phpfpm:1.63 + command: "php-fpm -d date.timezone=${TZ} -d expose_php=0" + depends_on: + - redis-mailcow + volumes: + - ./data/hooks/phpfpm:/hooks + - ./data/web:/web:rw + - ./data/conf/rspamd/dynmaps:/dynmaps:ro + - ./data/conf/rspamd/custom/:/rspamd_custom_maps + - rspamd-vol-1:/var/lib/rspamd + - mysql-socket-vol-1:/var/run/mysqld/ + - ./data/conf/sogo/:/etc/sogo/ + - ./data/conf/rspamd/meta_exporter:/meta_exporter:ro + - ./data/conf/phpfpm/sogo-sso/:/etc/sogo-sso/ + - ./data/conf/phpfpm/php-fpm.d/pools.conf:/usr/local/etc/php-fpm.d/z-pools.conf + - ./data/conf/phpfpm/php-conf.d/opcache-recommended.ini:/usr/local/etc/php/conf.d/opcache-recommended.ini + - ./data/conf/phpfpm/php-conf.d/upload.ini:/usr/local/etc/php/conf.d/upload.ini + - ./data/conf/phpfpm/php-conf.d/other.ini:/usr/local/etc/php/conf.d/zzz-other.ini + - ./data/conf/dovecot/global_sieve_before:/global_sieve/before + - ./data/conf/dovecot/global_sieve_after:/global_sieve/after + - ./data/assets/templates:/tpls + dns: + - ${IPV4_NETWORK:-172.22.1}.254 + environment: + - REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-} + - REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-} + - LOG_LINES=${LOG_LINES:-9999} + - TZ=${TZ} + - DBNAME=${DBNAME} + - DBUSER=${DBUSER} + - DBPASS=${DBPASS} + - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME} + - IMAP_PORT=${IMAP_PORT:-143} + - IMAPS_PORT=${IMAPS_PORT:-993} + - POP_PORT=${POP_PORT:-110} + - POPS_PORT=${POPS_PORT:-995} + - SIEVE_PORT=${SIEVE_PORT:-4190} + - SUBMISSION_PORT=${SUBMISSION_PORT:-587} + - SMTPS_PORT=${SMTPS_PORT:-465} + - SMTP_PORT=${SMTP_PORT:-25} + - API_KEY=${API_KEY:-invalid} + - API_KEY_READ_ONLY=${API_KEY_READ_ONLY:-invalid} + - API_ALLOW_FROM=${API_ALLOW_FROM:-invalid} + - COMPOSE_PROJECT_NAME=${COMPOSE_PROJECT_NAME:-mailcow-dockerized} + - SKIP_SOLR=${SKIP_SOLR:-y} + - SKIP_CLAMD=${SKIP_CLAMD:-n} + - SKIP_SOGO=${SKIP_SOGO:-n} + - ALLOW_ADMIN_EMAIL_LOGIN=${ALLOW_ADMIN_EMAIL_LOGIN:-n} + - MASTER=${MASTER:-y} + restart: always + networks: + mailcow-network: + aliases: + - phpfpm + + sogo-mailcow: + image: mailcow/sogo:1.74 + environment: + - DBNAME=${DBNAME} + - DBUSER=${DBUSER} + - DBPASS=${DBPASS} + - TZ=${TZ} + - LOG_LINES=${LOG_LINES:-9999} + - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME} + - ACL_ANYONE=${ACL_ANYONE:-disallow} + - ALLOW_ADMIN_EMAIL_LOGIN=${ALLOW_ADMIN_EMAIL_LOGIN:-n} + - IPV4_NETWORK=${IPV4_NETWORK:-172.22.1} + - SOGO_EXPIRE_SESSION=${SOGO_EXPIRE_SESSION:-480} + - SKIP_SOGO=${SKIP_SOGO:-n} + - MASTER=${MASTER:-y} + - REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-} + - REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-} + dns: + - ${IPV4_NETWORK:-172.22.1}.254 + volumes: + - ./data/conf/sogo/:/etc/sogo/ + - ./data/web/inc/init_db.inc.php:/init_db.inc.php + - ./data/conf/sogo/custom-sogo.js:/usr/lib/GNUstep/SOGo/WebServerResources/js/custom-sogo.js + - mysql-socket-vol-1:/var/run/mysqld/ + - sogo-web-vol-1:/sogo_web + - sogo-userdata-backup-vol-1:/sogo_backup + restart: always + networks: + mailcow-network: + ipv4_address: ${IPV4_NETWORK:-172.22.1}.248 + aliases: + - sogo + + dovecot-mailcow: + image: mailcow/dovecot:1.125 + depends_on: + - mysql-mailcow + dns: + - ${IPV4_NETWORK:-172.22.1}.254 + cap_add: + - NET_BIND_SERVICE + volumes: + - ./data/hooks/dovecot:/hooks + - ./data/conf/dovecot:/etc/dovecot + - ./data/assets/ssl:/etc/ssl/mail/:ro + - ./data/conf/sogo/:/etc/sogo/ + - ./data/conf/phpfpm/sogo-sso/:/etc/phpfpm/ + - vmail-vol-1:/var/vmail + - vmail-attachments-vol-1:/var/attachments + - crypt-vol-1:/mail_crypt/ + - ./data/conf/rspamd/custom/:/etc/rspamd/custom + - ./data/assets/templates:/templates + - rspamd-vol-1:/var/lib/rspamd + - mysql-socket-vol-1:/var/run/mysqld/ + environment: + - LOG_LINES=${LOG_LINES:-9999} + - DBNAME=${DBNAME} + - DBUSER=${DBUSER} + - DBPASS=${DBPASS} + - TZ=${TZ} + - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME} + - IPV4_NETWORK=${IPV4_NETWORK:-172.22.1} + - ALLOW_ADMIN_EMAIL_LOGIN=${ALLOW_ADMIN_EMAIL_LOGIN:-n} + - MAILDIR_GC_TIME=${MAILDIR_GC_TIME:-1440} + - ACL_ANYONE=${ACL_ANYONE:-disallow} + - SKIP_SOLR=${SKIP_SOLR:-y} + - MAILDIR_SUB=${MAILDIR_SUB:-} + - MASTER=${MASTER:-y} + - REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-} + - REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-} + ports: + - "${DOVEADM_PORT:-127.0.0.1:19991}:12345" + - "${IMAP_PORT:-143}:143" + - "${IMAPS_PORT:-993}:993" + - "${POP_PORT:-110}:110" + - "${POPS_PORT:-995}:995" + - "${SIEVE_PORT:-4190}:4190" + restart: always + tty: true + ulimits: + nproc: 65535 + nofile: + soft: 20000 + hard: 40000 + hostname: ${MAILCOW_HOSTNAME} + networks: + mailcow-network: + ipv4_address: ${IPV4_NETWORK:-172.22.1}.250 + aliases: + - dovecot + + postfix-mailcow: + image: mailcow/postfix:1.49 + depends_on: + - mysql-mailcow + volumes: + - ./data/hooks/postfix:/hooks + - ./data/conf/postfix:/opt/postfix/conf + - ./data/assets/ssl:/etc/ssl/mail/:ro + - postfix-vol-1:/var/spool/postfix + - crypt-vol-1:/var/lib/zeyple + - rspamd-vol-1:/var/lib/rspamd + - mysql-socket-vol-1:/var/run/mysqld/ + environment: + - LOG_LINES=${LOG_LINES:-9999} + - TZ=${TZ} + - DBNAME=${DBNAME} + - DBUSER=${DBUSER} + - DBPASS=${DBPASS} + - REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-} + - REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-} + cap_add: + - NET_BIND_SERVICE + ports: + - "${SMTP_PORT:-25}:25" + - "${SMTPS_PORT:-465}:465" + - "${SUBMISSION_PORT:-587}:587" + restart: always + dns: + - ${IPV4_NETWORK:-172.22.1}.254 + hostname: ${MAILCOW_HOSTNAME} + networks: + mailcow-network: + aliases: + - postfix + + memcached-mailcow: + image: memcached:alpine + restart: always + environment: + - TZ=${TZ} + networks: + mailcow-network: + aliases: + - memcached + + nginx-mailcow: + depends_on: + - sogo-mailcow + - php-fpm-mailcow + - redis-mailcow + image: nginx:mainline-alpine + dns: + - ${IPV4_NETWORK:-172.22.1}.254 + command: /bin/sh -c "envsubst < /etc/nginx/conf.d/templates/listen_plain.template > /etc/nginx/conf.d/listen_plain.active && + envsubst < /etc/nginx/conf.d/templates/listen_ssl.template > /etc/nginx/conf.d/listen_ssl.active && + envsubst < /etc/nginx/conf.d/templates/server_name.template > /etc/nginx/conf.d/server_name.active && + envsubst < /etc/nginx/conf.d/templates/sogo.template > /etc/nginx/conf.d/sogo.active && + envsubst < /etc/nginx/conf.d/templates/sogo_eas.template > /etc/nginx/conf.d/sogo_eas.active && + . /etc/nginx/conf.d/templates/sogo.auth_request.template.sh > /etc/nginx/conf.d/sogo_proxy_auth.active && + . /etc/nginx/conf.d/templates/sites.template.sh > /etc/nginx/conf.d/sites.active && + nginx -qt && + until ping phpfpm -c1 > /dev/null; do sleep 1; done && + until ping sogo -c1 > /dev/null; do sleep 1; done && + until ping redis -c1 > /dev/null; do sleep 1; done && + until ping rspamd -c1 > /dev/null; do sleep 1; done && + exec nginx -g 'daemon off;'" + environment: + - HTTPS_PORT=${HTTPS_PORT:-443} + - HTTP_PORT=${HTTP_PORT:-80} + - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME} + - IPV4_NETWORK=${IPV4_NETWORK:-172.22.1} + - TZ=${TZ} + - ALLOW_ADMIN_EMAIL_LOGIN=${ALLOW_ADMIN_EMAIL_LOGIN:-n} + volumes: + - ./data/web:/web:ro + - ./data/conf/rspamd/dynmaps:/dynmaps:ro + - ./data/assets/ssl/:/etc/ssl/mail/:ro + - ./data/conf/nginx/:/etc/nginx/conf.d/:rw + - ./data/conf/rspamd/meta_exporter:/meta_exporter:ro + - sogo-web-vol-1:/usr/lib/GNUstep/SOGo/ + ports: + - "${HTTPS_BIND:-0.0.0.0}:${HTTPS_PORT:-443}:${HTTPS_PORT:-443}" + - "${HTTP_BIND:-0.0.0.0}:${HTTP_PORT:-80}:${HTTP_PORT:-80}" + restart: always + networks: + mailcow-network: + aliases: + - nginx + + acme-mailcow: + depends_on: + - nginx-mailcow + image: mailcow/acme:1.70 + dns: + - ${IPV4_NETWORK:-172.22.1}.254 + environment: + - LOG_LINES=${LOG_LINES:-9999} + - ADDITIONAL_SAN=${ADDITIONAL_SAN} + - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME} + - DBNAME=${DBNAME} + - DBUSER=${DBUSER} + - DBPASS=${DBPASS} + - SKIP_LETS_ENCRYPT=${SKIP_LETS_ENCRYPT:-n} + - ENABLE_SSL_SNI=${ENABLE_SSL_SNI:-n} + - SKIP_IP_CHECK=${SKIP_IP_CHECK:-n} + - SKIP_HTTP_VERIFICATION=${SKIP_HTTP_VERIFICATION:-n} + - ONLY_MAILCOW_HOSTNAME=${ONLY_MAILCOW_HOSTNAME:-n} + - LE_STAGING=${LE_STAGING:-n} + - TZ=${TZ} + - REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-} + - REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-} + - SNAT_TO_SOURCE=${SNAT_TO_SOURCE:-n} + - SNAT6_TO_SOURCE=${SNAT6_TO_SOURCE:-n} + volumes: + - ./data/web/.well-known/acme-challenge:/var/www/acme:rw + - ./data/assets/ssl:/var/lib/acme/:rw + - ./data/assets/ssl-example:/var/lib/ssl-example/:ro + - mysql-socket-vol-1:/var/run/mysqld/ + restart: always + networks: + mailcow-network: + aliases: + - acme + + netfilter-mailcow: + image: mailcow/netfilter:1.36 + stop_grace_period: 30s + depends_on: + - dovecot-mailcow + - postfix-mailcow + - sogo-mailcow + - php-fpm-mailcow + - redis-mailcow + restart: always + privileged: true + environment: + - TZ=${TZ} + - IPV4_NETWORK=${IPV4_NETWORK:-172.22.1} + - IPV6_NETWORK=${IPV6_NETWORK:-fd4d:6169:6c63:6f77::/64} + - SNAT_TO_SOURCE=${SNAT_TO_SOURCE:-n} + - SNAT6_TO_SOURCE=${SNAT6_TO_SOURCE:-n} + - REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-} + - REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-} + network_mode: "host" + volumes: + - /lib/modules:/lib/modules:ro + + watchdog-mailcow: + image: mailcow/watchdog:1.77 + # Debug + #command: /watchdog.sh + dns: + - ${IPV4_NETWORK:-172.22.1}.254 + volumes: + - rspamd-vol-1:/var/lib/rspamd + - mysql-socket-vol-1:/var/run/mysqld/ + - ./data/assets/ssl:/etc/ssl/mail/:ro + restart: always + environment: + - IPV6_NETWORK=${IPV6_NETWORK:-fd4d:6169:6c63:6f77::/64} + - LOG_LINES=${LOG_LINES:-9999} + - TZ=${TZ} + - DBNAME=${DBNAME} + - DBUSER=${DBUSER} + - DBPASS=${DBPASS} + - DBROOT=${DBROOT} + - USE_WATCHDOG=${USE_WATCHDOG:-n} + - WATCHDOG_NOTIFY_EMAIL=${WATCHDOG_NOTIFY_EMAIL} + - WATCHDOG_NOTIFY_BAN=${WATCHDOG_NOTIFY_BAN:-y} + - WATCHDOG_EXTERNAL_CHECKS=${WATCHDOG_EXTERNAL_CHECKS:-n} + - WATCHDOG_MYSQL_REPLICATION_CHECKS=${WATCHDOG_MYSQL_REPLICATION_CHECKS:-n} + - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME} + - IPV4_NETWORK=${IPV4_NETWORK:-172.22.1} + - IP_BY_DOCKER_API=${IP_BY_DOCKER_API:-0} + - CHECK_UNBOUND=${CHECK_UNBOUND:-1} + - SKIP_CLAMD=${SKIP_CLAMD:-n} + - SKIP_LETS_ENCRYPT=${SKIP_LETS_ENCRYPT:-n} + - SKIP_SOGO=${SKIP_SOGO:-n} + - HTTPS_PORT=${HTTPS_PORT:-443} + - REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-} + - REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-} + - EXTERNAL_CHECKS_THRESHOLD=1 + - NGINX_THRESHOLD=5 + - UNBOUND_THRESHOLD=5 + - REDIS_THRESHOLD=5 + - MYSQL_THRESHOLD=5 + - MYSQL_REPLICATION_THRESHOLD=1 + - SOGO_THRESHOLD=3 + - POSTFIX_THRESHOLD=8 + - CLAMD_THRESHOLD=15 + - DOVECOT_THRESHOLD=12 + - DOVECOT_REPL_THRESHOLD=2 + - PHPFPM_THRESHOLD=5 + - RATELIMIT_THRESHOLD=1 + - FAIL2BAN_THRESHOLD=1 + - ACME_THRESHOLD=1 + - IPV6NAT_THRESHOLD=1 + - RSPAMD_THRESHOLD=5 + - OLEFY_THRESHOLD=5 + networks: + mailcow-network: + aliases: + - watchdog + + dockerapi-mailcow: + image: mailcow/dockerapi:1.37 + restart: always + oom_kill_disable: true + dns: + - ${IPV4_NETWORK:-172.22.1}.254 + environment: + - DBROOT=${DBROOT} + - TZ=${TZ} + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + networks: + mailcow-network: + aliases: + - dockerapi + + solr-mailcow: + image: mailcow/solr:1.7 + restart: always + volumes: + - solr-vol-1:/opt/solr/server/solr/dovecot-fts/data + ports: + - "${SOLR_PORT:-127.0.0.1:18983}:8983" + environment: + - TZ=${TZ} + - SOLR_HEAP=${SOLR_HEAP:-1024} + - SKIP_SOLR=${SKIP_SOLR:-y} + networks: + mailcow-network: + aliases: + - solr + + olefy-mailcow: + image: mailcow/olefy:1.3 + restart: always + environment: + - TZ=${TZ} + - OLEFY_BINDADDRESS=0.0.0.0 + - OLEFY_BINDPORT=10055 + - OLEFY_TMPDIR=/tmp + - OLEFY_PYTHON_PATH=/usr/bin/python3 + - OLEFY_OLEVBA_PATH=/usr/bin/olevba3 + - OLEFY_LOGLVL=20 + - OLEFY_MINLENGTH=500 + - OLEFY_DEL_TMP=1 + networks: + mailcow-network: + aliases: + - olefy + + ipv6nat-mailcow: + depends_on: + - unbound-mailcow + - mysql-mailcow + - redis-mailcow + - clamd-mailcow + - rspamd-mailcow + - php-fpm-mailcow + - sogo-mailcow + - dovecot-mailcow + - postfix-mailcow + - memcached-mailcow + - nginx-mailcow + - acme-mailcow + - netfilter-mailcow + - watchdog-mailcow + - dockerapi-mailcow + - solr-mailcow + environment: + - TZ=${TZ} + image: robbertkl/ipv6nat + restart: always + privileged: true + network_mode: "host" + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + - /lib/modules:/lib/modules:ro + + + gitlab: + image: 'gitlab/gitlab-ce:latest' + container_name: 'gitlab' + restart: always + hostname: 'localhost' + environment: + GITLAB_OMNIBUS_CONFIG: | + external_url 'https://aitrainer.app:8929' + gitlab_rails['smtp_enable'] = true + gitlab_rails['smtp_address'] = "email-smtp.eu-west-1.amazonaws.com" + gitlab_rails['smtp_port'] = 587 + gitlab_rails['smtp_user_name'] = "AKIAIWHHQDMPADT7ETHQ" + gitlab_rails['smtp_password'] = "AjCB8NA+61i/URp09gik0HHtbEuy48e4JXhuPaqGacFs" + gitlab_rails['smtp_domain'] = "aitrainer.app" + gitlab_rails['smtp_authentication'] = "login" + gitlab_rails['smtp_enable_starttls_auto'] = true + gitlab_rails['smtp_openssl_verify_mode'] = 'peer' + # Add any other gitlab.rb configuration here, each on its own line + gitlab_rails['gitlab_shell_ssh_port'] = 6622 + ports: + - '8929:8929' + - '443:443' + - '6622:22' + - '587:587' + volumes: + - '/srv/gitlab/config:/etc/gitlab' + - '/srv/gitlab/logs:/var/log/gitlab' + - '/srv/gitlab/data:/var/opt/gitlab' + + mysql: + image: mysql:latest + volumes: + - mysql-vol-0:/var/lib/mysql0 + restart: always + ports: + - 33061:33061 + environment: + MYSQL_ROOT_PASSWORD: /run/secrets/mysql_root_pwd + MYSQL_DATABASE: aitrainer + MYSQL_USER: aitrainer + MYSQL_PASSWORD: /run/secrets/mysql_user_pwd + networks: + - bosi_default + + phpmyadmin: + depends_on: + - mysql + image: phpmyadmin/phpmyadmin + restart: always + ports: + - '80:80' + environment: + PMA_HOST: mysql + MYSQL_ROOT_PASSWORD: andio2009 + networks: + - bosi_default + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - /srv/gitlab-runner/config:/etc/gitlab-runner + + +networks: + bosi_default: + mailcow-network: + driver: bridge + driver_opts: + com.docker.network.bridge.name: br-mailcow + enable_ipv6: true + ipam: + driver: default + config: + - subnet: ${IPV4_NETWORK:-172.22.1}.0/24 + - subnet: ${IPV6_NETWORK:-fd4d:6169:6c63:6f77::/64} + +volumes: + # Storage for email files + vmail-vol-1: + # Storage for attachments (deduplicated) + vmail-attachments-vol-1: + mysql-vol-1: + mysql-vol-0: + mysql-socket-vol-1: + redis-vol-1: + rspamd-vol-1: + solr-vol-1: + postfix-vol-1: + crypt-vol-1: + sogo-web-vol-1: + sogo-userdata-backup-vol-1: + php: + +secrets: + mysql_root_pwd: + file: /.sec/mysql_root_pwd + mysql_user_pwd: + file: /.sec/mysql_user_pwd + + diff --git a/docker-compose_gitlab.yml b/docker-compose_gitlab.yml new file mode 100644 index 0000000..c79b49d --- /dev/null +++ b/docker-compose_gitlab.yml @@ -0,0 +1,143 @@ +version: '3.8' +services: + + demo: + image: ehazlett/docker-demo + deploy: + replicas: 1 + labels: + com.docker.lb.hosts: aitrainer.app + com.docker.lb.network: bosi-network + com.docker.lb.port: 8080 + com.docker.lb.ssl_cert: demo_app.example.org.cert + com.docker.lb.ssl_key: demo_app.example.org.key + environment: + METADATA: proxy-handles-tls + networks: + - demo-network + + gitlab: + image: 'gitlab/gitlab-ce:latest' + container_name: 'gitlab' + restart: always + hostname: 'localhost' + environment: + GITLAB_OMNIBUS_CONFIG: | + external_url 'https://aitrainer.app' + gitlab_rails['smtp_enable'] = true + gitlab_rails['smtp_address'] = "email-smtp.eu-west-1.amazonaws.com" + gitlab_rails['smtp_port'] = 587 + gitlab_rails['smtp_user_name'] = "AKIAIWHHQDMPADT7ETHQ" + gitlab_rails['smtp_password'] = "AjCB8NA+61i/URp09gik0HHtbEuy48e4JXhuPaqGacFs" + gitlab_rails['smtp_domain'] = "aitrainer.app" + gitlab_rails['smtp_authentication'] = "login" + gitlab_rails['smtp_enable_starttls_auto'] = true + gitlab_rails['smtp_openssl_verify_mode'] = 'peer' + # Add any other gitlab.rb configuration here, each on its own line + gitlab_rails['gitlab_shell_ssh_port'] = 6622 + ports: + - '80:80' + - '443:443' + - '6622:22' + - '587:587' + volumes: + - '/srv/gitlab/config:/etc/gitlab' + - '/srv/gitlab/logs:/var/log/gitlab' + - '/srv/gitlab/data:/var/opt/gitlab' + mysql: + image: mysql:latest + volumes: + - db_data:/var/lib/mysql_aitrainer + restart: always + ports: + - 33061:33061 + environment: + MYSQL_ROOT_PASSWORD: /run/secrets/mysql_root_pwd + MYSQL_DATABASE: aitrainer + MYSQL_USER: aitrainer + MYSQL_PASSWORD: /run/secrets/mysql_user_pwd + networks: + - bosi_default + + phpmyadmin: + depends_on: + - mysql + image: phpmyadmin/phpmyadmin + restart: always + ports: + - '8081:80' + environment: + PMA_HOST: mysql + MYSQL_ROOT_PASSWORD: andio2009 + networks: + - bosi_default + php: + image: php:7.2-fpm + volumes: + - php:/var/www/html + - ./php/php.ini:/usr/local/etc/php/php.ini + depends_on: + - mysql + gitlab-runner: + image: gitlab/gitlab-runner:latest + container_name: gitlab-runner + restart: always + networks: + - bosi_default + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - /srv/gitlab-runner/config:/etc/gitlab-runner +secrets: + mysql_root_pwd: + file: /.sec/mysql_root_pwd + mysql_user_pwd: + file: /.sec/mysql_user_pwd +networks: + bosi_default: +volumes: + db_data: + php: + + + + openssl req \ + -new \ + -newkey rsa:4096 \ + -days 3650 \ + -nodes \ + -x509 \ + -subj "/C=US/ST=CA/L=SF/O=Docker-demo/CN=aitrainer.app" \ + -keyout aitrainer.app.key \ + -out aitrainer.app.cert + +version: "3.2" + +services: + demo: + image: proxy + command: --tls-cert=/run/secrets/cert.pem --tls-key=/run/secrets/key.pem + deploy: + replicas: 1 + labels: + com.docker.lb.hosts: aitrainer.app + com.docker.lb.network: proxy-network + com.docker.lb.port: 8029 + com.docker.lb.ssl_passthrough: "true" + environment: + METADATA: end-to-end-TLS + networks: + - proxy-network + secrets: + - source: aitrainer.app.cert + target: /run/secrets/cert.pem + - source: aitrainer.app.org.key + target: /run/secrets/key.pem + +networks: + demo-network: + driver: overlay +secrets: + aitrainer.app.cert: + file: ./aitrainer.app.cert + aitrainer.app.key: + file: ./aitrainer.app.key \ No newline at end of file diff --git a/readme.MD b/readme.MD index 3a4e2c2..451fa34 100644 --- a/readme.MD +++ b/readme.MD @@ -1,9 +1,13 @@ -aitrainer server API v0.0.2 +#aitrainer server API v0.0.5 connects the MYSQL Database -provide a RESTful API to the mobile app +provide a RESTful API for the mobile app -finished API: +##finished API -customers -exercise type impl.ed +* customers +* exercise_type +* exercise +* customer_information + +with automatic database update diff --git a/src/main/kotlin/com/aitrainer/api/ApiApplication.kt b/src/main/kotlin/com/aitrainer/api/ApiApplication.kt index 742e079..0682bc7 100644 --- a/src/main/kotlin/com/aitrainer/api/ApiApplication.kt +++ b/src/main/kotlin/com/aitrainer/api/ApiApplication.kt @@ -4,7 +4,6 @@ import org.slf4j.LoggerFactory import org.springframework.boot.SpringApplication import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.builder.SpringApplicationBuilder -import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController @@ -12,19 +11,14 @@ import org.springframework.web.bind.annotation.RestController @RestController class ApiApplication private val logger = LoggerFactory.getLogger(ApiApplication::class.simpleName) + @Override fun configure(application: SpringApplicationBuilder): SpringApplicationBuilder { return application.sources(ApiApplication::class.java) } - fun main(args: Array) { logger.info(" ---- Start aitrainer API") SpringApplication.run(ApiApplication::class.java, *args) } - - @RequestMapping( "/") - fun hello(): String { - return "Hello Aitrainer API" - } diff --git a/src/main/kotlin/com/aitrainer/api/controller/ApplicationProperties.kt b/src/main/kotlin/com/aitrainer/api/controller/ApplicationProperties.kt new file mode 100644 index 0000000..92070d1 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/controller/ApplicationProperties.kt @@ -0,0 +1,45 @@ +package com.aitrainer.api.controller + +import org.springframework.beans.factory.annotation.Value +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController + +@RestController +@RequestMapping() +class ApplicationProperties { + + @Value("\${application.version}") + private lateinit var version: String + + @Value("\${spring.datasource.url}") + private lateinit var datasourceUrl: String + + @Value("\${spring.datasource.username}") + private lateinit var datasourceUsername: String + + @Value("\${spring.datasource.password}") + private lateinit var datasourcePassword: String + + + + @GetMapping("/version") + fun getVersion(): String { + return this.version + } + + @GetMapping("/datasourceUrl") + fun getDatasourceUrl(): String { + return this.datasourceUrl + } + + @GetMapping("/datasourceUsername") + fun getDatasourceUsername(): String { + return this.datasourceUsername + } + + @GetMapping("/datasourcePassword") + fun getDatasourcePassword(): String { + return this.datasourcePassword + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/controller/ConfigurationController.kt b/src/main/kotlin/com/aitrainer/api/controller/ConfigurationController.kt new file mode 100644 index 0000000..98e16fc --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/controller/ConfigurationController.kt @@ -0,0 +1,27 @@ +package com.aitrainer.api.controller + +import com.aitrainer.api.model.Configuration + +import com.aitrainer.api.repository.ConfigurationRepository +import org.springframework.web.bind.annotation.RestController +import java.time.LocalDateTime + +@RestController +class ConfigurationController ( private val configurationRepository: ConfigurationRepository) { + + fun getConfiguration(key: String): Configuration = + configurationRepository.findByConfigKey(key) + + fun updateConfiguration( newConfiguration: Configuration): Configuration { + val existingConfiguration: Configuration = configurationRepository.findByConfigKey(newConfiguration.configKey) + val updatedConfiguration: Configuration = existingConfiguration.copy( + configKey = newConfiguration.configKey, + configValue = newConfiguration.configValue, + //dateAdd = newConfiguration.dateAdd, + dateChange = LocalDateTime.now().toString()) + + configurationRepository.save(updatedConfiguration) + return existingConfiguration + } + +} diff --git a/src/main/kotlin/com/aitrainer/api/controller/CustomerControllerAspect.kt b/src/main/kotlin/com/aitrainer/api/controller/CustomerControllerAspect.kt new file mode 100644 index 0000000..b4301e6 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/controller/CustomerControllerAspect.kt @@ -0,0 +1,34 @@ +package com.aitrainer.api.controller + +import com.aitrainer.api.ApiApplication +import com.aitrainer.api.repository.ConfigurationRepository +import org.aspectj.lang.annotation.Around +import org.aspectj.lang.annotation.Aspect +import org.aspectj.lang.annotation.Before +import org.aspectj.lang.annotation.Pointcut +import org.slf4j.LoggerFactory +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.stereotype.Component + + +@Suppress("unused") +@Aspect +@Component +class CustomerControllerAspect { + private val logger = LoggerFactory.getLogger(ApiApplication::class.simpleName) + + @Autowired + private lateinit var configurationRepository: ConfigurationRepository + @Autowired + private lateinit var properties: ApplicationProperties + + @Suppress("unused") + @Pointcut("execution(* com.aitrainer.api.controller.CustomerController.*())") + fun customerControllerAspect() { + } + + @Before("customerControllerAspect()") + fun loggingAop() { + Singleton.checkDBUpdate(configurationRepository, properties) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/controller/CustomerInformationController.kt b/src/main/kotlin/com/aitrainer/api/controller/CustomerInformationController.kt new file mode 100644 index 0000000..1a40648 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/controller/CustomerInformationController.kt @@ -0,0 +1,18 @@ +package com.aitrainer.api.controller + +import com.aitrainer.api.model.CustomerInformation +import com.aitrainer.api.repository.CustomerInformationRepository +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController +import java.time.LocalDateTime + +@RestController +@RequestMapping("/api") +class CustomerInformationController( private val customerInformationRepository: CustomerInformationRepository ) { + + @GetMapping("/customer_information") + fun getCustomerInformation(dateTime: String): List = + customerInformationRepository.findByDisplayBeginLessThanAndDisplayEndGreaterThan(dateTime, dateTime ) + +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/controller/DatabaseCheckSingleton.kt b/src/main/kotlin/com/aitrainer/api/controller/DatabaseCheckSingleton.kt new file mode 100644 index 0000000..ec4fc01 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/controller/DatabaseCheckSingleton.kt @@ -0,0 +1,105 @@ +package com.aitrainer.api.controller + +import com.aitrainer.api.ApiApplication +import com.aitrainer.api.model.Configuration +import com.aitrainer.api.repository.ConfigurationRepository +import org.hibernate.Hibernate.isInitialized +import org.slf4j.LoggerFactory +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.web.bind.annotation.RestController +import java.io.File +import java.sql.Connection +import java.sql.DriverManager +import java.sql.ResultSet +import java.util.Properties + +@RestController +object Singleton { + + private lateinit var connection: Connection + private lateinit var configurationRepository: ConfigurationRepository + private lateinit var properties: ApplicationProperties + + private var initialized: Boolean = false + + private val logger = LoggerFactory.getLogger(ApiApplication::class.simpleName) + + // to use the singleton functionality avoiding the db access before each request + private var dbVersion: String = "" + private var appVersion: String = "" + + fun checkDBUpdate(configurationRepository: ConfigurationRepository, properties: ApplicationProperties) { + + if ( dbVersion.isNotEmpty() && appVersion.isNotEmpty()) { + // no db access + //println("DB up-to-date, no DB access") + return + } + + this.configurationRepository = configurationRepository + this.properties = properties + + val dbConfig: Configuration = configurationRepository.findByConfigKey("db_version") + val applicationVersion: String = properties.getVersion() + + this.dbVersion = dbConfig.configValue + this.appVersion = applicationVersion + + if ( dbConfig.configValue != applicationVersion ) { + + try { + + + val versionNumber: String = applicationVersion.replace(".", "_") + val fileName = "update_$versionNumber.sql" + val path = "./data/db/" + val file2Update = path+fileName + + var sqlRows = "" + File(file2Update).forEachLine { + sqlRows += it + if ( sqlRows.contains(";") ) { + execSQL(sqlRows) + sqlRows = "" + } + } + this.connection.commit() + logger.info("Database has been updated to $applicationVersion" ) + } catch (exception: Exception) { + logger.info("Database exception of $applicationVersion: " + exception.message ) + this.connection.rollback() + } + } + + } + + fun execSQL( sql: String ) { + + if (! this.initialized ) { + this.getConnection() + } + + with(this.connection) { + createStatement().execute(sql) + //commit() + } + } + + fun execQuery( sql: String ): ResultSet { + if (! this.initialized ) { + this.getConnection() + } + + return connection.createStatement().executeQuery(sql) + } + + private fun getConnection(): Connection { + val connectionProps = Properties() + connectionProps["user"] = this.properties.getDatasourceUsername() + connectionProps["password"] = this.properties.getDatasourcePassword() + this.connection = DriverManager.getConnection(this.properties.getDatasourceUrl(), connectionProps) + this.connection.autoCommit = false + this.initialized = true + return this.connection + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/controller/ExerciesController.kt b/src/main/kotlin/com/aitrainer/api/controller/ExerciseController.kt similarity index 92% rename from src/main/kotlin/com/aitrainer/api/controller/ExerciesController.kt rename to src/main/kotlin/com/aitrainer/api/controller/ExerciseController.kt index 36da824..adda633 100644 --- a/src/main/kotlin/com/aitrainer/api/controller/ExerciesController.kt +++ b/src/main/kotlin/com/aitrainer/api/controller/ExerciseController.kt @@ -8,7 +8,7 @@ import javax.validation.Valid @RestController @RequestMapping("/api") -class ExerciesController(private val exercisesRepository: ExercisesRepository) { +class ExerciseController(private val exercisesRepository: ExercisesRepository) { @GetMapping("/exercises/{id}") fun getExerciseById(@PathVariable(value = "id") exerciseId: Long): ResponseEntity { @@ -33,7 +33,7 @@ class ExerciesController(private val exercisesRepository: ExercisesRepository) { val updatedExercises: Exercises = existingExercises.copy( exerciseTypeId = newExercises.exerciseTypeId, customerId = newExercises.customerId, - datetimeExercise = newExercises.datetimeExercise, + dateAdd = newExercises.dateAdd, quantity = newExercises.quantity, restTime = newExercises.restTime ) diff --git a/src/main/kotlin/com/aitrainer/api/controller/ExerciseControllerAspect.kt b/src/main/kotlin/com/aitrainer/api/controller/ExerciseControllerAspect.kt new file mode 100644 index 0000000..02089ed --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/controller/ExerciseControllerAspect.kt @@ -0,0 +1,35 @@ +package com.aitrainer.api.controller + +import com.aitrainer.api.ApiApplication +import com.aitrainer.api.repository.ConfigurationRepository +import org.aspectj.lang.annotation.Aspect +import org.aspectj.lang.annotation.Before +import org.aspectj.lang.annotation.Pointcut +import org.slf4j.LoggerFactory +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.stereotype.Component + +@Component +@Suppress("unused") +@Aspect +class ExerciseControllerAspect { + + private val logger = LoggerFactory.getLogger(ApiApplication::class.simpleName) + + @Autowired + private lateinit var configurationRepository: ConfigurationRepository + @Autowired + private lateinit var properties: ApplicationProperties + + @Suppress("unused") + @Pointcut("execution(* com.aitrainer.api.controller.ExerciseController.*())") + fun exerciseControllerAspect() { + } + + @Before("exerciseControllerAspect()") + fun loggingAop() { + Singleton.checkDBUpdate(configurationRepository, properties) + } + + +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/controller/ExerciseTypeControllerAspect.kt b/src/main/kotlin/com/aitrainer/api/controller/ExerciseTypeControllerAspect.kt new file mode 100644 index 0000000..67531b3 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/controller/ExerciseTypeControllerAspect.kt @@ -0,0 +1,34 @@ +package com.aitrainer.api.controller + +import com.aitrainer.api.ApiApplication +import com.aitrainer.api.repository.ConfigurationRepository +import org.aspectj.lang.annotation.Around +import org.aspectj.lang.annotation.Aspect +import org.aspectj.lang.annotation.Before +import org.aspectj.lang.annotation.Pointcut +import org.slf4j.LoggerFactory +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.stereotype.Component + +@Suppress("unused") +@Aspect +@Component +class ExerciseTypeControllerAspect { + private val logger = LoggerFactory.getLogger(ApiApplication::class.simpleName) + + @Autowired + private lateinit var configurationRepository: ConfigurationRepository + @Autowired + private lateinit var properties: ApplicationProperties + + @Suppress("unused") + @Pointcut("execution(* com.aitrainer.api.controller.ExerciseTypeController.*())") + fun exerciseTypeControllerAspect() { + } + + @Before("exerciseTypeControllerAspect()") + fun loggingAop() { + Singleton.checkDBUpdate(configurationRepository, properties) + } + +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/model/Configuration.kt b/src/main/kotlin/com/aitrainer/api/model/Configuration.kt new file mode 100644 index 0000000..0370a6c --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/model/Configuration.kt @@ -0,0 +1,21 @@ +package com.aitrainer.api.model + +import javax.persistence.Entity +import javax.persistence.GeneratedValue +import javax.persistence.GenerationType +import javax.persistence.Id +import javax.validation.constraints.NotBlank +import javax.validation.constraints.Null + +@Entity +data class Configuration ( + + + @get: NotBlank var configKey: String = "", + @get: NotBlank var configValue: String = "", + var dateAdd: String, + var dateChange: String = "", + + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + val configuration_id: Long = 0 +) diff --git a/src/main/kotlin/com/aitrainer/api/model/Customer.kt b/src/main/kotlin/com/aitrainer/api/model/Customer.kt index d932a5d..490cd5a 100644 --- a/src/main/kotlin/com/aitrainer/api/model/Customer.kt +++ b/src/main/kotlin/com/aitrainer/api/model/Customer.kt @@ -16,6 +16,10 @@ data class Customer ( var age: Int = 0, var sex: String = "m", var active: String = "N", + var dateAdd: String? = null, + var dateChange: String? = null, + var dataPolicyAllowed: Int = 0, + var admin: Int = 0, @Id @GeneratedValue(strategy = GenerationType.IDENTITY) val customer_id: Long = 0 diff --git a/src/main/kotlin/com/aitrainer/api/model/CustomerInformation.kt b/src/main/kotlin/com/aitrainer/api/model/CustomerInformation.kt new file mode 100644 index 0000000..493ada5 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/model/CustomerInformation.kt @@ -0,0 +1,21 @@ +package com.aitrainer.api.model + +import javax.persistence.Entity +import javax.persistence.GeneratedValue +import javax.persistence.GenerationType +import javax.persistence.Id +import javax.validation.constraints.NotBlank + +@Entity +class CustomerInformation ( + @get: NotBlank var title: String = "", + var description: String = "", + + var dateAdd: String? = null, + var displayBegin: String? = null, + var displayEnd: String? = null, + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + val customerInformationId: Long = 0 +) \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/model/Exercises.kt b/src/main/kotlin/com/aitrainer/api/model/Exercises.kt index 6770c95..d8a1d88 100644 --- a/src/main/kotlin/com/aitrainer/api/model/Exercises.kt +++ b/src/main/kotlin/com/aitrainer/api/model/Exercises.kt @@ -11,9 +11,10 @@ import javax.validation.constraints.Null data class Exercises ( @get: NonNull var exerciseTypeId: Long = 0, @get: NonNull var customerId: Long = 0, - @get: NonNull var datetimeExercise: String? = null, + @get: NonNull var dateAdd: String? = null, @get: NonNull var quantity: Int = 0, @get: Null var restTime: Int?, // in seconds + @get: NonNull var unit: String? = null, @Id @GeneratedValue(strategy = GenerationType.IDENTITY) val exerciseId: Long = 0 diff --git a/src/main/kotlin/com/aitrainer/api/repository/ConfigurationRepository.kt b/src/main/kotlin/com/aitrainer/api/repository/ConfigurationRepository.kt new file mode 100644 index 0000000..30383c5 --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/repository/ConfigurationRepository.kt @@ -0,0 +1,10 @@ +package com.aitrainer.api.repository + +import com.aitrainer.api.model.Configuration +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.stereotype.Repository + +@Repository +interface ConfigurationRepository : JpaRepository { + fun findByConfigKey( key: String ):Configuration +} \ No newline at end of file diff --git a/src/main/kotlin/com/aitrainer/api/repository/CustomerInformationRepository.kt b/src/main/kotlin/com/aitrainer/api/repository/CustomerInformationRepository.kt new file mode 100644 index 0000000..3e3f87f --- /dev/null +++ b/src/main/kotlin/com/aitrainer/api/repository/CustomerInformationRepository.kt @@ -0,0 +1,11 @@ +package com.aitrainer.api.repository + +import com.aitrainer.api.model.CustomerInformation +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.stereotype.Repository + +@Repository +interface CustomerInformationRepository: JpaRepository { + fun findByDisplayBeginLessThanAndDisplayEndGreaterThan( dateTimeBegin: String, dateTimeEnd: String ): + List +} \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index a43762e..c5131fe 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -11,5 +11,8 @@ spring.datasource.password = andio2009 # The SQL dialect makes Hibernate generate better SQL for the chosen database spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect + logging.config=classpath:logback-spring.xml -logging.file=logs \ No newline at end of file +logging.file=logs + +application.version=0.0.2 \ No newline at end of file diff --git a/src/test/kotlin/com/aitrainer/api/test/AitrainerDBTest.kt b/src/test/kotlin/com/aitrainer/api/test/AitrainerDBTest.kt deleted file mode 100644 index 6450923..0000000 --- a/src/test/kotlin/com/aitrainer/api/test/AitrainerDBTest.kt +++ /dev/null @@ -1,49 +0,0 @@ -package com.aitrainer.api.test - -import org.springframework.beans.factory.annotation.Autowired -import java.sql.Connection -import java.sql.DriverManager -import java.util.* -import kotlin.test.assertNotNull -import kotlin.test.assertTrue - - -class AitrainerDBTest(configuration: ApplicationConfiguration) { - - - @Autowired - private lateinit var username: String - private lateinit var password: String - private lateinit var datasourceUrl: String - private lateinit var conn: Connection - private val conf: ApplicationConfiguration = configuration - - fun initDB() { - this.username = this.conf.username.orEmpty() - this.password = this.conf.password.orEmpty() - this.datasourceUrl = this.conf.url.orEmpty() - assertTrue ("username should not be empty") { this.username.isNotEmpty() } - assertTrue ("password should not be empty") { this.password.isNotEmpty() } - assertTrue ("url should not be empty") { this.datasourceUrl.isNotEmpty() } - - this.getConnection() - - assertNotNull({this.conn}, "MySQL connection should not be null") - } - - - - /** - * This method makes a connection to MySQL Server - * In this example, MySQL Server is running in the local host (so 127.0.0.1) - * at the standard port 3306 - */ - private fun getConnection() { - val connectionProps = Properties() - connectionProps["user"] = this.username - connectionProps["password"] = this.password - Class.forName("com.mysql.cj.jdbc.Driver").getDeclaredConstructor().newInstance() - this.conn = DriverManager.getConnection(this.datasourceUrl, connectionProps) - } - -} \ No newline at end of file diff --git a/src/test/kotlin/com/aitrainer/api/test/ApplicationConfiguration.kt b/src/test/kotlin/com/aitrainer/api/test/ApplicationConfiguration.kt deleted file mode 100644 index 8d378d5..0000000 --- a/src/test/kotlin/com/aitrainer/api/test/ApplicationConfiguration.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.aitrainer.api.test - -import org.springframework.boot.context.properties.ConfigurationProperties -import org.springframework.stereotype.Component - -@Component -@ConfigurationProperties(prefix = "spring.datasource") -class ApplicationConfiguration { - var username: String? = null - var password: String? = null - var url: String? = null -} \ No newline at end of file diff --git a/src/test/kotlin/com/aitrainer/api/test/ApplicationStartTest.kt b/src/test/kotlin/com/aitrainer/api/test/ApplicationStartTest.kt new file mode 100644 index 0000000..3beb06c --- /dev/null +++ b/src/test/kotlin/com/aitrainer/api/test/ApplicationStartTest.kt @@ -0,0 +1,34 @@ +package com.aitrainer.api.test + +import com.aitrainer.api.controller.ApplicationProperties +import com.aitrainer.api.controller.Singleton +import com.aitrainer.api.repository.ConfigurationRepository +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest +import java.sql.ResultSet +import kotlin.test.assertEquals + +@SpringBootTest +class ApplicationStartTest { + + @Autowired + private lateinit var configurationRepository: ConfigurationRepository + @Autowired + private lateinit var properties: ApplicationProperties + + @Test + fun testDBCheck() { + Singleton.checkDBUpdate(this.configurationRepository, this.properties) + + var foundTable = false + val rs: ResultSet = Singleton.execQuery("Show tables;") + while ( rs.next() ) { + if ( rs.getString("tables_in_aitrainer") == "customer_information" ) { + foundTable = true + } + } + + assertEquals(foundTable, true) + } +} \ No newline at end of file diff --git a/src/test/kotlin/com/aitrainer/api/test/ConfigurationTest.kt b/src/test/kotlin/com/aitrainer/api/test/ConfigurationTest.kt new file mode 100644 index 0000000..d7540b5 --- /dev/null +++ b/src/test/kotlin/com/aitrainer/api/test/ConfigurationTest.kt @@ -0,0 +1,31 @@ +package com.aitrainer.api.test + +import com.aitrainer.api.controller.ConfigurationController +import com.aitrainer.api.model.Configuration +import com.aitrainer.api.repository.ConfigurationRepository +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest +import kotlin.test.assertEquals + +@SpringBootTest +class ConfigurationTest { + + @Autowired + private lateinit var configurationRepository: ConfigurationRepository + private lateinit var configurationController: ConfigurationController + + @Test + fun testUpdateConfig() { + val config: Configuration = configurationRepository.findByConfigKey("db_version") + config.configValue = "0.0.2" + + configurationController = ConfigurationController(configurationRepository) + val updatedConfig: Configuration = configurationController.updateConfiguration(config) + assertEquals(updatedConfig.configValue, "0.0.2") + + val foundConfig: Configuration = configurationRepository.findByConfigKey("db_version") + assertEquals(foundConfig.configValue, "0.0.2") + + } +} \ No newline at end of file diff --git a/src/test/kotlin/com/aitrainer/api/test/CustomerInformationTest.kt b/src/test/kotlin/com/aitrainer/api/test/CustomerInformationTest.kt new file mode 100644 index 0000000..0666d40 --- /dev/null +++ b/src/test/kotlin/com/aitrainer/api/test/CustomerInformationTest.kt @@ -0,0 +1,24 @@ +package com.aitrainer.api.test + +import com.aitrainer.api.model.CustomerInformation +import com.aitrainer.api.repository.CustomerInformationRepository +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest +import kotlin.test.assertEquals + +@SpringBootTest +class CustomerInformationTest { + + @Autowired + private lateinit var customerInformationRepository: CustomerInformationRepository + + @Test + fun getActiveCustomerInformation() { + val dateTime = "2020-06-01 09:00:00" + val info: List = this.customerInformationRepository. + findByDisplayBeginLessThanAndDisplayEndGreaterThan(dateTime, dateTime ) + assertEquals(info.size, 2) + assertEquals(info.first().title, "Fekvőtámasz világcsúcs") + } +} \ No newline at end of file diff --git a/src/test/kotlin/com/aitrainer/api/test/ExerciseTest.kt b/src/test/kotlin/com/aitrainer/api/test/ExerciseTest.kt index 3196656..bbc2a55 100644 --- a/src/test/kotlin/com/aitrainer/api/test/ExerciseTest.kt +++ b/src/test/kotlin/com/aitrainer/api/test/ExerciseTest.kt @@ -33,7 +33,8 @@ class ExerciseTest { exerciseTypeId = 3, customerId = 11, quantity = 100, - datetimeExercise = "2020-05-13 04:32:00", + dateAdd = "2020-05-13 04:32:00", + unit = "repeat", restTime = null ) val exerciseNew = exerciseRepository.save(exercise) diff --git a/src/test/kotlin/com/aitrainer/api/test/PropertiesTest.kt b/src/test/kotlin/com/aitrainer/api/test/PropertiesTest.kt new file mode 100644 index 0000000..26130b1 --- /dev/null +++ b/src/test/kotlin/com/aitrainer/api/test/PropertiesTest.kt @@ -0,0 +1,27 @@ +package com.aitrainer.api.test + +import com.aitrainer.api.controller.ApplicationProperties +import org.springframework.boot.test.context.SpringBootTest +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import kotlin.test.assertEquals + +@SpringBootTest +class PropertiesTest { + + @Autowired + private lateinit var properties: ApplicationProperties + + @Test + fun testProperties() { + val version: String = properties.getVersion() + assertEquals(version, "0.0.2") + } + + @Test + fun testDatasourceUrl() { + val url: String = properties.getDatasourceUrl() + assertEquals(url, "jdbc:mysql://localhost:3306/aitrainer?serverTimezone=CET&useSSL=false&characterEncoding=UTF-8&allowMultiQueries=true") + } + +} \ No newline at end of file