├── .env.example
├── .gitignore
├── docker-compose.yml
├── file-management
├── .editorconfig
├── .env.example
├── .gitattributes
├── .gitignore
├── Dockerfile
├── artisan
├── bootstrap
│ ├── app.php
│ ├── cache
│ │ └── .gitignore
│ └── providers.php
├── composer.json
├── composer.lock
├── config
│ ├── kafka.php
│ └── services.php
├── database
│ └── .gitignore
├── docker
│ ├── php.ini
│ ├── start-container
│ └── supervisord.conf
├── public
│ ├── .htaccess
│ ├── favicon.ico
│ ├── index.php
│ └── robots.txt
├── src
│ ├── Actions
│ │ ├── DownloadFile.php
│ │ ├── GetFiles.php
│ │ └── UploadFile.php
│ ├── Clients
│ │ ├── LicenseClient.php
│ │ └── S3Client.php
│ ├── Commands
│ │ └── ConsumeMessages.php
│ ├── Exceptions
│ │ ├── DailyLimitException.php
│ │ ├── EntityTooLargeException.php
│ │ ├── LicenseExpiredException.php
│ │ └── QuotaReachedException.php
│ ├── Handlers
│ │ └── KafkaMessageHandler.php
│ ├── Jobs
│ │ └── CreateNewBucket.php
│ ├── Middlewares
│ │ └── EnsureTokenIsValid.php
│ ├── Migrations
│ │ ├── 2024_06_07_020305_create_jobs_table.php
│ │ ├── 2024_06_07_020313_create_failed_jobs_table.php
│ │ ├── 2024_06_07_054155_create_files_table.php
│ │ └── 2024_06_07_064602_create_cache_table.php
│ ├── Models
│ │ ├── File.php
│ │ └── Limits.php
│ ├── Providers
│ │ ├── AppServiceProvider.php
│ │ └── RouteServiceProvider.php
│ ├── Resources
│ │ └── FileResource.php
│ └── Routes
│ │ └── ApiV1.php
└── storage
│ ├── app
│ ├── .gitignore
│ └── public
│ │ └── .gitignore
│ ├── framework
│ ├── .gitignore
│ ├── cache
│ │ ├── .gitignore
│ │ └── data
│ │ │ └── .gitignore
│ ├── sessions
│ │ └── .gitignore
│ ├── testing
│ │ └── .gitignore
│ └── views
│ │ └── .gitignore
│ └── logs
│ └── .gitignore
├── license
├── .editorconfig
├── .env.example
├── .gitattributes
├── .gitignore
├── Dockerfile
├── artisan
├── bootstrap
│ ├── app.php
│ ├── cache
│ │ └── .gitignore
│ └── providers.php
├── composer.json
├── composer.lock
├── config
│ └── kafka.php
├── docker
│ ├── php.ini
│ ├── start-container
│ └── supervisord.conf
├── public
│ ├── .htaccess
│ ├── favicon.ico
│ ├── index.php
│ └── robots.txt
├── src
│ ├── Actions
│ │ ├── GetLicenseOfUser.php
│ │ ├── LicenseUpdated.php
│ │ └── MeLicense.php
│ ├── Commands
│ │ └── ConsumeMessages.php
│ ├── Handlers
│ │ └── KafkaMessageHandler.php
│ ├── Middlewares
│ │ └── EnsureTokenIsValid.php
│ ├── Migrations
│ │ ├── 2024_06_06_135026_create_licenses_table.php
│ │ ├── 2024_06_07_021508_create_failed_jobs_table.php
│ │ └── 2024_06_07_021519_create_jobs_table.php
│ ├── Models
│ │ ├── License.php
│ │ └── LicenseType.php
│ ├── Providers
│ │ ├── AppServiceProvider.php
│ │ ├── DatabaseServiceProvider.php
│ │ └── RouteServiceProvider.php
│ ├── Resources
│ │ └── LicenseResource.php
│ └── Routes
│ │ └── ApiV1.php
└── storage
│ ├── app
│ ├── .gitignore
│ └── public
│ │ └── .gitignore
│ ├── framework
│ ├── .gitignore
│ ├── cache
│ │ ├── .gitignore
│ │ └── data
│ │ │ └── .gitignore
│ ├── sessions
│ │ └── .gitignore
│ ├── testing
│ │ └── .gitignore
│ └── views
│ │ └── .gitignore
│ └── logs
│ └── .gitignore
├── notification
├── .editorconfig
├── .env.example
├── .gitattributes
├── .gitignore
├── Dockerfile
├── artisan
├── bootstrap
│ ├── app.php
│ ├── cache
│ │ └── .gitignore
│ └── providers.php
├── composer.json
├── composer.lock
├── config
│ ├── kafka.php
│ └── mail.php
├── database
│ └── .gitignore
├── docker
│ ├── php.ini
│ ├── start-container
│ └── supervisord.conf
├── src
│ ├── Commands
│ │ └── ConsumeMessages.php
│ ├── Handlers
│ │ └── KafkaMessageHandler.php
│ ├── Jobs
│ │ └── SendWelcomeEmail.php
│ ├── Mail
│ │ └── WelcomeEmail.php
│ ├── Migrations
│ │ ├── 2024_06_07_012217_create_jobs_table.php
│ │ └── 2024_06_07_013016_create_failed_jobs_table.php
│ └── Providers
│ │ └── AppServiceProvider.php
├── storage
│ ├── app
│ │ ├── .gitignore
│ │ └── public
│ │ │ └── .gitignore
│ ├── framework
│ │ ├── .gitignore
│ │ ├── cache
│ │ │ ├── .gitignore
│ │ │ └── data
│ │ │ │ └── .gitignore
│ │ ├── sessions
│ │ │ └── .gitignore
│ │ ├── testing
│ │ │ └── .gitignore
│ │ └── views
│ │ │ └── .gitignore
│ └── logs
│ │ └── .gitignore
└── views
│ └── emails
│ ├── welcome-plaintext.blade.php
│ └── welcome.blade.php
├── readme.md
├── secrets
└── .gitignore
└── security
├── .editorconfig
├── .env.example
├── .gitattributes
├── .gitignore
├── Dockerfile
├── artisan
├── bootstrap
├── app.php
├── cache
│ └── .gitignore
└── providers.php
├── composer.json
├── composer.lock
├── config
└── kafka.php
├── database
├── .gitignore
└── migrations
│ ├── 0001_01_01_000000_create_users_table.php
│ ├── 0001_01_01_000001_create_cache_table.php
│ ├── 0001_01_01_000002_create_jobs_table.php
│ ├── 2024_06_04_130737_create_oauth_personal_access_clients_table.php
│ ├── 2024_06_04_130738_create_oauth_refresh_tokens_table.php
│ ├── 2024_06_04_130739_create_oauth_clients_table.php
│ ├── 2024_06_04_130740_create_oauth_access_tokens_table.php
│ └── 2024_06_04_130741_create_oauth_auth_codes_table.php
├── docker
├── php.ini
├── start-container
└── supervisord.conf
├── public
├── .htaccess
├── favicon.ico
├── index.php
└── robots.txt
├── src
├── Actions
│ ├── CreateNewUser.php
│ └── PublishUserCreatedMessage.php
├── Models
│ └── User.php
├── Providers
│ ├── AppServiceProvider.php
│ ├── AuthServiceProvider.php
│ └── RouteServiceProvider.php
└── Routes
│ └── ApiV1.php
└── storage
├── app
├── .gitignore
└── public
│ └── .gitignore
├── framework
├── .gitignore
├── cache
│ ├── .gitignore
│ └── data
│ │ └── .gitignore
├── sessions
│ └── .gitignore
├── testing
│ └── .gitignore
└── views
│ └── .gitignore
└── logs
└── .gitignore
/.env.example:
--------------------------------------------------------------------------------
1 | ZOOKEEPER_IMAGE=confluentinc/cp-zookeeper
2 | ZOOKEEPER_IMAGE_VERSION=7.6.1
3 |
4 | ZOONAVIGATOR_VERSION=1.1.2
5 |
6 | KAFKA_IMAGE=confluentinc/cp-kafka
7 | KAFKA_IMAGE_VERSION=7.6.1
8 |
9 | SCHEMA_REGISTRY_IMAGE=confluentinc/cp-schema-registry
10 | SCHEMA_REGISTRY_IMAGE_VERSION=7.6.1
11 |
12 | KAFKA_CONNECT_IMAGE=confluentinc/cp-kafka-connect
13 | KAFKA_CONNECT_IMAGE_VERSION=7.6.1
14 |
15 | MINIO_IMAGE_VERSION=RELEASE.2024-06-04T19-20-08Z.fips
16 | MINIO_USER=
17 | MINIO_PASSWORD=
18 |
19 | WWWUSER=1000
20 | WWWGROUP=1000
21 |
22 | APP_SECURITY_DB_IMAGE_VERSION=15
23 | APP_SECURITY_PORT=8082
24 | APP_SECURITY_XDEBUG_MODE=off
25 | APP_SECURITY_XDEBUG_CONFIG=-client_host=host.docker.internal
26 | APP_SECURITY_DB_PORT=5432
27 |
28 | APP_LICENSE_DB_IMAGE_VERSION=15
29 | APP_LICENSE_PORT=8083
30 | APP_LICENSE_XDEBUG_MODE=off
31 | APP_LICENSE_XDEBUG_CONFIG=-client_host=host.docker.internal
32 | APP_LICENSE_DB_PORT=5433
33 |
34 | APP_FILEMANAGEMENT_DB_IMAGE_VERSION=15
35 | APP_FILEMANAGEMENT_PORT=8084
36 | APP_FILEMANAGEMENT_XDEBUG_MODE=off
37 | APP_FILEMANAGEMENT_XDEBUG_CONFIG=-client_host=host.docker.internal
38 | APP_FILEMANAGEMENT_DB_PORT=5434
39 |
40 | APP_NOTIFICATION_DB_IMAGE_VERSION=15
41 | APP_NOTIFICATION_PORT=8085
42 | APP_NOTIFICATION_XDEBUG_MODE=off
43 | APP_NOTIFICATION_XDEBUG_CONFIG=-client_host=host.docker.internal
44 | APP_NOTIFICATION_DB_PORT=5435
45 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ### Project
2 | /.env
3 | /.env.backup
4 | /.env.production
5 |
6 | ### Intellij
7 | /.idea
8 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | services:
2 | security:
3 | build:
4 | context: ./security
5 | dockerfile: Dockerfile
6 | args:
7 | WWWGROUP: '${WWWGROUP}'
8 | extra_hosts:
9 | - 'host.docker.internal:host-gateway'
10 | ports:
11 | - '${APP_SECURITY_PORT:-8082}:80'
12 | env_file:
13 | - ./security/.env
14 | environment:
15 | WWWUSER: '${WWWUSER}'
16 | APP_IN_DOCKER: 1
17 | XDEBUG_MODE: '${APP_SECURITY_XDEBUG_MODE:-off}'
18 | XDEBUG_CONFIG: '${APP_SECURITY_XDEBUG_CONFIG:-client_host=host.docker.internal}'
19 | IGNITION_LOCAL_SITES_PATH: '${PWD}'
20 | volumes:
21 | - './security:/var/www/html'
22 | - './secrets:/tmp/secrets'
23 | networks:
24 | - security
25 | - backend
26 | - vpc
27 | depends_on:
28 | - security-db
29 | security-db:
30 | image: postgres:${APP_SECURITY_DB_IMAGE_VERSION}
31 | ports:
32 | - '${APP_SECURITY_DB_PORT:-5432}:5432'
33 | env_file:
34 | - ./security/.env
35 | environment:
36 | PGPASSWD: '${DB_PASSWORD:-secret}'
37 | POSTGRES_DB: '${DB_DATABASE:-security}'
38 | POSTGRES_USER: '${DB_USERNAME:-security}'
39 | POSTGRES_PASSWORD: '${DB_PASSWORD:-secret}'
40 | volumes:
41 | - security-db-data:/var/lib/postgresql/data
42 | networks:
43 | - security
44 | healthcheck:
45 | test: ["CMD", "pg_isready", "-q", "-d", "${DB_DATABASE:-security}", "-U", "${DB_USERNAME:-security}"]
46 | retries: 3
47 | timeout: 5s
48 | license:
49 | build:
50 | context: ./license
51 | dockerfile: Dockerfile
52 | args:
53 | WWWGROUP: '${WWWGROUP}'
54 | extra_hosts:
55 | - 'host.docker.internal:host-gateway'
56 | ports:
57 | - '${APP_LICENSE_PORT:-8083}:80'
58 | env_file:
59 | - ./license/.env
60 | environment:
61 | WWWUSER: '${WWWUSER}'
62 | APP_IN_DOCKER: 1
63 | XDEBUG_MODE: '${APP_LICENSE_XDEBUG_MODE:-off}'
64 | XDEBUG_CONFIG: '${APP_LICENSE_XDEBUG_CONFIG:-client_host=host.docker.internal}'
65 | IGNITION_LOCAL_SITES_PATH: '${PWD}'
66 | volumes:
67 | - './license:/var/www/html'
68 | - './secrets:/tmp/secrets'
69 | networks:
70 | - license
71 | - file-management
72 | - backend
73 | - vpc
74 | depends_on:
75 | - license-db
76 | license-db:
77 | image: postgres:${APP_LICENSE_DB_IMAGE_VERSION}
78 | ports:
79 | - '${APP_LICENSE_DB_PORT:-5433}:5432'
80 | env_file:
81 | - ./license/.env
82 | environment:
83 | PGPASSWD: '${DB_PASSWORD:-secret}'
84 | POSTGRES_DB: '${DB_DATABASE:-license}'
85 | POSTGRES_USER: '${DB_USERNAME:-license}'
86 | POSTGRES_PASSWORD: '${DB_PASSWORD:-secret}'
87 | volumes:
88 | - license-db-data:/var/lib/postgresql/data
89 | networks:
90 | - license
91 | healthcheck:
92 | test: ["CMD", "pg_isready", "-q", "-d", "${DB_DATABASE:-license}", "-U", "${DB_USERNAME:-license}"]
93 | retries: 3
94 | timeout: 5s
95 | file-management:
96 | build:
97 | context: ./file-management
98 | dockerfile: Dockerfile
99 | args:
100 | WWWGROUP: '${WWWGROUP}'
101 | extra_hosts:
102 | - 'host.docker.internal:host-gateway'
103 | ports:
104 | - '${APP_FILEMANAGEMENT_PORT:-8084}:80'
105 | env_file:
106 | - ./file-management/.env
107 | environment:
108 | WWWUSER: '${WWWUSER}'
109 | APP_IN_DOCKER: 1
110 | XDEBUG_MODE: '${APP_FILEMANAGEMENT_XDEBUG_MODE:-off}'
111 | XDEBUG_CONFIG: '${APP_FILEMANAGEMENT_XDEBUG_CONFIG:-client_host=host.docker.internal}'
112 | IGNITION_LOCAL_SITES_PATH: '${PWD}'
113 | volumes:
114 | - './file-management:/var/www/html'
115 | - './secrets:/tmp/secrets'
116 | networks:
117 | - file-management
118 | - license
119 | - backend
120 | - vpc
121 | depends_on:
122 | - file-management-db
123 | file-management-db:
124 | image: postgres:${APP_FILEMANAGEMENT_DB_IMAGE_VERSION}
125 | ports:
126 | - '${APP_FILEMANAGEMENT_DB_PORT:-5434}:5432'
127 | env_file:
128 | - ./file-management/.env
129 | environment:
130 | PGPASSWD: '${DB_PASSWORD:-secret}'
131 | POSTGRES_DB: '${DB_DATABASE:-filemanagement}'
132 | POSTGRES_USER: '${DB_USERNAME:-filemanagement}'
133 | POSTGRES_PASSWORD: '${DB_PASSWORD:-secret}'
134 | volumes:
135 | - file-management-db-data:/var/lib/postgresql/data
136 | networks:
137 | - file-management
138 | healthcheck:
139 | test: ["CMD", "pg_isready", "-q", "-d", "${DB_DATABASE:-filemanagement}", "-U", "${DB_USERNAME:-filemanagement}"]
140 | retries: 3
141 | timeout: 5s
142 | notification:
143 | build:
144 | context: ./notification
145 | dockerfile: Dockerfile
146 | args:
147 | WWWGROUP: '${WWWGROUP}'
148 | extra_hosts:
149 | - 'host.docker.internal:host-gateway'
150 | ports:
151 | - '${APP_NOTIFICATION_PORT:-8085}:80'
152 | env_file:
153 | - ./notification/.env
154 | environment:
155 | WWWUSER: '${WWWUSER}'
156 | APP_IN_DOCKER: 1
157 | XDEBUG_MODE: '${APP_NOTIFICATION_XDEBUG_MODE:-off}'
158 | XDEBUG_CONFIG: '${APP_NOTIFICATION_XDEBUG_CONFIG:-client_host=host.docker.internal}'
159 | IGNITION_LOCAL_SITES_PATH: '${PWD}'
160 | volumes:
161 | - './notification:/var/www/html'
162 | - './secrets:/tmp/secrets'
163 | networks:
164 | - notification
165 | - backend
166 | - vpc
167 | depends_on:
168 | - notification-db
169 | notification-db:
170 | image: postgres:${APP_NOTIFICATION_DB_IMAGE_VERSION}
171 | ports:
172 | - '${APP_NOTIFICATION_DB_PORT:-5435}:5432'
173 | env_file:
174 | - ./notification/.env
175 | environment:
176 | PGPASSWD: '${DB_PASSWORD:-secret}'
177 | POSTGRES_DB: '${DB_DATABASE:-notification}'
178 | POSTGRES_USER: '${DB_USERNAME:-notification}'
179 | POSTGRES_PASSWORD: '${DB_PASSWORD:-secret}'
180 | volumes:
181 | - notification-db-data:/var/lib/postgresql/data
182 | networks:
183 | - notification
184 | healthcheck:
185 | test: ["CMD", "pg_isready", "-q", "-d", "${DB_DATABASE:-notification}", "-U", "${DB_USERNAME:-notification}"]
186 | retries: 3
187 | timeout: 5s
188 | zoo1:
189 | image: ${ZOOKEEPER_IMAGE}:${ZOOKEEPER_IMAGE_VERSION}
190 | restart: unless-stopped
191 | ports:
192 | - "2181:2181"
193 | environment:
194 | ZOOKEEPER_SERVER_ID: 1
195 | ZOOKEEPER_CLIENT_PORT: 2181
196 | ZOOKEEPER_TICK_TIME: 2000
197 | ZOOKEEPER_INIT_LIMIT: 10
198 | ZOOKEEPER_SYNC_LIMIT: 5
199 | ZOOKEEPER_PEER_PORT: 2888
200 | ZOOKEEPER_LEADER_PORT: 3888
201 | ZOOKEEPER_SERVERS: zoo1:2888:3888;zoo2:2888:3888;zoo3:2888:3888
202 | volumes:
203 | - zookeeper1-data:/var/lib/zookeeper/data
204 | - zookeeper1-logs:/var/lib/zookeeper/log
205 | networks:
206 | - backend
207 | zoo2:
208 | image: ${ZOOKEEPER_IMAGE}:${ZOOKEEPER_IMAGE_VERSION}
209 | restart: unless-stopped
210 | ports:
211 | - "2182:2182"
212 | environment:
213 | ZOOKEEPER_SERVER_ID: 2
214 | ZOOKEEPER_CLIENT_PORT: 2182
215 | ZOOKEEPER_TICK_TIME: 2000
216 | ZOOKEEPER_INIT_LIMIT: 10
217 | ZOOKEEPER_SYNC_LIMIT: 5
218 | ZOOKEEPER_PEER_PORT: 2888
219 | ZOOKEEPER_LEADER_PORT: 3888
220 | ZOOKEEPER_SERVERS: zoo1:2888:3888;zoo2:2888:3888;zoo3:2888:3888
221 | volumes:
222 | - zookeeper2-data:/var/lib/zookeeper/data
223 | - zookeeper2-logs:/var/lib/zookeeper/log
224 | networks:
225 | - backend
226 | zoo3:
227 | image: ${ZOOKEEPER_IMAGE}:${ZOOKEEPER_IMAGE_VERSION}
228 | restart: unless-stopped
229 | ports:
230 | - "2183:2183"
231 | environment:
232 | ZOOKEEPER_SERVER_ID: 3
233 | ZOOKEEPER_CLIENT_PORT: 2183
234 | ZOOKEEPER_TICK_TIME: 2000
235 | ZOOKEEPER_INIT_LIMIT: 10
236 | ZOOKEEPER_SYNC_LIMIT: 5
237 | ZOOKEEPER_PEER_PORT: 2888
238 | ZOOKEEPER_LEADER_PORT: 3888
239 | ZOOKEEPER_SERVERS: zoo1:2888:3888;zoo2:2888:3888;zoo3:2888:3888
240 | volumes:
241 | - zookeeper3-data:/var/lib/zookeeper/data
242 | - zookeeper3-logs:/var/lib/zookeeper/log
243 | networks:
244 | - backend
245 | zoonavigator:
246 | image: elkozmon/zoonavigator:${ZOONAVIGATOR_VERSION}
247 | restart: unless-stopped
248 | ports:
249 | - "19000:9000"
250 | environment:
251 | - CONNECTION_ZK1_NAME=zoo1
252 | - CONNECTION_ZK1_CONN=zoo1:2181
253 | - CONNECTION_ZK2_NAME=zoo2
254 | - CONNECTION_ZK2_CONN=zoo2:2182
255 | - CONNECTION_ZK3_NAME=zoo3
256 | - CONNECTION_ZK3_CONN=zoo3:2183
257 | - AUTO_CONNECT_CONNECTION_ID=ZK1
258 | depends_on:
259 | - zoo1
260 | - zoo2
261 | - zoo3
262 | networks:
263 | - backend
264 | - vpc
265 | kafka1:
266 | image: ${KAFKA_IMAGE}:${KAFKA_IMAGE_VERSION}
267 | ports:
268 | - "9092:9092"
269 | - "29092:29092"
270 | - "9997:9997"
271 | environment:
272 | KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka1:19092,EXTERNAL://${DOCKER_HOST_IP:-127.0.0.1}:9092,DOCKER://host.docker.internal:29092
273 | KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT,DOCKER:PLAINTEXT
274 | KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL
275 | KAFKA_ZOOKEEPER_CONNECT: "zoo1:2181,zoo2:2182,zoo3:2183"
276 | KAFKA_BROKER_ID: 1
277 | KAFKA_JMX_PORT: 9997
278 | KAFKA_JMX_OPTS: -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=kafka1 -Dcom.sun.management.jmxremote.rmi.port=9997
279 | KAFKA_LOG4J_LOGGERS: "kafka.controller=INFO,kafka.producer.async.DefaultEventHandler=INFO,state.change.logger=INFO"
280 | KAFKA_AUTHORIZER_CLASS_NAME: kafka.security.authorizer.AclAuthorizer
281 | KAFKA_ALLOW_EVERYONE_IF_NO_ACL_FOUND: "true"
282 | depends_on:
283 | - zoo1
284 | - zoo2
285 | - zoo3
286 | networks:
287 | - backend
288 | volumes:
289 | - kafka1-data:/var/lib/kafka/data
290 | kafka2:
291 | image: ${KAFKA_IMAGE}:${KAFKA_IMAGE_VERSION}
292 | ports:
293 | - "9093:9093"
294 | - "29093:29093"
295 | - "9998:9998"
296 | environment:
297 | KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka2:19093,EXTERNAL://${DOCKER_HOST_IP:-127.0.0.1}:9093,DOCKER://host.docker.internal:29093
298 | KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT,DOCKER:PLAINTEXT
299 | KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL
300 | KAFKA_ZOOKEEPER_CONNECT: "zoo1:2181,zoo2:2182,zoo3:2183"
301 | KAFKA_BROKER_ID: 2
302 | KAFKA_JMX_PORT: 9998
303 | KAFKA_JMX_OPTS: -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=kafka1 -Dcom.sun.management.jmxremote.rmi.port=9998
304 | KAFKA_LOG4J_LOGGERS: "kafka.controller=INFO,kafka.producer.async.DefaultEventHandler=INFO,state.change.logger=INFO"
305 | KAFKA_AUTHORIZER_CLASS_NAME: kafka.security.authorizer.AclAuthorizer
306 | KAFKA_ALLOW_EVERYONE_IF_NO_ACL_FOUND: "true"
307 | depends_on:
308 | - zoo1
309 | - zoo2
310 | - zoo3
311 | networks:
312 | - backend
313 | volumes:
314 | - kafka2-data:/var/lib/kafka/data
315 | kafka3:
316 | image: ${KAFKA_IMAGE}:${KAFKA_IMAGE_VERSION}
317 | ports:
318 | - "9094:9094"
319 | - "29094:29094"
320 | - "9999:9999"
321 | environment:
322 | KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka3:19094,EXTERNAL://${DOCKER_HOST_IP:-127.0.0.1}:9094,DOCKER://host.docker.internal:29094
323 | KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT,DOCKER:PLAINTEXT
324 | KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL
325 | KAFKA_ZOOKEEPER_CONNECT: "zoo1:2181,zoo2:2182,zoo3:2183"
326 | KAFKA_BROKER_ID: 3
327 | KAFKA_JMX_PORT: 9999
328 | KAFKA_JMX_OPTS: -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=kafka2 -Dcom.sun.management.jmxremote.rmi.port=9999
329 | KAFKA_LOG4J_LOGGERS: "kafka.controller=INFO,kafka.producer.async.DefaultEventHandler=INFO,state.change.logger=INFO"
330 | KAFKA_AUTHORIZER_CLASS_NAME: kafka.security.authorizer.AclAuthorizer
331 | KAFKA_ALLOW_EVERYONE_IF_NO_ACL_FOUND: "true"
332 | depends_on:
333 | - zoo1
334 | - zoo2
335 | - zoo3
336 | networks:
337 | - backend
338 | volumes:
339 | - kafka3-data:/var/lib/kafka/data
340 | schemaregistry1:
341 | image: ${SCHEMA_REGISTRY_IMAGE}:${SCHEMA_REGISTRY_IMAGE_VERSION}
342 | ports:
343 | - 8085:8085
344 | environment:
345 | SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: PLAINTEXT://kafka1:19092
346 | SCHEMA_REGISTRY_KAFKASTORE_SECURITY_PROTOCOL: PLAINTEXT
347 | SCHEMA_REGISTRY_HOST_NAME: schemaregistry1
348 | SCHEMA_REGISTRY_LISTENERS: http://schemaregistry1:8085
349 |
350 | SCHEMA_REGISTRY_SCHEMA_REGISTRY_INTER_INSTANCE_PROTOCOL: "http"
351 | SCHEMA_REGISTRY_LOG4J_ROOT_LOGLEVEL: INFO
352 | SCHEMA_REGISTRY_KAFKASTORE_TOPIC: _schemas
353 | depends_on:
354 | - kafka1
355 | networks:
356 | - backend
357 | schemaregistry2:
358 | image: ${SCHEMA_REGISTRY_IMAGE}:${SCHEMA_REGISTRY_IMAGE_VERSION}
359 | ports:
360 | - 18085:8085
361 | environment:
362 | SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: PLAINTEXT://kafka2:19093
363 | SCHEMA_REGISTRY_KAFKASTORE_SECURITY_PROTOCOL: PLAINTEXT
364 | SCHEMA_REGISTRY_HOST_NAME: schemaregistry2
365 | SCHEMA_REGISTRY_LISTENERS: http://schemaregistry2:8085
366 |
367 | SCHEMA_REGISTRY_SCHEMA_REGISTRY_INTER_INSTANCE_PROTOCOL: "http"
368 | SCHEMA_REGISTRY_LOG4J_ROOT_LOGLEVEL: INFO
369 | SCHEMA_REGISTRY_KAFKASTORE_TOPIC: _schemas
370 | depends_on:
371 | - kafka1
372 | networks:
373 | - backend
374 | kafka-connect1:
375 | image: ${KAFKA_CONNECT_IMAGE}:${KAFKA_CONNECT_IMAGE_VERSION}
376 | ports:
377 | - 8083:8083
378 | environment:
379 | CONNECT_BOOTSTRAP_SERVERS: kafka1:19092
380 | CONNECT_GROUP_ID: compose-connect-group
381 | CONNECT_CONFIG_STORAGE_TOPIC: _connect_configs
382 | CONNECT_CONFIG_STORAGE_REPLICATION_FACTOR: 1
383 | CONNECT_OFFSET_STORAGE_TOPIC: _connect_offset
384 | CONNECT_OFFSET_STORAGE_REPLICATION_FACTOR: 1
385 | CONNECT_STATUS_STORAGE_TOPIC: _connect_status
386 | CONNECT_STATUS_STORAGE_REPLICATION_FACTOR: 1
387 | CONNECT_KEY_CONVERTER: org.apache.kafka.connect.storage.StringConverter
388 | CONNECT_KEY_CONVERTER_SCHEMA_REGISTRY_URL: http://schemaregistry1:8085
389 | CONNECT_VALUE_CONVERTER: org.apache.kafka.connect.storage.StringConverter
390 | CONNECT_VALUE_CONVERTER_SCHEMA_REGISTRY_URL: http://schemaregistry1:8085
391 | CONNECT_INTERNAL_KEY_CONVERTER: org.apache.kafka.connect.json.JsonConverter
392 | CONNECT_INTERNAL_VALUE_CONVERTER: org.apache.kafka.connect.json.JsonConverter
393 | CONNECT_REST_ADVERTISED_HOST_NAME: kafka-connect1
394 | CONNECT_PLUGIN_PATH: "/usr/share/java,/usr/share/confluent-hub-components"
395 | depends_on:
396 | - kafka1
397 | - schemaregistry1
398 | networks:
399 | - backend
400 | kafkaui:
401 | image: provectuslabs/kafka-ui:latest
402 | ports:
403 | - 8081:8080
404 | environment:
405 | KAFKA_CLUSTERS_0_NAME: local
406 | KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: kafka1:19092
407 | KAFKA_CLUSTERS_0_METRICS_PORT: 9997
408 | KAFKA_CLUSTERS_0_SCHEMAREGISTRY: http://schemaregistry1:8085
409 | KAFKA_CLUSTERS_0_KAFKACONNECT_0_NAME: first
410 | KAFKA_CLUSTERS_0_KAFKACONNECT_0_ADDRESS: http://kafka-connect1:8083
411 | KAFKA_CLUSTERS_1_NAME: secondLocal
412 | KAFKA_CLUSTERS_1_BOOTSTRAPSERVERS: kafka2:19093
413 | KAFKA_CLUSTERS_1_METRICS_PORT: 9998
414 | KAFKA_CLUSTERS_1_SCHEMAREGISTRY: http://schemaregistry2:8085
415 | KAFKA_CLUSTERS_2_NAME: thirdLocal
416 | KAFKA_CLUSTERS_2_BOOTSTRAPSERVERS: kafka3:19094
417 | KAFKA_CLUSTERS_2_METRICS_PORT: 9999
418 | KAFKA_CLUSTERS_2_SCHEMAREGISTRY: http://schemaregistry2:8085
419 | DYNAMIC_CONFIG_ENABLED: 'true'
420 | networks:
421 | - backend
422 | - vpc
423 | depends_on:
424 | - kafka1
425 | - kafka2
426 | - kafka3
427 | - schemaregistry1
428 | - schemaregistry2
429 | - kafka-connect1
430 | minio:
431 | image: quay.io/minio/minio:${MINIO_IMAGE_VERSION}
432 | ports:
433 | - "9000:9000"
434 | - "9001:9001"
435 | command: server /data --console-address ":9001"
436 | networks:
437 | - file-management
438 | - vpc
439 | volumes:
440 | - minio-data:/data
441 | environment:
442 | - MINIO_ROOT_USER=${MINIO_USER}
443 | - MINIO_ROOT_PASSWORD=${MINIO_PASSWORD}
444 | networks:
445 | backend:
446 | driver: bridge
447 | internal: true
448 | security:
449 | driver: bridge
450 | internal: true
451 | license:
452 | driver: bridge
453 | internal: true
454 | file-management:
455 | driver: bridge
456 | internal: true
457 | notification:
458 | driver: bridge
459 | internal: true
460 | vpc:
461 | driver: bridge
462 | volumes:
463 | zookeeper1-data:
464 | zookeeper1-logs:
465 | zookeeper2-data:
466 | zookeeper2-logs:
467 | zookeeper3-data:
468 | zookeeper3-logs:
469 | kafka1-data:
470 | kafka2-data:
471 | kafka3-data:
472 | security-db-data:
473 | license-db-data:
474 | file-management-db-data:
475 | notification-db-data:
476 | minio-data:
477 |
--------------------------------------------------------------------------------
/file-management/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | end_of_line = lf
6 | indent_size = 4
7 | indent_style = space
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.md]
12 | trim_trailing_whitespace = false
13 |
14 | [*.{yml,yaml}]
15 | indent_size = 2
16 |
--------------------------------------------------------------------------------
/file-management/.env.example:
--------------------------------------------------------------------------------
1 | APP_NAME=Laravel
2 | APP_ENV=local
3 | APP_KEY=
4 | APP_DEBUG=true
5 | APP_TIMEZONE=UTC
6 | APP_URL=http://localhost
7 |
8 | APP_LOCALE=en
9 | APP_FALLBACK_LOCALE=en
10 | APP_FAKER_LOCALE=en_US
11 |
12 | APP_MAINTENANCE_DRIVER=file
13 | APP_MAINTENANCE_STORE=database
14 |
15 | BCRYPT_ROUNDS=12
16 |
17 | LOG_CHANNEL=stack
18 | LOG_STACK=single
19 | LOG_DEPRECATIONS_CHANNEL=null
20 | LOG_LEVEL=debug
21 |
22 | DB_CONNECTION=pgsql
23 | DB_HOST=127.0.0.1
24 | DB_PORT=5432
25 | DB_DATABASE=filemanagement
26 | DB_USERNAME=root
27 | DB_PASSWORD=
28 |
29 | SESSION_DRIVER=database
30 | SESSION_LIFETIME=120
31 | SESSION_ENCRYPT=false
32 | SESSION_PATH=/
33 | SESSION_DOMAIN=null
34 |
35 | KAFKA_BROKERS=
36 | KAFKA_CONSUMER_GROUP_ID=file-management
37 | BROADCAST_CONNECTION=log
38 | FILESYSTEM_DISK=local
39 | QUEUE_CONNECTION=database
40 |
41 | CACHE_STORE=database
42 | CACHE_PREFIX=
43 |
44 | MEMCACHED_HOST=127.0.0.1
45 |
46 | REDIS_CLIENT=phpredis
47 | REDIS_HOST=127.0.0.1
48 | REDIS_PASSWORD=null
49 | REDIS_PORT=6379
50 |
51 | MAIL_MAILER=log
52 | MAIL_HOST=127.0.0.1
53 | MAIL_PORT=2525
54 | MAIL_USERNAME=null
55 | MAIL_PASSWORD=null
56 | MAIL_ENCRYPTION=null
57 | MAIL_FROM_ADDRESS="hello@example.com"
58 | MAIL_FROM_NAME="${APP_NAME}"
59 |
60 | AWS_ACCESS_KEY_ID=
61 | AWS_SECRET_ACCESS_KEY=
62 | AWS_DEFAULT_REGION=us-east-1
63 | AWS_BUCKET=
64 | AWS_USE_PATH_STYLE_ENDPOINT=false
65 |
66 | VITE_APP_NAME="${APP_NAME}"
67 |
68 | MINIO_ENDPOINT=http://127.0.0.1:9000/
69 | MINIO_ACCESS_KEY=mservice
70 | MINIO_SECRET_KEY=topsecret
71 |
--------------------------------------------------------------------------------
/file-management/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto eol=lf
2 |
3 | *.md diff=markdown
4 | *.php diff=php
5 |
--------------------------------------------------------------------------------
/file-management/.gitignore:
--------------------------------------------------------------------------------
1 | /.phpunit.cache
2 | /node_modules
3 | /public/build
4 | /public/hot
5 | /public/storage
6 | /storage/*.key
7 | /vendor
8 | .env
9 | .env.backup
10 | .env.production
11 | .phpactor.json
12 | .phpunit.result.cache
13 | Homestead.json
14 | Homestead.yaml
15 | auth.json
16 | npm-debug.log
17 | yarn-error.log
18 | /.fleet
19 | /.idea
20 | /.vscode
21 |
--------------------------------------------------------------------------------
/file-management/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ubuntu:22.04
2 |
3 | ARG WWWGROUP=1000
4 | ARG NODE_VERSION=20
5 | ARG POSTGRES_VERSION=15
6 |
7 | WORKDIR /var/www/html
8 |
9 | ENV DEBIAN_FRONTEND noninteractive
10 | ENV TZ=UTC
11 | ENV SUPERVISOR_PHP_COMMAND="/usr/bin/php -d variables_order=EGPCS /var/www/html/artisan serve --host=0.0.0.0 --port=80"
12 | ENV SUPERVISOR_WORKER_COMMAND="/usr/bin/php /var/www/html/artisan queue:listen"
13 | ENV SUPERVISOR_CONSUMER_COMMAND="/usr/bin/php /var/www/html/artisan app:consume-messages"
14 | ENV SUPERVISOR_PHP_USER="app"
15 |
16 | RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
17 |
18 | RUN apt-get update \
19 | && mkdir -p /etc/apt/keyrings \
20 | && apt-get install -y gnupg gosu curl ca-certificates zip unzip git supervisor sqlite3 libcap2-bin libpng-dev python2 dnsutils librsvg2-bin fswatch ffmpeg nano \
21 | && curl -sS 'https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x14aa40ec0831756756d7f66c4f4ea0aae5267a6c' | gpg --dearmor | tee /etc/apt/keyrings/ppa_ondrej_php.gpg > /dev/null \
22 | && echo "deb [signed-by=/etc/apt/keyrings/ppa_ondrej_php.gpg] https://ppa.launchpadcontent.net/ondrej/php/ubuntu jammy main" > /etc/apt/sources.list.d/ppa_ondrej_php.list \
23 | && apt-get update \
24 | && apt-get install -y librdkafka-dev php8.2-cli php8.2-dev \
25 | php8.2-pgsql php8.2-sqlite3 php8.2-gd php8.2-imagick \
26 | php8.2-curl \
27 | php8.2-imap php8.2-mysql php8.2-mbstring \
28 | php8.2-xml php8.2-zip php8.2-bcmath php8.2-soap \
29 | php8.2-intl php8.2-readline \
30 | php8.2-ldap \
31 | php8.2-msgpack php8.2-igbinary php8.2-redis php8.2-swoole \
32 | php8.2-memcached php8.2-pcov php8.2-xdebug \
33 | && pecl install rdkafka \
34 | && curl -sLS https://getcomposer.org/installer | php -- --install-dir=/usr/bin/ --filename=composer \
35 | && curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \
36 | && echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_VERSION.x nodistro main" > /etc/apt/sources.list.d/nodesource.list \
37 | && apt-get update \
38 | && apt-get install -y nodejs \
39 | && npm install -g npm \
40 | && npm install -g pnpm \
41 | && npm install -g bun \
42 | && curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor | tee /etc/apt/keyrings/yarn.gpg >/dev/null \
43 | && echo "deb [signed-by=/etc/apt/keyrings/yarn.gpg] https://dl.yarnpkg.com/debian/ stable main" > /etc/apt/sources.list.d/yarn.list \
44 | && curl -sS https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor | tee /etc/apt/keyrings/pgdg.gpg >/dev/null \
45 | && echo "deb [signed-by=/etc/apt/keyrings/pgdg.gpg] http://apt.postgresql.org/pub/repos/apt jammy-pgdg main" > /etc/apt/sources.list.d/pgdg.list \
46 | && apt-get update \
47 | && apt-get install -y yarn \
48 | && apt-get install -y mysql-client \
49 | && apt-get install -y postgresql-client-$POSTGRES_VERSION \
50 | && apt-get -y autoremove \
51 | && apt-get clean \
52 | && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
53 |
54 | RUN setcap "cap_net_bind_service=+ep" /usr/bin/php8.2
55 |
56 | RUN groupadd --force -g $WWWGROUP app
57 | RUN useradd -ms /bin/bash --no-user-group -g $WWWGROUP -u 1337 app
58 |
59 | COPY docker/start-container /usr/local/bin/start-container
60 | COPY docker/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
61 | COPY docker/php.ini /etc/php/8.2/cli/conf.d/99-app.ini
62 | RUN chmod +x /usr/local/bin/start-container
63 |
64 | EXPOSE 8000
65 |
66 | ENTRYPOINT ["start-container"]
67 |
--------------------------------------------------------------------------------
/file-management/artisan:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 | handleCommand(new ArgvInput);
14 |
15 | exit($status);
16 |
--------------------------------------------------------------------------------
/file-management/bootstrap/app.php:
--------------------------------------------------------------------------------
1 | withCommands([ConsumeMessages::class])
11 | ->withRouting(
12 | health: '/up',
13 | )
14 | ->withMiddleware(function (Middleware $middleware) {
15 | //
16 | })
17 | ->withExceptions(function (Exceptions $exceptions) {
18 | //
19 | })->create();
20 |
21 | $app->useAppPath(join_paths(dirname(__DIR__), 'src'));
22 |
23 | return $app;
24 |
--------------------------------------------------------------------------------
/file-management/bootstrap/cache/.gitignore:
--------------------------------------------------------------------------------
1 | *
2 | !.gitignore
3 |
--------------------------------------------------------------------------------
/file-management/bootstrap/providers.php:
--------------------------------------------------------------------------------
1 | env('KAFKA_BROKERS', 'localhost:9092'),
8 |
9 | /*
10 | | Default security protocol
11 | */
12 | 'securityProtocol' => env('KAFKA_SECURITY_PROTOCOL', 'PLAINTEXT'),
13 |
14 | /*
15 | | Default sasl configuration
16 | */
17 | 'sasl' => [
18 | 'mechanisms' => env('KAFKA_MECHANISMS', 'PLAINTEXT'),
19 | 'username' => env('KAFKA_USERNAME', null),
20 | 'password' => env('KAFKA_PASSWORD', null)
21 | ],
22 |
23 | /*
24 | | Kafka consumers belonging to the same consumer group share a group id.
25 | | The consumers in a group then divides the topic partitions as fairly amongst themselves as possible by
26 | | establishing that each partition is only consumed by a single consumer from the group.
27 | | This config defines the consumer group id you want to use for your project.
28 | */
29 | 'consumer_group_id' => env('KAFKA_CONSUMER_GROUP_ID', 'group'),
30 |
31 | 'consumer_timeout_ms' => env("KAFKA_CONSUMER_DEFAULT_TIMEOUT", 2000),
32 |
33 | /*
34 | | After the consumer receives its assignment from the coordinator,
35 | | it must determine the initial position for each assigned partition.
36 | | When the group is first created, before any messages have been consumed, the position is set according to a configurable
37 | | offset reset policy (auto.offset.reset). Typically, consumption starts either at the earliest offset or the latest offset.
38 | | You can choose between "latest", "earliest" or "none".
39 | */
40 | 'offset_reset' => env('KAFKA_OFFSET_RESET', 'latest'),
41 |
42 | /*
43 | | If you set enable.auto.commit (which is the default), then the consumer will automatically commit offsets periodically at the
44 | | interval set by auto.commit.interval.ms.
45 | */
46 | 'auto_commit' => env('KAFKA_AUTO_COMMIT', true),
47 |
48 | 'sleep_on_error' => env('KAFKA_ERROR_SLEEP', 5),
49 |
50 | 'partition' => env('KAFKA_PARTITION', 0),
51 |
52 | /*
53 | | Kafka supports 4 compression codecs: none , gzip , lz4 and snappy
54 | */
55 | 'compression' => env('KAFKA_COMPRESSION_TYPE', 'snappy'),
56 |
57 | /*
58 | | Choose if debug is enabled or not.
59 | */
60 | 'debug' => env('KAFKA_DEBUG', false),
61 |
62 | /*
63 | | Repository for batching messages together
64 | | Implement BatchRepositoryInterface to save batches in different storage
65 | */
66 | 'batch_repository' => env('KAFKA_BATCH_REPOSITORY', \Junges\Kafka\BatchRepositories\InMemoryBatchRepository::class),
67 |
68 | /*
69 | | The sleep time in milliseconds that will be used when retrying flush
70 | */
71 | 'flush_retry_sleep_in_ms' => 100,
72 |
73 | /*
74 | | The cache driver that will be used
75 | */
76 | 'cache_driver' => env('KAFKA_CACHE_DRIVER', env('CACHE_DRIVER', 'file')),
77 | ];
78 |
--------------------------------------------------------------------------------
/file-management/config/services.php:
--------------------------------------------------------------------------------
1 | [
5 | 'endpoint' => env('MINIO_ENDPOINT', 'http://127.0.0.1:9000'),
6 | 'access_key' => env('MINIO_ACCESS_KEY', 'mservice'),
7 | 'secret_key' => env('MINIO_SECRET_KEY', 'topsecret'),
8 | ],
9 |
10 | 'license' => [
11 | 'base_uri' => env('LICENSE_SERVICE_URL', 'http://license/api/v1/'),
12 | 'timeout' => env('LICENSE_SERVICE_TIMEOUT', 30),
13 | ]
14 | ];
15 |
--------------------------------------------------------------------------------
/file-management/database/.gitignore:
--------------------------------------------------------------------------------
1 | *.sqlite*
2 |
--------------------------------------------------------------------------------
/file-management/docker/php.ini:
--------------------------------------------------------------------------------
1 | [PHP]
2 | post_max_size = 100M
3 | upload_max_filesize = 100M
4 | variables_order = EGPCS
5 | pcov.directory = .
6 |
7 | extension=rdkafka.so
8 |
--------------------------------------------------------------------------------
/file-management/docker/start-container:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | if [ "$SUPERVISOR_PHP_USER" != "root" ] && [ "$SUPERVISOR_PHP_USER" != "app" ]; then
4 | echo "You should set SUPERVISOR_PHP_USER to either 'app' or 'root'."
5 | exit 1
6 | fi
7 |
8 | if [ ! -z "$WWWUSER" ]; then
9 | usermod -u $WWWUSER app
10 | fi
11 |
12 | if [ ! -d /.composer ]; then
13 | mkdir /.composer
14 | fi
15 |
16 | chmod -R ugo+rw /.composer
17 |
18 | if [ $# -gt 0 ]; then
19 | if [ "$SUPERVISOR_PHP_USER" = "root" ]; then
20 | exec "$@"
21 | else
22 | exec gosu $WWWUSER "$@"
23 | fi
24 | else
25 | exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf
26 | fi
27 |
--------------------------------------------------------------------------------
/file-management/docker/supervisord.conf:
--------------------------------------------------------------------------------
1 | [supervisord]
2 | nodaemon=true
3 | user=root
4 | logfile=/var/log/supervisor/supervisord.log
5 | pidfile=/var/run/supervisord.pid
6 |
7 | [program:php]
8 | command=%(ENV_SUPERVISOR_PHP_COMMAND)s
9 | user=%(ENV_SUPERVISOR_PHP_USER)s
10 | environment=APP_IN_DOCKER="1"
11 | stdout_logfile=/dev/stdout
12 | stdout_logfile_maxbytes=0
13 | stderr_logfile=/dev/stderr
14 | stderr_logfile_maxbytes=0
15 |
16 | [program:worker]
17 | command=%(ENV_SUPERVISOR_WORKER_COMMAND)s
18 | user=%(ENV_SUPERVISOR_PHP_USER)s
19 | environment=APP_IN_DOCKER="1"
20 | stdout_logfile=/dev/stdout
21 | stdout_logfile_maxbytes=0
22 | stderr_logfile=/dev/stderr
23 | stderr_logfile_maxbytes=0
24 |
25 | [program:consumer]
26 | command=%(ENV_SUPERVISOR_CONSUMER_COMMAND)s
27 | user=%(ENV_SUPERVISOR_PHP_USER)s
28 | environment=APP_IN_DOCKER="1"
29 | stdout_logfile=/dev/stdout
30 | stdout_logfile_maxbytes=0
31 | stderr_logfile=/dev/stderr
32 | stderr_logfile_maxbytes=0
33 |
--------------------------------------------------------------------------------
/file-management/public/.htaccess:
--------------------------------------------------------------------------------
1 |
Welcome to our application!
2 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Microservice Architecture for Laravel 2 | 3 | ## Table of Contents 4 | 5 | - [Overview](#overview) 6 | - [Technologies](#technologies) 7 | - [Getting Started](#getting-started) 8 | - [Installation](#installation) 9 | - [Configuration](#configuration) 10 | - [Generate RSA Keys](#generate-rsa-keys) 11 | - [Running the Services](#running-the-services) 12 | - [Microservices](#microservices) 13 | - [Security](#security-service) 14 | - [License](#license-service) 15 | - [File Management](#file-management-service) 16 | - [Need to Implement](#need-to-implement) 17 | - [Contributing](#contributing) 18 | - [License](#license) 19 | 20 | ## Overview 21 | 22 | This project is a microservice-based architecture designed to provide scalable and maintainable solutions. 23 | It includes various technologies for managing service discovery, messaging, and data integration. 24 | 25 | ## Technologies 26 | 27 | - **Zookeeper**: Used for service discovery and coordination. 28 | - **ZooNavigator**: A web-based UI for managing Zookeeper instances. 29 | - **Kafka**: A distributed streaming platform used for building real-time data pipelines and streaming applications. 30 | - **Schema Registry**: Manages and enforces schemas for Kafka topics. 31 | - **Kafka Connect**: A tool for scalable and reliably streaming data between Apache Kafka and other systems. 32 | - **Kafka UI**: A web-based UI for managing and monitoring Kafka clusters. 33 | - **PostgreSQL**: A powerful, open source object-relational database system. 34 | 35 | ## Getting Started 36 | 37 | Ensure you have the following software installed: 38 | - Docker 39 | - Docker Compose 40 | 41 | To get a local copy of this project up and running, follow these simple steps. 42 | 43 | ## Installation 44 | 45 | 1. Clone the repository: 46 | ```shell 47 | git clone https://github.com/erayaydin/microservice-laravel.git 48 | cd microservice-laravel 49 | ``` 50 | 2. Copy the sample `.env.example` to `.env`: 51 | ```shell 52 | cp .env.example .env 53 | ``` 54 | 3. Edit necessary parts in `.env` file as needed. 55 | 56 | ## Configuration 57 | 58 | The configuration settings are stored in the `.env` file. Customize the necessary parts as needed. 59 | 60 | - **ZOOKEEPER_IMAGE**: Docker image name to use for zookeeper instances. Default: `confluentinc/cp-zookeeper` 61 | - **ZOOKEEPER_IMAGE_VERSION**: Docker image version for _ZOOKEEPER_IMAGE_ image. Default: `7.6.1` 62 | - **ZOONAVIGATOR_VERSION**: ZooNavigator UI image version to install with services. Default: `1.1.2` 63 | - **KAFKA_IMAGE**: Docker image name to use for kafka instances. Default: `confluentinc/cp-kafka` 64 | - **KAFKA_IMAGE_VERSION**: Docker image version for _KAFKA_IMAGE_ image. Default: `7.6.1` 65 | - **SCHEMA_REGISTRY_IMAGE**: Docker image name to use for SchemaRegistry instances. Default: `confluentinc/cp-schema-registry` 66 | - **SCHEMA_REGISTRY_IMAGE_VERSION**: Docker image version for _SCHEMA_REGISTRY_IMAGE_ image. Default: `7.6.1` 67 | - **KAFKA_CONNECT_IMAGE**: Docker image name to use for kafka connect instances. Default: `confluentinc/cp-kafka-connect` 68 | - **KAFKA_CONNECT_IMAGE_VERSION**: Docker image version for _KAFKA_CONNECT_IMAGE_ image. Default: `7.6.1` 69 | - **WWWUSER**: User id for microservice instances. Default: `1000` 70 | - **WWWGROUP**: Group id for microservice instances. Default: `1000` 71 | - **APP_[SERVICE]_DB_IMAGE_VERSION**: PostgreSQL instance version for the `[SERVICE]` microservice. Default: `15` 72 | - **APP_[SERVICE]_PORT**: External port of the `[SERVICE]` microservice. It will be increased 1 by 1 starting from 73 | `8082`. 74 | - **APP_[SERVICE]_XDEBUG_MODE**: Enable xdebug extension for the `[SERVICE]` microservice. Default: `off` 75 | - **APP_[SERVICE]_XDEBUG_CONFIG**: If xdebug enabled, xdebug integration config. Edit for development environment needs. 76 | Default: `-client_host=host.docker.internal` 77 | - **APP_[SERVICE]_DB_PORT**: External port of the `[SERVICE]` microservice's database. It will be increased 1 by 1 78 | starting from `5432`. 79 | 80 | ## Generate RSA Keys 81 | 82 | You need to generate a pair of 4096-bit RSA private and public keys for inter-service authentication 83 | and authorization. These keys will be shared between services. 84 | 85 | ```shell 86 | openssl genrsa -out secrets/oauth-private.key 4096 87 | openssl rsa -in secrets/oauth-private.key -pubout -out secrets/oauth-public.key 88 | ``` 89 | 90 | ## Running the Services 91 | 92 | To start all the services, run: 93 | 94 | ```shell 95 | docker compose up -d 96 | ``` 97 | 98 | This command will start all the containers defined in the docker-compose.yml file. 99 | 100 | Remember to run migrations and necessary adjustments before testing services. Like: 101 | 102 | ```shell 103 | docker compose exec -u app security php artisan migrate 104 | ``` 105 | 106 | ## Microservices 107 | 108 | ### Security Service 109 | 110 | The Security Service is responsible for handling user authentication and authorization. 111 | Authentication and authorization will be handled with OAuth2. 112 | 113 | #### Endpoints 114 | 115 | - `GET /health`: Health check endpoint. It'll respond with **200** status code. 116 | - `POST /users`: Create new user. It'll respond with **201** status code if success. 117 | - `GET /oauth/authorize`: Show authorization to the end user. 118 | - `POST /oauth/authorize`: Approve authorization. 119 | - `DELETE /oauth/authorize`: Deny authorization. 120 | - `GET /oauth/clients`: Get oauth clients for the user. 121 | - `POST /oauth/clients`: Create new oauth client. 122 | - `PUT /oauth/clients/{client_id}`: Update an oauth client. 123 | - `DELETE /oauth/clients/{client_id}`: Delete an oauth client. 124 | - `GET /oauth/personal-access-tokens`: Get personal access token oauth clients for the user. 125 | - `POST /oauth/personal-access-tokens`: Create new personal access token oauth client. 126 | - `DELETE /oauth/personal-access-tokens/{token_id}`: Delete a personal access token oauth client. 127 | - `GET /oauth/scopes`: Get all registered scopes. 128 | - `POST /oauth/token`: Issue new token with specified strategy. 129 | - `POST /oauth/token/refresh`: Refresh access token with refresh token. 130 | - `GET /oauth/tokens`: Get authorized access token for the user. 131 | - `DELETE /oauth/tokens/{token_id}`: Delete an access token. 132 | 133 | #### Data Store 134 | 135 | - **PostgreSQL**: The Security Service uses PostgreSQL to store user credentials and authorization data. 136 | 137 | ### License Service 138 | 139 | The Security Service is responsible for handling user licenses. 140 | Auth verification will be handled with JWT key decoding. 141 | 142 | #### Endpoints 143 | 144 | - `GET /health`: Health check endpoint. It'll respond with 200 status code. 145 | - `GET /me`: Get current user license information. 146 | - `GET /users/{user}`: Get user's license information. (need `admin.licenses` scope). 147 | 148 | #### Data Store 149 | 150 | - **PostgreSQL**: The License Service uses PostgreSQL to store license information. 151 | 152 | ### File Management Service 153 | 154 | The File Management Service is responsible for handling file operations. 155 | End user can upload and download files. 156 | 157 | #### Endpoints 158 | 159 | - `GET /health`: Health check endpoint. It'll respond with 200 status code. 160 | - `GET /files`: List of current user's uploaded files. 161 | - `POST /files`: Upload new file to user's bucket. 162 | - `GET /files/{file}/download`: Downloads the given file in attachment mode. 163 | 164 | #### Data Store 165 | 166 | - **PostgreSQL**: The File Management Service uses PostgreSQL to store file metadata. 167 | 168 | ## Need to Implement 169 | 170 | - Use [`Kong`](https://github.com/Kong/kong) api-gateway to single entrypoint. 171 | - Implement permission and scope system to license `/users/{user}` endpoint. 172 | - Use `docker secret` to share oauth private and public keys. 173 | - Implement `ObjectStorage` service to manage buckets. 174 | - Use RDKafka data processor instead of the current one. 175 | - Define schemas for `user.created` and `license.updated` kafka messages. 176 | - Remove config files for `services` and `kafka`. Use provider to bind instances with values. 177 | - Use kafka-connect1 for connect services to kafka cluster. 178 | - Fix style issues and apply on CI. 179 | - Add ELK stack and/or Grafana metrics. 180 | - Add unit, integration and e2e tests. 181 | - Add k8s yaml files. 182 | - Add OpenAPI documentation for the api-gateway and services. 183 | - Use kong+security to validate and decode OAuth2 184 | 185 | ## Contributing 186 | 187 | Contributions are what make the open-source community such an amazing place to learn, inspire, and create. Any 188 | contributions you make are **greatly appreciated.** 189 | 190 | 1. Fork the Project 191 | 2. Create your feature branch (`git checkout -b feature/amazing-feature`) 192 | 3. Commit your changes (`git commit`) 193 | 4. Push to the branch (`git push origin feature/amazing-feature`) 194 | 5. Open a pull request with detailed description. 195 | 196 | ## License 197 | 198 | Distributed under the **MIT License**. 199 | -------------------------------------------------------------------------------- /secrets/.gitignore: -------------------------------------------------------------------------------- 1 | *.key -------------------------------------------------------------------------------- /security/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_size = 4 7 | indent_style = space 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | 14 | [*.{yml,yaml}] 15 | indent_size = 2 16 | -------------------------------------------------------------------------------- /security/.env.example: -------------------------------------------------------------------------------- 1 | APP_NAME=Laravel 2 | APP_ENV=local 3 | APP_KEY= 4 | APP_DEBUG=true 5 | APP_TIMEZONE=UTC 6 | APP_URL=http://localhost 7 | 8 | APP_LOCALE=en 9 | APP_FALLBACK_LOCALE=en 10 | APP_FAKER_LOCALE=en_US 11 | 12 | APP_MAINTENANCE_DRIVER=file 13 | APP_MAINTENANCE_STORE=database 14 | 15 | BCRYPT_ROUNDS=12 16 | 17 | LOG_CHANNEL=stack 18 | LOG_STACK=single 19 | LOG_DEPRECATIONS_CHANNEL=null 20 | LOG_LEVEL=debug 21 | 22 | DB_CONNECTION=pgsql 23 | DB_HOST=127.0.0.1 24 | DB_PORT=5432 25 | DB_DATABASE=security 26 | DB_USERNAME=root 27 | DB_PASSWORD= 28 | 29 | SESSION_DRIVER=database 30 | SESSION_LIFETIME=120 31 | SESSION_ENCRYPT=false 32 | SESSION_PATH=/ 33 | SESSION_DOMAIN=null 34 | 35 | KAFKA_BROKERS= 36 | BROADCAST_CONNECTION=log 37 | FILESYSTEM_DISK=local 38 | QUEUE_CONNECTION=database 39 | 40 | CACHE_STORE=database 41 | CACHE_PREFIX= 42 | 43 | MEMCACHED_HOST=127.0.0.1 44 | 45 | REDIS_CLIENT=phpredis 46 | REDIS_HOST=127.0.0.1 47 | REDIS_PASSWORD=null 48 | REDIS_PORT=6379 49 | 50 | MAIL_MAILER=log 51 | MAIL_HOST=127.0.0.1 52 | MAIL_PORT=2525 53 | MAIL_USERNAME=null 54 | MAIL_PASSWORD=null 55 | MAIL_ENCRYPTION=null 56 | MAIL_FROM_ADDRESS="hello@example.com" 57 | MAIL_FROM_NAME="${APP_NAME}" 58 | 59 | AWS_ACCESS_KEY_ID= 60 | AWS_SECRET_ACCESS_KEY= 61 | AWS_DEFAULT_REGION=us-east-1 62 | AWS_BUCKET= 63 | AWS_USE_PATH_STYLE_ENDPOINT=false 64 | 65 | VITE_APP_NAME="${APP_NAME}" 66 | -------------------------------------------------------------------------------- /security/.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | 3 | *.md diff=markdown 4 | *.php diff=php 5 | -------------------------------------------------------------------------------- /security/.gitignore: -------------------------------------------------------------------------------- 1 | /.phpunit.cache 2 | /node_modules 3 | /public/build 4 | /public/hot 5 | /public/storage 6 | /storage/*.key 7 | /vendor 8 | .env 9 | .env.backup 10 | .env.production 11 | .phpactor.json 12 | .phpunit.result.cache 13 | Homestead.json 14 | Homestead.yaml 15 | auth.json 16 | npm-debug.log 17 | yarn-error.log 18 | /.fleet 19 | /.idea 20 | /.vscode 21 | -------------------------------------------------------------------------------- /security/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 2 | 3 | ARG WWWGROUP=1000 4 | ARG NODE_VERSION=20 5 | ARG POSTGRES_VERSION=15 6 | 7 | WORKDIR /var/www/html 8 | 9 | ENV DEBIAN_FRONTEND noninteractive 10 | ENV TZ=UTC 11 | ENV SUPERVISOR_PHP_COMMAND="/usr/bin/php -d variables_order=EGPCS /var/www/html/artisan serve --host=0.0.0.0 --port=80" 12 | ENV SUPERVISOR_WORKER_COMMAND="/usr/bin/php /var/www/html/artisan queue:listen" 13 | ENV SUPERVISOR_PHP_USER="app" 14 | 15 | RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone 16 | 17 | RUN apt-get update \ 18 | && mkdir -p /etc/apt/keyrings \ 19 | && apt-get install -y gnupg gosu curl ca-certificates zip unzip git supervisor sqlite3 libcap2-bin libpng-dev python2 dnsutils librsvg2-bin fswatch ffmpeg nano \ 20 | && curl -sS 'https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x14aa40ec0831756756d7f66c4f4ea0aae5267a6c' | gpg --dearmor | tee /etc/apt/keyrings/ppa_ondrej_php.gpg > /dev/null \ 21 | && echo "deb [signed-by=/etc/apt/keyrings/ppa_ondrej_php.gpg] https://ppa.launchpadcontent.net/ondrej/php/ubuntu jammy main" > /etc/apt/sources.list.d/ppa_ondrej_php.list \ 22 | && apt-get update \ 23 | && apt-get install -y librdkafka-dev php8.2-cli php8.2-dev \ 24 | php8.2-pgsql php8.2-sqlite3 php8.2-gd php8.2-imagick \ 25 | php8.2-curl \ 26 | php8.2-imap php8.2-mysql php8.2-mbstring \ 27 | php8.2-xml php8.2-zip php8.2-bcmath php8.2-soap \ 28 | php8.2-intl php8.2-readline \ 29 | php8.2-ldap \ 30 | php8.2-msgpack php8.2-igbinary php8.2-redis php8.2-swoole \ 31 | php8.2-memcached php8.2-pcov php8.2-xdebug \ 32 | && pecl install rdkafka \ 33 | && curl -sLS https://getcomposer.org/installer | php -- --install-dir=/usr/bin/ --filename=composer \ 34 | && curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg \ 35 | && echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_$NODE_VERSION.x nodistro main" > /etc/apt/sources.list.d/nodesource.list \ 36 | && apt-get update \ 37 | && apt-get install -y nodejs \ 38 | && npm install -g npm \ 39 | && npm install -g pnpm \ 40 | && npm install -g bun \ 41 | && curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor | tee /etc/apt/keyrings/yarn.gpg >/dev/null \ 42 | && echo "deb [signed-by=/etc/apt/keyrings/yarn.gpg] https://dl.yarnpkg.com/debian/ stable main" > /etc/apt/sources.list.d/yarn.list \ 43 | && curl -sS https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor | tee /etc/apt/keyrings/pgdg.gpg >/dev/null \ 44 | && echo "deb [signed-by=/etc/apt/keyrings/pgdg.gpg] http://apt.postgresql.org/pub/repos/apt jammy-pgdg main" > /etc/apt/sources.list.d/pgdg.list \ 45 | && apt-get update \ 46 | && apt-get install -y yarn \ 47 | && apt-get install -y mysql-client \ 48 | && apt-get install -y postgresql-client-$POSTGRES_VERSION \ 49 | && apt-get -y autoremove \ 50 | && apt-get clean \ 51 | && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 52 | 53 | RUN setcap "cap_net_bind_service=+ep" /usr/bin/php8.2 54 | 55 | RUN groupadd --force -g $WWWGROUP app 56 | RUN useradd -ms /bin/bash --no-user-group -g $WWWGROUP -u 1337 app 57 | 58 | COPY docker/start-container /usr/local/bin/start-container 59 | COPY docker/supervisord.conf /etc/supervisor/conf.d/supervisord.conf 60 | COPY docker/php.ini /etc/php/8.2/cli/conf.d/99-app.ini 61 | RUN chmod +x /usr/local/bin/start-container 62 | 63 | EXPOSE 8000 64 | 65 | ENTRYPOINT ["start-container"] 66 | -------------------------------------------------------------------------------- /security/artisan: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | handleCommand(new ArgvInput); 14 | 15 | exit($status); 16 | -------------------------------------------------------------------------------- /security/bootstrap/app.php: -------------------------------------------------------------------------------- 1 | singleton( 20 | HttpKernelContract::class, 21 | HttpKernel::class, 22 | ); 23 | $app->singleton( 24 | ConsoleKernelContract::class, 25 | ConsoleKernel::class, 26 | ); 27 | 28 | // Register essential providers 29 | $app->register(EventServiceProvider::class); 30 | 31 | // Register default bootstrap providers 32 | RegisterProviders::merge([], $app->getBootstrapProvidersPath()); 33 | */ 34 | 35 | $app = Application::configure(basePath: dirname(__DIR__)) 36 | ->withRouting( 37 | health: '/up', 38 | ) 39 | ->withMiddleware(function (Middleware $middleware) { 40 | // 41 | }) 42 | ->withExceptions(function (Exceptions $exceptions) { 43 | // 44 | })->create(); 45 | 46 | $app->useAppPath(join_paths(dirname(__DIR__), 'src')); 47 | 48 | return $app; 49 | -------------------------------------------------------------------------------- /security/bootstrap/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /security/bootstrap/providers.php: -------------------------------------------------------------------------------- 1 | env('KAFKA_BROKERS', 'localhost:9092'), 8 | 9 | /* 10 | | Default security protocol 11 | */ 12 | 'securityProtocol' => env('KAFKA_SECURITY_PROTOCOL', 'PLAINTEXT'), 13 | 14 | /* 15 | | Default sasl configuration 16 | */ 17 | 'sasl' => [ 18 | 'mechanisms' => env('KAFKA_MECHANISMS', 'PLAINTEXT'), 19 | 'username' => env('KAFKA_USERNAME', null), 20 | 'password' => env('KAFKA_PASSWORD', null) 21 | ], 22 | 23 | /* 24 | | Kafka consumers belonging to the same consumer group share a group id. 25 | | The consumers in a group then divides the topic partitions as fairly amongst themselves as possible by 26 | | establishing that each partition is only consumed by a single consumer from the group. 27 | | This config defines the consumer group id you want to use for your project. 28 | */ 29 | 'consumer_group_id' => env('KAFKA_CONSUMER_GROUP_ID', 'group'), 30 | 31 | 'consumer_timeout_ms' => env("KAFKA_CONSUMER_DEFAULT_TIMEOUT", 2000), 32 | 33 | /* 34 | | After the consumer receives its assignment from the coordinator, 35 | | it must determine the initial position for each assigned partition. 36 | | When the group is first created, before any messages have been consumed, the position is set according to a configurable 37 | | offset reset policy (auto.offset.reset). Typically, consumption starts either at the earliest offset or the latest offset. 38 | | You can choose between "latest", "earliest" or "none". 39 | */ 40 | 'offset_reset' => env('KAFKA_OFFSET_RESET', 'latest'), 41 | 42 | /* 43 | | If you set enable.auto.commit (which is the default), then the consumer will automatically commit offsets periodically at the 44 | | interval set by auto.commit.interval.ms. 45 | */ 46 | 'auto_commit' => env('KAFKA_AUTO_COMMIT', true), 47 | 48 | 'sleep_on_error' => env('KAFKA_ERROR_SLEEP', 5), 49 | 50 | 'partition' => env('KAFKA_PARTITION', 0), 51 | 52 | /* 53 | | Kafka supports 4 compression codecs: none , gzip , lz4 and snappy 54 | */ 55 | 'compression' => env('KAFKA_COMPRESSION_TYPE', 'snappy'), 56 | 57 | /* 58 | | Choose if debug is enabled or not. 59 | */ 60 | 'debug' => env('KAFKA_DEBUG', false), 61 | 62 | /* 63 | | Repository for batching messages together 64 | | Implement BatchRepositoryInterface to save batches in different storage 65 | */ 66 | 'batch_repository' => env('KAFKA_BATCH_REPOSITORY', \Junges\Kafka\BatchRepositories\InMemoryBatchRepository::class), 67 | 68 | /* 69 | | The sleep time in milliseconds that will be used when retrying flush 70 | */ 71 | 'flush_retry_sleep_in_ms' => 100, 72 | 73 | /* 74 | | The cache driver that will be used 75 | */ 76 | 'cache_driver' => env('KAFKA_CACHE_DRIVER', env('CACHE_DRIVER', 'file')), 77 | ]; 78 | -------------------------------------------------------------------------------- /security/database/.gitignore: -------------------------------------------------------------------------------- 1 | *.sqlite* 2 | -------------------------------------------------------------------------------- /security/database/migrations/0001_01_01_000000_create_users_table.php: -------------------------------------------------------------------------------- 1 | id(); 16 | $table->string('name'); 17 | $table->string('email')->unique(); 18 | $table->timestamp('email_verified_at')->nullable(); 19 | $table->string('password'); 20 | $table->rememberToken(); 21 | $table->timestamps(); 22 | }); 23 | 24 | Schema::create('password_reset_tokens', function (Blueprint $table) { 25 | $table->string('email')->primary(); 26 | $table->string('token'); 27 | $table->timestamp('created_at')->nullable(); 28 | }); 29 | 30 | Schema::create('sessions', function (Blueprint $table) { 31 | $table->string('id')->primary(); 32 | $table->foreignId('user_id')->nullable()->index(); 33 | $table->string('ip_address', 45)->nullable(); 34 | $table->text('user_agent')->nullable(); 35 | $table->longText('payload'); 36 | $table->integer('last_activity')->index(); 37 | }); 38 | } 39 | 40 | /** 41 | * Reverse the migrations. 42 | */ 43 | public function down(): void 44 | { 45 | Schema::dropIfExists('users'); 46 | Schema::dropIfExists('password_reset_tokens'); 47 | Schema::dropIfExists('sessions'); 48 | } 49 | }; 50 | -------------------------------------------------------------------------------- /security/database/migrations/0001_01_01_000001_create_cache_table.php: -------------------------------------------------------------------------------- 1 | string('key')->primary(); 16 | $table->mediumText('value'); 17 | $table->integer('expiration'); 18 | }); 19 | 20 | Schema::create('cache_locks', function (Blueprint $table) { 21 | $table->string('key')->primary(); 22 | $table->string('owner'); 23 | $table->integer('expiration'); 24 | }); 25 | } 26 | 27 | /** 28 | * Reverse the migrations. 29 | */ 30 | public function down(): void 31 | { 32 | Schema::dropIfExists('cache'); 33 | Schema::dropIfExists('cache_locks'); 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /security/database/migrations/0001_01_01_000002_create_jobs_table.php: -------------------------------------------------------------------------------- 1 | id(); 16 | $table->string('queue')->index(); 17 | $table->longText('payload'); 18 | $table->unsignedTinyInteger('attempts'); 19 | $table->unsignedInteger('reserved_at')->nullable(); 20 | $table->unsignedInteger('available_at'); 21 | $table->unsignedInteger('created_at'); 22 | }); 23 | 24 | Schema::create('job_batches', function (Blueprint $table) { 25 | $table->string('id')->primary(); 26 | $table->string('name'); 27 | $table->integer('total_jobs'); 28 | $table->integer('pending_jobs'); 29 | $table->integer('failed_jobs'); 30 | $table->longText('failed_job_ids'); 31 | $table->mediumText('options')->nullable(); 32 | $table->integer('cancelled_at')->nullable(); 33 | $table->integer('created_at'); 34 | $table->integer('finished_at')->nullable(); 35 | }); 36 | 37 | Schema::create('failed_jobs', function (Blueprint $table) { 38 | $table->id(); 39 | $table->string('uuid')->unique(); 40 | $table->text('connection'); 41 | $table->text('queue'); 42 | $table->longText('payload'); 43 | $table->longText('exception'); 44 | $table->timestamp('failed_at')->useCurrent(); 45 | }); 46 | } 47 | 48 | /** 49 | * Reverse the migrations. 50 | */ 51 | public function down(): void 52 | { 53 | Schema::dropIfExists('jobs'); 54 | Schema::dropIfExists('job_batches'); 55 | Schema::dropIfExists('failed_jobs'); 56 | } 57 | }; 58 | -------------------------------------------------------------------------------- /security/database/migrations/2024_06_04_130737_create_oauth_personal_access_clients_table.php: -------------------------------------------------------------------------------- 1 | bigIncrements('id'); 16 | $table->unsignedBigInteger('client_id'); 17 | $table->timestamps(); 18 | }); 19 | } 20 | 21 | /** 22 | * Reverse the migrations. 23 | */ 24 | public function down(): void 25 | { 26 | Schema::dropIfExists('oauth_personal_access_clients'); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /security/database/migrations/2024_06_04_130738_create_oauth_refresh_tokens_table.php: -------------------------------------------------------------------------------- 1 | string('id', 100)->primary(); 16 | $table->string('access_token_id', 100)->index(); 17 | $table->boolean('revoked'); 18 | $table->dateTime('expires_at')->nullable(); 19 | }); 20 | } 21 | 22 | /** 23 | * Reverse the migrations. 24 | */ 25 | public function down(): void 26 | { 27 | Schema::dropIfExists('oauth_refresh_tokens'); 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /security/database/migrations/2024_06_04_130739_create_oauth_clients_table.php: -------------------------------------------------------------------------------- 1 | bigIncrements('id'); 16 | $table->unsignedBigInteger('user_id')->nullable()->index(); 17 | $table->string('name'); 18 | $table->string('secret', 100)->nullable(); 19 | $table->string('provider')->nullable(); 20 | $table->text('redirect'); 21 | $table->boolean('personal_access_client'); 22 | $table->boolean('password_client'); 23 | $table->boolean('revoked'); 24 | $table->timestamps(); 25 | }); 26 | } 27 | 28 | /** 29 | * Reverse the migrations. 30 | */ 31 | public function down(): void 32 | { 33 | Schema::dropIfExists('oauth_clients'); 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /security/database/migrations/2024_06_04_130740_create_oauth_access_tokens_table.php: -------------------------------------------------------------------------------- 1 | string('id', 100)->primary(); 16 | $table->unsignedBigInteger('user_id')->nullable()->index(); 17 | $table->unsignedBigInteger('client_id'); 18 | $table->string('name')->nullable(); 19 | $table->text('scopes')->nullable(); 20 | $table->boolean('revoked'); 21 | $table->timestamps(); 22 | $table->dateTime('expires_at')->nullable(); 23 | }); 24 | } 25 | 26 | /** 27 | * Reverse the migrations. 28 | */ 29 | public function down(): void 30 | { 31 | Schema::dropIfExists('oauth_access_tokens'); 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /security/database/migrations/2024_06_04_130741_create_oauth_auth_codes_table.php: -------------------------------------------------------------------------------- 1 | string('id', 100)->primary(); 16 | $table->unsignedBigInteger('user_id')->index(); 17 | $table->unsignedBigInteger('client_id'); 18 | $table->text('scopes')->nullable(); 19 | $table->boolean('revoked'); 20 | $table->dateTime('expires_at')->nullable(); 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | */ 27 | public function down(): void 28 | { 29 | Schema::dropIfExists('oauth_auth_codes'); 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /security/docker/php.ini: -------------------------------------------------------------------------------- 1 | [PHP] 2 | post_max_size = 100M 3 | upload_max_filesize = 100M 4 | variables_order = EGPCS 5 | pcov.directory = . 6 | 7 | extension=rdkafka.so 8 | -------------------------------------------------------------------------------- /security/docker/start-container: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [ "$SUPERVISOR_PHP_USER" != "root" ] && [ "$SUPERVISOR_PHP_USER" != "app" ]; then 4 | echo "You should set SUPERVISOR_PHP_USER to either 'app' or 'root'." 5 | exit 1 6 | fi 7 | 8 | if [ ! -z "$WWWUSER" ]; then 9 | usermod -u $WWWUSER app 10 | fi 11 | 12 | if [ ! -d /.composer ]; then 13 | mkdir /.composer 14 | fi 15 | 16 | chmod -R ugo+rw /.composer 17 | 18 | if [ $# -gt 0 ]; then 19 | if [ "$SUPERVISOR_PHP_USER" = "root" ]; then 20 | exec "$@" 21 | else 22 | exec gosu $WWWUSER "$@" 23 | fi 24 | else 25 | exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf 26 | fi 27 | -------------------------------------------------------------------------------- /security/docker/supervisord.conf: -------------------------------------------------------------------------------- 1 | [supervisord] 2 | nodaemon=true 3 | user=root 4 | logfile=/var/log/supervisor/supervisord.log 5 | pidfile=/var/run/supervisord.pid 6 | 7 | [program:php] 8 | command=%(ENV_SUPERVISOR_PHP_COMMAND)s 9 | user=%(ENV_SUPERVISOR_PHP_USER)s 10 | environment=APP_IN_DOCKER="1" 11 | stdout_logfile=/dev/stdout 12 | stdout_logfile_maxbytes=0 13 | stderr_logfile=/dev/stderr 14 | stderr_logfile_maxbytes=0 15 | 16 | [program:worker] 17 | command=%(ENV_SUPERVISOR_WORKER_COMMAND)s 18 | user=%(ENV_SUPERVISOR_PHP_USER)s 19 | environment=APP_IN_DOCKER="1" 20 | stdout_logfile=/dev/stdout 21 | stdout_logfile_maxbytes=0 22 | stderr_logfile=/dev/stderr 23 | stderr_logfile_maxbytes=0 24 | -------------------------------------------------------------------------------- /security/public/.htaccess: -------------------------------------------------------------------------------- 1 |