From 83897285e489672ccf16c4af2f79ef312634fad0 Mon Sep 17 00:00:00 2001 From: Swordsteel Date: Wed, 10 Sep 2025 09:49:42 +0200 Subject: [PATCH] project setup - update README.md - setup tls - update gradle.properties with docker tls ports - update application.yml - disable tls in develop - set docker values - add default tls values - add keystore.p12 - setup postgres - update application.yml with defualt values - add 000-initizalise.sql - add postgres dependencies and config - add docker compose development - add actuator.http - add http environment - update name and readme for service --- README.md | 22 ++++++--- build.gradle.kts | 7 ++- development-compose.yml | 24 ++++++++++ gradle.properties | 5 ++- http/actuator.http | 3 ++ http/http-client.env.json | 11 +++++ instructions.md | 20 +++++++++ settings.gradle.kts | 2 +- sql/initial/000-initizalise.sql | 64 +++++++++++++++++++++++++++ src/main/resources/application.yml | 27 +++++++++++ src/main/resources/cert/keystore.p12 | Bin 0 -> 2598 bytes 11 files changed, 177 insertions(+), 8 deletions(-) create mode 100644 development-compose.yml create mode 100644 http/actuator.http create mode 100644 http/http-client.env.json create mode 100644 instructions.md create mode 100644 sql/initial/000-initizalise.sql create mode 100644 src/main/resources/cert/keystore.p12 diff --git a/README.md b/README.md index 7dbfc45..872db93 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,20 @@ -# {service} +# Basic Banking -{description} +This Monolith is pretend to be different services, it also Postgres 18rc1 to have access to UUIDv7. ## Properties For Deployment -| Name | Required | Information | -|------------------------|:--------:|-------------------------| -| spring.profiles.active | ✔ | Spring Boot environment | +| Name | Required | Information | +|-------------------------------|:--------:|-------------------------| +| spring.profiles.active | ✔ | Spring Boot environment | +| spring.r2dbc.url | ✔ | Postgres host url | +| spring.r2dbc.username | ✓ | Postgres username | +| spring.r2dbc.password | ✱ | Postgres password | +| server.port | | HTTP port | +| server.ssl.enabled | | HTTP Enable SSL | +| server.ssl.key-store | ✗ | HTTP Keystore | +| server.ssl.key-store-type | | HTTP Cert Type | +| server.ssl.key-store-password | ✱ | HTTP Cert Pass | *Required:* @@ -14,6 +22,10 @@ - *✗ mounted file.* - *✱ need to be stored as secret.* +## Development + +Use `development-compose.yml` to set up needed external dependencies. + ## Releasing Service Run release pipeline from `master` branch. diff --git a/build.gradle.kts b/build.gradle.kts index d1695fc..93f835f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,14 +12,19 @@ dependencies { implementation(aa.kotlin.reflect) implementation(aa.kotlinx.coroutines) implementation(aa.springboot.starter.actuator) + implementation(aa.springboot.starter.r2dbc) implementation(aa.springboot.starter.webflux) + runtimeOnly(aa.postgresql) + runtimeOnly(aa.postgresql.r2dbc) + testImplementation(aa.kotlin.junit5) testImplementation(aa.kotlinx.coroutines.test) + testImplementation(aa.mockk) testImplementation(aa.springboot.starter.test) testRuntimeOnly(aa.junit.platform.launcher) } group = "ltd.lulz" -description = "service template" +description = "service basic banking" diff --git a/development-compose.yml b/development-compose.yml new file mode 100644 index 0000000..fa3ffd7 --- /dev/null +++ b/development-compose.yml @@ -0,0 +1,24 @@ +name: develop + +networks: + develop: + name: develop + external: true + +volumes: + postgres: + +services: + postgres: + image: postgres:18rc1-alpine + container_name: postgres + restart: unless-stopped + environment: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: password + ports: + - 5432:5432 + networks: + - develop + volumes: + - postgres:/var/lib/postgresql/data diff --git a/gradle.properties b/gradle.properties index 918eb4b..62ca361 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,5 @@ version=0.1.0-SNAPSHOT -catalog=0.1.0 +catalog=0.2.0-SNAPSHOT +docker.port.expose=8443 +container.port.expose=8443 +container.port.host=8443 diff --git a/http/actuator.http b/http/actuator.http new file mode 100644 index 0000000..0058446 --- /dev/null +++ b/http/actuator.http @@ -0,0 +1,3 @@ +### Actuator + +GET {{url}}/actuator diff --git a/http/http-client.env.json b/http/http-client.env.json new file mode 100644 index 0000000..26984d1 --- /dev/null +++ b/http/http-client.env.json @@ -0,0 +1,11 @@ +{ + "develop": { + "url": "http://localhost:8080" + }, + "docker": { + "url": "https://localhost:8443" + }, + "kubernetes": { + "url": "https://10.0.0.0" + } +} diff --git a/instructions.md b/instructions.md new file mode 100644 index 0000000..bc72022 --- /dev/null +++ b/instructions.md @@ -0,0 +1,20 @@ +# Senior Engineer Test + +### **Develop a service that simulates basic banking operations in a programming language of your choice. This service will manage accounts, process deposits, withdrawals, and transfers between accounts.** + +### The system should be designed reflecting real-world constraints of a bank. + +## Requirements: + +1. A class or set of functions that allow: + * Account creation: Allow users to create an account with an initial deposit. + * Deposit: Enable users to deposit money into their account. + * Withdrawal: Allow users to withdraw money from their account, ensuring that overdrafts are not allowed. + * Transfer: Enable transferring funds between accounts. + * Account balance: Provide the ability to check the account balance. +2. Database: + * In-memory data storage will suffice, no need to have a database alongside the project, but you can add one at your discretion + +The word “service” here is used in a “software component/module” rather “deployable unit with an API” sense, no need to provide API for it. + +## Feel free to take as along as you need to complete the exercise. This will be used as a base for a follow-up pair programming session. diff --git a/settings.gradle.kts b/settings.gradle.kts index a4d35d0..7aa7f63 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -34,4 +34,4 @@ pluginManagement.repositories { gradlePluginPortal() } -rootProject.name = "service" +rootProject.name = "basic-banking" diff --git a/sql/initial/000-initizalise.sql b/sql/initial/000-initizalise.sql new file mode 100644 index 0000000..0e59659 --- /dev/null +++ b/sql/initial/000-initizalise.sql @@ -0,0 +1,64 @@ +-- Role: role_administrator +-- DROP ROLE IF EXISTS role_administrator; + +CREATE ROLE role_owner; + + +-- Role: role_service +-- DROP ROLE IF EXISTS role_service; + +CREATE ROLE role_service; + + +-- Role: role_maintainer +-- DROP ROLE IF EXISTS role_maintainer; + +CREATE ROLE role_maintainer; + + +-- Role: support_role +-- DROP ROLE IF EXISTS support_role; + +CREATE ROLE role_support; + + +-- User: services +-- DROP USER IF EXISTS services; + +CREATE USER service WITH PASSWORD 'password'; + +-- Assign role to the user +GRANT role_service TO service; + + +-- User: user_maintainer +-- DROP USER IF EXISTS user_maintainer; + +CREATE USER user_maintainer WITH PASSWORD 'password'; + +-- Assign role to the user +GRANT role_maintainer TO user_maintainer; + + +-- User: user_support +-- DROP USER IF EXISTS user_support; + +CREATE USER user_support WITH PASSWORD 'password'; + +-- Assign role to the user +GRANT role_support TO user_support; + + +-- Database: basic_banking +-- DROP DATABASE IF EXISTS basic_banking; + +CREATE DATABASE basic_banking + WITH + OWNER = role_owner + ENCODING = 'UTF8' + TABLESPACE = pg_default + CONNECTION LIMIT = -1 + IS_TEMPLATE = False; + +COMMENT ON DATABASE basic_banking + IS 'Database for basic banking, registered account and transactions.'; diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 045a197..0dc690b 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -24,6 +24,13 @@ management: exposure: include: "health,info" +server: + port: 8443 + ssl: + enabled: true + key-store: classpath:cert/keystore.p12 + key-store-type: PKCS12 + --- ########################### ### Develop environment ### @@ -32,6 +39,16 @@ spring: config: activate: on-profile: develop + r2dbc: + url: r2dbc:postgresql://localhost:5432/basic_banking + username: service + password: password + +server: + port: 8080 + ssl: + enabled: false +# key-store-password: password --- ########################## @@ -41,6 +58,14 @@ spring: config: activate: on-profile: docker + r2dbc: + url: r2dbc:postgresql://postgres:5432/basic_banking + username: service + password: password + +server: + ssl: + key-store-password: password --- ############################## @@ -50,3 +75,5 @@ spring: config: activate: on-profile: kubernetes + r2dbc: + url: r2dbc:postgresql://postgres:5432/basic_banking diff --git a/src/main/resources/cert/keystore.p12 b/src/main/resources/cert/keystore.p12 new file mode 100644 index 0000000000000000000000000000000000000000..38735adc828a6b4bccf21bd75fa2d263071eb282 GIT binary patch literal 2598 zcma)8X*d*&7M|5QwlS87hO!$5F_uEs`9xHW zNQ`x-a21*aZTPPc^d*D@Ejfh?PbHU*`9D=KCLkz>1l2qRFQJ`(RX|zLIJEL_7lxLC zATm&Ku?gW9-Bz;#H73C~TBhQF1Q1A!9Rx(8VRQ`t?g(Op0?-0reM5#3jwO)AXe5rjd&PJd>1a;AjKAQ}BhN&eD1 zKk_47<+S3Qnrkg@KpCdRQ4?$-9<;5=#rckZe)C+jB<}E&(~wHd7b$fCX&f;zP$Z$? zIHqJ`?PGC`;vNm%A@TERL;Od^DE%@%e=tHI*FrWSs`Zg`Yhw0S2`?l~uvgXIebru7 z`W5_$^*B!sw4Q_dm?y3>q#erf>MbJmO`{wVPAM(Up4iIQ0@>cB(OxI*fX^idn}at# z-zhP;;>46W`Xmvo5*cxApzdp8b->Kinmi(WcCN3hC=YLVH+~H^<2gyS{zKhz{7BM> zk9Ad{otTl(A%fz~+@kdl3QReEjNIPKyTn+Uliok*;>$7XrW|wS%}r}o&VsPm^yGbO zNOfDi--C2DDoXUjJ7yTxh+?=%PATNs8xM9mdK^r04eR`ve3PP5LbAXqkJf-&1(T~D z3?7AWHVfEph+kA|a~!Z%sY}7F$d3RkYR1&rGu@up0qS`dBNDoSUo-vse1)Hf-w(eRl{~#-46!Up` z&h76cinJb`Ld*9&f_MHGgfl?`L=Jg zHP443_vaR+y6aCDrq`=CoLIihrF&ZC`n|pRb`?WG`Wg8RE|zdKNF*;bY<+7YEVdd~ zUs3fh+kQ4Kj5s!SRg%?nm6F+7CWg740C2z&bYu}ajgaY{;{ zzE!@GKO_S$JWuHy9bvT$J^!-6`2F=w2|2vg!EFXH^@J#1X5+^Pah5Bvpo@R7$|U2r zy`i@d^&pm9!v?X?78$;jMjoF|@VDR>;X|7vezo-c>7z+Rq!(FH@8QK|6GU&c&;C;F zqUSMVP4!Bmk8}w?j{9tT>MX8KO+2|**#Jy@>?x!4XNa2j? zVD9#3iSY~UWmPnrJ|ZAEtXx*q_%h;kPyH~{IYq+2y~OE3RGn1S4b!G`3EPw3%%?YP z<*uP6e$gc(Lhh^}AHW`92k-^B0UQ9Rf7zY@!l~y8a6t?GPUVtAK;Wis9!^L(j3P!+ z4uiRh0)#7nJ z<=VDZ+l93=ta3i$2Zb5&nzjPIpPN-fEOyqV{j}TIV6I+X4$dnThHx9?t|M=KM`P9p z9G~z0 zxsIZLuivHK7o+7LsaarbS~pbt^TJf^_-?p-)60+kLiYp-*7f=4Ck~zc!{C|*KWKJR zrp>o_d3^5MzwvC|HR_4nrP)}CAbx0@>P53y2A~qup*8DRrbK?!t_@fCa3Wgs3?8Y!1e|Ncn-^qVn9wZyr&dbPQBuE=U zT~8fX^0WwxXtZGHdGzI8XNAIe9z)w---}V@P4i)9PqdaDta`AoD?v6Smm2?M(^h-?}x@%mdn2v9r|2%BT;lwC$+J)h4k{7->@uJ}Iy%r~B0 literal 0 HcmV?d00001