346 Commits

Author SHA1 Message Date
Arnaud Delcasse
6112f6f7aa fix: assets web Dex dans /web 2026-03-03 11:16:12 +01:00
Arnaud Delcasse
a7ecc4f82e fix: set workdir as / in dockerfile 2026-03-03 05:55:35 +01:00
Arnaud Delcasse
a40a7e2712 fix: bump golang to 1.25, remove integration tests 2026-03-03 00:02:19 +01:00
Arnaud Delcasse
1787a90909 Migrate CI to GitLab, clean up Dockerfile and repo 2026-03-02 20:41:59 +01:00
Arnaud Delcasse
722c89e86a Replace Fosite OIDC provider with embedded Dex
All checks were successful
Build and Push Docker Image / build_and_push (push) Successful in 2m26s
2026-03-02 20:08:06 +01:00
Arnaud Delcasse
52a6e25bc3 Migrate module path to gitlab.com/mobicoop/solidarity
All checks were successful
Build and Push Docker Image / build_and_push (push) Successful in 2m6s
2026-03-02 17:30:39 +01:00
Arnaud Delcasse
bc7ba530d4 Add metadate management in grpc
All checks were successful
Build and Push Docker Image / build_and_push (push) Successful in 2m7s
2026-01-14 00:38:18 +01:00
Arnaud Delcasse
44f5a3d182 dete accounts
All checks were successful
Build and Push Docker Image / build_and_push (push) Successful in 2m1s
2026-01-13 15:33:38 +01:00
Arnaud Delcasse
c958736472 fix duplicate accounts
All checks were successful
Build and Push Docker Image / build_and_push (push) Successful in 2m3s
2026-01-13 13:05:06 +01:00
Arnaud Delcasse
db5bcc292b fix duplicate accounts
All checks were successful
Build and Push Docker Image / build_and_push (push) Successful in 2m2s
2026-01-13 12:56:35 +01:00
Arnaud Delcasse
0c982c8f47 fix duplicate accounts
All checks were successful
Build and Push Docker Image / build_and_push (push) Successful in 2m22s
2026-01-13 12:38:46 +01:00
Arnaud Delcasse
b0b3de1f63 fix build issue with old golang versions
All checks were successful
Build and Push Docker Image / build_and_push (push) Successful in 1m56s
2026-01-05 23:56:42 +01:00
Arnaud Delcasse
99a8502a89 tidy
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 1m48s
2026-01-05 23:44:13 +01:00
Arnaud Delcasse
a362fd6ec5 resolve conflicts
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 1m5s
2026-01-05 23:40:17 +01:00
5e4cea0bb3 Remove fmt.Println and add Zerolog logging system
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 1m2s
2024-11-11 20:35:17 +01:00
4ae6aa7a90 edit build.yml - edit metadata step
All checks were successful
Build and Push Docker Image / build_and_push (push) Successful in 1m35s
2024-04-03 11:31:27 +02:00
c784657da2 edit build.yml - add metadata step
All checks were successful
Build and Push Docker Image / build_and_push (push) Successful in 1m38s
2024-04-03 11:23:59 +02:00
66c87b16ff edit build.yml - back to base
All checks were successful
Build and Push Docker Image / build_and_push (push) Successful in 1m34s
2024-04-03 11:15:04 +02:00
284e3c918a edit build.yml - back to base
All checks were successful
Build and Push Docker Image / build_and_push (push) Successful in 1m36s
2024-04-03 11:08:35 +02:00
053066b511 edit build.yml - try if for tag
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 38s
2024-04-03 11:04:58 +02:00
b028120e47 edit build.yml - try if for tag
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 37s
2024-04-03 11:03:07 +02:00
d2a8c57274 edit build.yml - try if for tag
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 39s
2024-04-03 10:59:18 +02:00
140d366894 edit build.yml - edit flavor
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 36s
2024-04-03 10:55:13 +02:00
a70ef04ffd edit build.yml - edit flavor
All checks were successful
Build and Push Docker Image / build_and_push (push) Successful in 1m34s
2024-04-03 10:24:09 +02:00
4c787bdc86 edit build.yml - add flavor
All checks were successful
Build and Push Docker Image / build_and_push (push) Successful in 1m32s
2024-04-03 10:19:14 +02:00
ae04ab23fc edit build.yml - add buil on tags
All checks were successful
Build and Push Docker Image / build_and_push (push) Successful in 1m33s
2024-04-03 10:00:47 +02:00
e192d2253f edit folder .github to .gitea
All checks were successful
Build and Push Docker Image / build_and_push (push) Successful in 1m38s
2024-03-27 13:41:32 +01:00
d588fe2b67 comment postgres config & add mongodb config in config.go
All checks were successful
Build and Push Docker Image / build_and_push (push) Successful in 1m44s
2024-03-27 13:32:50 +01:00
2501dabdba Try Docker Buildx with Kubernetes driver
All checks were successful
Build and Push Docker Image / build_and_push (push) Successful in 1m35s
2024-03-24 23:12:54 +01:00
9486551ee5 Try Docker Buildx with Kubernetes driver
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 21s
2024-03-24 23:02:53 +01:00
170b599f54 Try repository token
All checks were successful
Build and Push Docker Image / checkout_repository (push) Successful in 1m30s
2024-03-24 20:14:28 +01:00
8891517866 Try repository token
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 5s
2024-03-24 20:04:50 +01:00
901faeadc3 Try repository token
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 5s
2024-03-24 20:00:26 +01:00
f469e1da01 test secrets
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 6s
2024-03-22 16:22:05 +01:00
c6c7cd72e4 test secrets
All checks were successful
Build and Push Docker Image / checkout_repository (push) Successful in 1m21s
2024-03-22 15:04:43 +01:00
9fe3d6b6bc test secrets
All checks were successful
Build and Push Docker Image / checkout_repository (push) Successful in 5s
2024-03-22 15:02:03 +01:00
4f3b3b12b3 test secrets
All checks were successful
Build and Push Docker Image / checkout_repository (push) Successful in 5s
2024-03-22 14:58:33 +01:00
8ae62e7aef test secrets
All checks were successful
Build and Push Docker Image / checkout_repository (push) Successful in 1m13s
2024-03-22 14:53:29 +01:00
461f5d1f5f test secrets
All checks were successful
Build and Push Docker Image / checkout_repository (push) Successful in 1m17s
2024-03-22 14:51:46 +01:00
b9f3c0e074 test secrets
All checks were successful
Build and Push Docker Image / checkout_repository (push) Successful in 1m19s
2024-03-22 14:48:34 +01:00
8c427b45bb test secrets
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 5s
2024-03-22 14:47:08 +01:00
5d78a88975 test secrets
All checks were successful
Build and Push Docker Image / checkout_repository (push) Successful in 1m16s
2024-03-22 14:40:06 +01:00
7728a7d0a4 test secrets
All checks were successful
Build and Push Docker Image / checkout_repository (push) Successful in 1m13s
2024-03-22 14:23:44 +01:00
d22c69542d test secrets
All checks were successful
Build and Push Docker Image / checkout_repository (push) Successful in 1m15s
2024-03-22 14:22:17 +01:00
d5ac13cc2e test secrets
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 5s
2024-03-22 14:18:53 +01:00
7e2210e5cc test secrets
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 5s
2024-03-22 14:18:29 +01:00
c91fbccf34 test secrets
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 5s
2024-03-22 14:17:28 +01:00
597e01d290 test secrets
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 5s
2024-03-22 14:16:48 +01:00
18e40b975d test secrets
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 5s
2024-03-22 14:15:16 +01:00
5493dca7ef test secrets
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 5s
2024-03-22 14:13:08 +01:00
d27c2a266a test secrets
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 5s
2024-03-22 14:12:07 +01:00
146eb44ffe test secrets
All checks were successful
Build and Push Docker Image / checkout_repository (push) Successful in 1m16s
2024-03-22 14:10:35 +01:00
cc1fee615b test secrets
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 4s
2024-03-22 14:07:59 +01:00
35e84a6121 test secrets
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 5s
2024-03-22 14:07:32 +01:00
39e4d265cb test secrets
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 5s
2024-03-22 14:05:23 +01:00
15649e452a test secrets 2024-03-22 14:03:52 +01:00
2c79e9eca6 test secrets 2024-03-22 14:02:39 +01:00
d950e799e1 test secrets
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 5s
2024-03-22 13:50:25 +01:00
f56de46ed9 test secrets
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 5s
2024-03-22 13:49:57 +01:00
6ca42da674 test secrets
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 5s
2024-03-22 13:49:19 +01:00
3fa71d8b2e test secrets
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 5s
2024-03-22 13:47:38 +01:00
6629c50aa5 test secrets
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 6s
2024-03-22 13:44:22 +01:00
ff11bd78b0 test secrets
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 5s
2024-03-22 13:43:50 +01:00
0c34321400 test secrets
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 5s
2024-03-22 13:43:12 +01:00
b6cec61b31 test secrets
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 5s
2024-03-22 13:39:27 +01:00
e7d9369929 test secrets
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 4s
2024-03-22 13:35:17 +01:00
f05ea0af06 test secrets
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 5s
2024-03-22 13:34:06 +01:00
c1c89c637c test secrets
All checks were successful
Build and Push Docker Image / checkout_repository (push) Successful in 1m36s
2024-03-22 13:32:09 +01:00
8663a8b400 test secrets
All checks were successful
Build and Push Docker Image / checkout_repository (push) Successful in 1m28s
2024-03-22 12:03:10 +01:00
744863873e test secrets
All checks were successful
Build and Push Docker Image / checkout_repository (push) Successful in 1m12s
2024-03-22 10:31:31 +01:00
dfd1c964d7 test secrets
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 5s
2024-03-22 10:30:09 +01:00
932e5ad90f test secrets
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 6s
2024-03-22 10:17:36 +01:00
fe0f6dd7f6 test secrets
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 5s
2024-03-22 10:15:14 +01:00
31ac6306c0 test secrets
All checks were successful
Build and Push Docker Image / checkout_repository (push) Successful in 1m18s
2024-03-22 10:12:44 +01:00
5a0bf30060 test secrets
All checks were successful
Build and Push Docker Image / checkout_repository (push) Successful in 1m29s
2024-03-22 10:10:24 +01:00
24e619b4a9 test secrets
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 5s
2024-03-22 10:09:38 +01:00
4917662c49 test secrets
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 5s
2024-03-22 10:07:57 +01:00
12b02788fc test secrets
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 5s
2024-03-22 10:06:50 +01:00
4fedd2a72f test secrets
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 6s
2024-03-22 10:05:07 +01:00
0c7d2f22b7 Try with Buildah
All checks were successful
Build and Push Docker Image / checkout_repository (push) Successful in 1m20s
2024-03-22 09:28:26 +01:00
7ad30a24cf Try with Buildah 2024-03-22 09:27:04 +01:00
4ce7c8d00f Try with Buildah
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 22s
2024-03-22 09:18:09 +01:00
7dd32f8e68 Try with Buildah
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 23s
2024-03-22 10:14:52 +01:00
632d99458a Try with Buildah
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 23s
2024-03-22 10:06:27 +01:00
f86693da90 Try with Buildah
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 21s
2024-03-22 08:51:34 +01:00
678d1cef20 Try with Buildah
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 23s
2024-03-22 08:47:28 +01:00
a14f418580 Try with Buildah
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 13s
2024-03-22 08:46:00 +01:00
3f1d407a8f Try with Kaniko
All checks were successful
Build and Push Docker Image / checkout_repository (push) Successful in 1m18s
2024-03-21 19:51:35 +01:00
de98447171 Try with Kaniko
All checks were successful
Build and Push Docker Image / checkout_repository (push) Successful in 1m54s
2024-03-21 19:49:00 +01:00
2ca47bd7a1 add kubernetes driver
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 31s
2024-03-21 19:30:24 +01:00
604322aa25 test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 31s
2024-03-21 11:41:21 +01:00
a3ee7cc98e test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 7s
2024-03-21 11:11:41 +01:00
e38fb54459 test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 35s
2024-03-21 11:09:19 +01:00
13680dba9b test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 54s
2024-03-21 11:07:04 +01:00
74366a8cdb test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 7s
2024-03-21 11:00:24 +01:00
197510cda8 test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 8s
2024-03-21 10:59:05 +01:00
974a8b071a test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 7s
2024-03-21 10:58:17 +01:00
b253f4159e test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 8s
2024-03-21 10:47:09 +01:00
0411673842 test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 13s
2024-03-21 10:46:21 +01:00
122d0cf7a7 test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 4s
2024-03-21 10:45:02 +01:00
23c399cf35 test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 2s
2024-03-21 10:32:01 +01:00
a76e039e82 test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 2s
2024-03-21 10:31:40 +01:00
e9b9dd889c test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 3s
2024-03-21 10:25:16 +01:00
784173e9ee test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 13s
2024-03-21 10:23:40 +01:00
a02870f2f8 test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 2s
2024-03-20 13:27:21 +01:00
ca8c6319d5 test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 6s
2024-03-20 13:22:16 +01:00
6f08957805 test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 7s
2024-03-20 13:20:33 +01:00
b87f21d6f7 test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 7s
2024-03-20 13:19:05 +01:00
ba05c496b2 test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 8s
2024-03-20 13:18:41 +01:00
d456eb80d4 test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 7s
2024-03-20 13:11:42 +01:00
7c4a3f7a37 test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 7s
2024-03-20 13:09:55 +01:00
a6f7116e03 test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 6s
2024-03-20 13:08:25 +01:00
22a5a692d0 test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 7s
2024-03-20 13:08:05 +01:00
cf352c6911 test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 6s
2024-03-20 13:05:54 +01:00
0c26ed9b08 test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 7s
2024-03-20 13:05:11 +01:00
22647dcf11 test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 7s
2024-03-20 13:03:41 +01:00
f21e6d2cef test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 6s
2024-03-20 13:02:59 +01:00
6b1b4d6624 test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 7s
2024-03-20 12:59:00 +01:00
379a7fa4ed test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 4s
2024-03-20 12:56:28 +01:00
de604ac77b test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 7s
2024-03-20 12:55:36 +01:00
b3fa9e3b38 test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 7s
2024-03-20 12:53:16 +01:00
3f8fa2d6ab test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 3s
2024-03-20 12:34:13 +01:00
d24ed53b45 test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 6s
2024-03-20 12:32:40 +01:00
11497f8cc4 test
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 1s
2024-03-20 11:52:33 +01:00
c5c99dbe3c test
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 23s
2024-03-20 11:51:39 +01:00
428fa558e0 test
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 9s
2024-03-20 11:51:01 +01:00
ce9f17735c test
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 5s
2024-03-20 11:50:21 +01:00
bac39121bd test
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 0s
2024-03-20 11:46:03 +01:00
531ff72b9e test
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 5s
2024-03-20 11:42:44 +01:00
71a6df958e test
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 1s
2024-03-20 11:41:05 +01:00
0f41ecfce0 test
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 5s
2024-03-20 11:38:59 +01:00
2db156dbed test
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 11s
2024-03-20 11:34:30 +01:00
0998e825a4 test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 2s
2024-03-20 11:25:23 +01:00
68e1589fd1 test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 1s
2024-03-20 11:23:45 +01:00
d36abf1c23 test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 4s
2024-03-20 11:21:00 +01:00
9bb366864a test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 7s
2024-03-20 11:19:30 +01:00
aef4362b04 test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 4s
2024-03-20 11:18:11 +01:00
b99dfde7e1 test
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 19s
2024-03-20 11:11:11 +01:00
af2767e9de test
All checks were successful
Build and Push Docker Image / checkout_repository (push) Successful in 24s
2024-03-20 11:09:32 +01:00
b7d0b6cda8 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / test (push) Failing after 10s
2024-03-15 13:56:02 +01:00
b4dfd1a173 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / test (push) Failing after 11s
2024-03-15 13:40:22 +01:00
d4eade0228 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / test (push) Failing after 10s
2024-03-15 12:08:09 +01:00
99d1e55fa8 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / test (push) Failing after 15s
2024-03-15 12:06:15 +01:00
11077fd56f test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / test (push) Failing after 5s
2024-03-15 12:03:46 +01:00
ddf002ee11 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / test (push) Failing after 1m16s
2024-03-15 12:01:12 +01:00
ac8e704ed7 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / test (push) Failing after 1m14s
2024-03-15 11:59:11 +01:00
fca47a69a3 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / test (push) Failing after 1m14s
2024-03-15 11:57:11 +01:00
151e86dbee test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / test (push) Failing after 26s
2024-03-15 11:56:23 +01:00
bd28920cdc test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / test (push) Failing after 6s
2024-03-15 11:52:45 +01:00
cebf885278 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / test (push) Failing after 16s
2024-03-15 11:50:38 +01:00
c6ec354d6d test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / test (push) Failing after 16s
2024-03-15 11:49:36 +01:00
09a72d4b44 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / test (push) Failing after 12s
2024-03-15 11:48:53 +01:00
f9fea0864a test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / test (push) Failing after 33s
2024-03-15 11:45:59 +01:00
09c7d11188 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / test (push) Failing after 13s
2024-03-15 11:45:26 +01:00
62a756d2f3 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / test (push) Failing after 9s
2024-03-15 11:44:59 +01:00
f1c77bfebf test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / test (push) Failing after 10s
2024-03-15 11:36:17 +01:00
e0f2693f09 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / test (push) Failing after 9s
2024-03-15 11:34:40 +01:00
c36af927be test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / test (push) Failing after 12s
2024-03-15 11:33:54 +01:00
2ad8530736 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / test (push) Failing after 11s
2024-03-15 11:32:17 +01:00
49dc3872c5 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / test (push) Failing after 11s
2024-03-15 11:31:54 +01:00
4222a348a4 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / test (push) Failing after 12s
2024-03-15 11:31:13 +01:00
618c9b9206 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / test (push) Failing after 13s
2024-03-15 11:15:55 +01:00
47b86968d4 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / test (push) Failing after 12s
2024-03-15 11:15:25 +01:00
4ef0c875af test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / test (push) Failing after 12s
2024-03-15 11:14:44 +01:00
0f6a65d1a4 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / test (push) Failing after 11s
2024-03-15 11:13:56 +01:00
379fb05841 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / test (push) Failing after 12s
2024-03-15 11:12:54 +01:00
99b72aa390 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / test (push) Failing after 11s
2024-03-15 11:11:55 +01:00
75b222a3c0 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / test (push) Failing after 15s
2024-03-15 11:10:23 +01:00
f971df6ead test workflow build and push on gitea registry 2024-03-15 11:09:43 +01:00
e45fc1b52e test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / test (push) Failing after 12s
2024-03-15 11:09:04 +01:00
42b48c4ce1 test workflow build and push on gitea registry 2024-03-15 11:07:15 +01:00
0d984243f8 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / test (push) Failing after 0s
2024-03-15 11:06:42 +01:00
7c18d78686 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / test (push) Failing after 12s
2024-03-15 11:04:51 +01:00
af31c9676b test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / test (push) Failing after 12s
2024-03-15 11:04:24 +01:00
cff757eff3 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / test (push) Failing after 12s
2024-03-15 11:01:55 +01:00
130f048eb1 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / test (push) Failing after 12s
2024-03-15 10:58:48 +01:00
b6a2edb179 test workflow build and push on gitea registry
All checks were successful
Build and Push Docker Image / test (push) Successful in 11s
2024-03-15 10:56:45 +01:00
71d7c3ce61 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / test (push) Failing after 11s
2024-03-15 10:55:34 +01:00
599f66d065 test workflow build and push on gitea registry
All checks were successful
Build and Push Docker Image / test (push) Successful in 7s
2024-03-15 10:54:26 +01:00
eb066ba888 test workflow build and push on gitea registry
All checks were successful
Build and Push Docker Image / test (push) Successful in 6s
2024-03-15 10:53:46 +01:00
9e70d3941d test workflow build and push on gitea registry
All checks were successful
Build and Push Docker Image / test (push) Successful in 3s
2024-03-15 10:52:24 +01:00
a9eb91bd83 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 7s
Build and Push Docker Image / login_docker_registry (push) Successful in 7s
Build and Push Docker Image / build_and_push_image (push) Failing after 3s
2024-03-15 09:57:38 +01:00
472796c444 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 8s
Build and Push Docker Image / login_docker_registry (push) Successful in 7s
Build and Push Docker Image / build_and_push_image (push) Failing after 4s
2024-03-15 09:57:01 +01:00
0a43b72819 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 8s
Build and Push Docker Image / login_docker_registry (push) Successful in 6s
Build and Push Docker Image / build_and_push_image (push) Failing after 3s
2024-03-15 09:17:27 +01:00
5f757210ac test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 7s
Build and Push Docker Image / login_docker_registry (push) Successful in 6s
Build and Push Docker Image / build_and_push_image (push) Failing after 3s
2024-03-15 09:11:10 +01:00
d3bdfb24b9 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 8s
Build and Push Docker Image / login_docker_registry (push) Successful in 7s
Build and Push Docker Image / clone_repository (push) Successful in 5s
Build and Push Docker Image / build_and_push_image (push) Failing after 4s
2024-03-15 09:08:38 +01:00
f4b1d75e96 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / login_docker_registry (push) Successful in 6s
Build and Push Docker Image / clone_repository (push) Failing after 1m43s
Build and Push Docker Image / build_and_push_image (push) Has been skipped
2024-03-15 09:00:36 +01:00
2482c64d1c test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 5s
Build and Push Docker Image / login_docker_registry (push) Successful in 6s
Build and Push Docker Image / clone_repository (push) Failing after 6s
Build and Push Docker Image / build_and_push_image (push) Has been skipped
2024-03-15 08:55:56 +01:00
740d14894e test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 8s
Build and Push Docker Image / login_docker_registry (push) Successful in 7s
Build and Push Docker Image / clone_repository (push) Failing after 4s
Build and Push Docker Image / build_and_push_image (push) Has been skipped
2024-03-15 08:54:28 +01:00
68c8941157 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / login_docker_registry (push) Successful in 6s
Build and Push Docker Image / clone_repository (push) Failing after 3s
Build and Push Docker Image / build_and_push_image (push) Has been skipped
2024-03-13 15:35:28 +01:00
42028219ba test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Failing after 5s
Build and Push Docker Image / login_docker_registry (push) Successful in 6s
Build and Push Docker Image / clone_repository (push) Failing after 4s
Build and Push Docker Image / build_and_push_image (push) Has been skipped
2024-03-13 15:34:38 +01:00
546628213f test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 7s
Build and Push Docker Image / login_docker_registry (push) Successful in 5s
Build and Push Docker Image / clone_repository (push) Failing after 3s
Build and Push Docker Image / build_and_push_image (push) Has been skipped
2024-03-13 15:30:12 +01:00
bc318e5b45 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 7s
Build and Push Docker Image / login_docker_registry (push) Successful in 7s
Build and Push Docker Image / clone_repository (push) Successful in 3s
Build and Push Docker Image / build_and_push_image (push) Failing after 3s
2024-03-13 15:29:19 +01:00
a525721aa0 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / login_docker_registry (push) Successful in 5s
Build and Push Docker Image / clone_repository (push) Successful in 3s
Build and Push Docker Image / build_and_push_image (push) Failing after 3s
2024-03-13 15:25:39 +01:00
8fa6f50e38 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / login_docker_registry (push) Successful in 5s
Build and Push Docker Image / clone_repository (push) Successful in 4s
Build and Push Docker Image / build_and_push_image (push) Failing after 4s
2024-03-13 15:22:20 +01:00
54bc0245a9 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 5s
Build and Push Docker Image / login_docker_registry (push) Successful in 5s
Build and Push Docker Image / clone_repository (push) Successful in 4s
Build and Push Docker Image / build_and_push_image (push) Failing after 4s
2024-03-13 15:21:43 +01:00
b135171322 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / login_docker_registry (push) Successful in 5s
Build and Push Docker Image / clone_repository (push) Successful in 3s
Build and Push Docker Image / build_and_push_image (push) Failing after 3s
2024-03-13 15:18:48 +01:00
431233a1df test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / login_docker_registry (push) Successful in 5s
Build and Push Docker Image / clone_repository (push) Successful in 3s
Build and Push Docker Image / build_and_push_image (push) Failing after 3s
2024-03-13 15:16:48 +01:00
108e1f576e test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / login_docker_registry (push) Successful in 5s
Build and Push Docker Image / clone_repository (push) Failing after 3s
Build and Push Docker Image / build_and_push_image (push) Has been skipped
2024-03-13 15:16:16 +01:00
a95f9a49dd test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / login_docker_registry (push) Successful in 5s
Build and Push Docker Image / clone_repository (push) Successful in 3s
Build and Push Docker Image / build_and_push_image (push) Failing after 4s
2024-03-13 15:15:10 +01:00
a8ee047d44 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 5s
Build and Push Docker Image / login_docker_registry (push) Successful in 5s
Build and Push Docker Image / clone_repository (push) Successful in 4s
Build and Push Docker Image / build_and_push_image (push) Failing after 4s
2024-03-13 15:14:08 +01:00
60aab2efa3 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / login_docker_registry (push) Successful in 5s
Build and Push Docker Image / clone_repository (push) Successful in 4s
Build and Push Docker Image / build_and_push_image (push) Failing after 4s
2024-03-13 15:13:25 +01:00
22db0f738f test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / login_docker_registry (push) Successful in 5s
Build and Push Docker Image / clone_repository (push) Successful in 3s
Build and Push Docker Image / build_and_push_image (push) Failing after 4s
2024-03-13 15:12:45 +01:00
cb2ce7bc1b test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / login_docker_registry (push) Successful in 6s
Build and Push Docker Image / clone_repository (push) Successful in 3s
Build and Push Docker Image / build_and_push_image (push) Failing after 4s
2024-03-13 15:10:15 +01:00
747344ce36 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / login_docker_registry (push) Successful in 6s
Build and Push Docker Image / clone_repository (push) Successful in 7s
Build and Push Docker Image / build_and_push_image (push) Failing after 5s
2024-03-13 15:07:27 +01:00
10039d1b4c test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / login_docker_registry (push) Successful in 6s
Build and Push Docker Image / build_and_push_image (push) Failing after 4s
2024-03-13 14:59:59 +01:00
956b4a2d84 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / login_docker_registry (push) Successful in 6s
Build and Push Docker Image / build_and_push_image (push) Failing after 4s
2024-03-13 14:56:45 +01:00
e2558ec3cb test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 5s
Build and Push Docker Image / login_docker_registry (push) Successful in 5s
Build and Push Docker Image / build_and_push_image (push) Failing after 3s
2024-03-13 14:55:57 +01:00
ac1ea1ba2c test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / login_docker_registry (push) Successful in 5s
Build and Push Docker Image / build_and_push_image (push) Failing after 4s
2024-03-13 14:55:11 +01:00
32b948350a test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / login_docker_registry (push) Successful in 5s
Build and Push Docker Image / build_and_push_image (push) Failing after 8s
2024-03-13 14:54:28 +01:00
0202348b0c test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / login_docker_registry (push) Successful in 6s
Build and Push Docker Image / build_and_push_image (push) Failing after 7s
2024-03-13 14:53:28 +01:00
e5cb07c01e test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 5s
Build and Push Docker Image / login_docker_registry (push) Successful in 6s
Build and Push Docker Image / build_and_push_image (push) Failing after 8s
2024-03-13 14:52:04 +01:00
86eddf894c test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / login_docker_registry (push) Successful in 6s
Build and Push Docker Image / build_and_push_image (push) Failing after 6s
2024-03-13 14:50:42 +01:00
ada0e51864 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / login_docker_registry (push) Successful in 5s
Build and Push Docker Image / build_and_push_image (push) Failing after 6s
2024-03-13 14:49:02 +01:00
aa1f12db77 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 5s
Build and Push Docker Image / login_docker_registry (push) Successful in 6s
Build and Push Docker Image / build_and_push_image (push) Failing after 6s
2024-03-13 14:47:32 +01:00
9cbce9c764 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / build_and_push_image (push) Failing after 6s
2024-03-13 14:46:07 +01:00
ad69095f72 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / login_docker_registry (push) Successful in 6s
Build and Push Docker Image / build_and_push_image (push) Failing after 4s
2024-03-13 14:44:01 +01:00
414ba0809d test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / login_docker_registry (push) Successful in 6s
Build and Push Docker Image / build_and_push_image (push) Failing after 1m8s
2024-03-13 14:40:21 +01:00
74bfd69f00 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 5s
Build and Push Docker Image / login_docker_registry (push) Successful in 5s
Build and Push Docker Image / build_and_push_image (push) Failing after 1m20s
2024-03-13 14:34:48 +01:00
2cc271561d test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 5s
Build and Push Docker Image / login_docker_registry (push) Successful in 6s
Build and Push Docker Image / build_and_push_image (push) Failing after 23s
2024-03-13 14:33:47 +01:00
9b836bf4c8 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / login_docker_registry (push) Successful in 5s
Build and Push Docker Image / build_and_push_image (push) Failing after 9s
2024-03-13 14:32:58 +01:00
eb7ff92322 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 5s
Build and Push Docker Image / login_docker_registry (push) Successful in 6s
Build and Push Docker Image / build_and_push_image (push) Failing after 9s
2024-03-13 14:26:09 +01:00
9a87fe7943 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / login_docker_registry (push) Successful in 5s
Build and Push Docker Image / build_and_push_image (push) Failing after 47s
2024-03-13 14:22:29 +01:00
bb21558ee1 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 5s
Build and Push Docker Image / login_docker_registry (push) Successful in 6s
Build and Push Docker Image / build_and_push_image (push) Failing after 48s
2024-03-13 14:20:27 +01:00
eabb4bdae8 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 5s
Build and Push Docker Image / login_docker_registry (push) Successful in 6s
Build and Push Docker Image / build_and_push_image (push) Failing after 48s
2024-03-13 14:17:44 +01:00
7eabb4f9f5 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 5s
Build and Push Docker Image / login_docker_registry (push) Successful in 6s
Build and Push Docker Image / build_and_push_image (push) Failing after 48s
2024-03-13 14:15:46 +01:00
386a848291 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / login_docker_registry (push) Successful in 5s
Build and Push Docker Image / build_and_push_image (push) Failing after 47s
2024-03-13 14:14:08 +01:00
fb17476487 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 5s
Build and Push Docker Image / login_docker_registry (push) Successful in 6s
Build and Push Docker Image / build_and_push_image (push) Failing after 38s
2024-03-13 14:12:17 +01:00
c2dcb594b2 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / login_docker_registry (push) Successful in 5s
Build and Push Docker Image / build_and_push_image (push) Failing after 8s
2024-03-13 14:11:27 +01:00
2cbe3eb6d4 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 5s
Build and Push Docker Image / login_docker_registry (push) Successful in 6s
Build and Push Docker Image / build_and_push_image (push) Failing after 13s
2024-03-13 14:06:06 +01:00
d06d7a5ef3 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / login_docker_registry (push) Successful in 5s
Build and Push Docker Image / build_and_push_image (push) Failing after 36s
2024-03-13 14:02:52 +01:00
558251f5f3 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / login_docker_registry (push) Successful in 5s
Build and Push Docker Image / prepare_environment (push) Failing after 1m55s
Build and Push Docker Image / build_and_push_image (push) Failing after 10s
2024-03-13 12:44:16 +01:00
1a283360aa test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 5s
Build and Push Docker Image / login_docker_registry (push) Successful in 6s
Build and Push Docker Image / prepare_environment (push) Successful in 9s
Build and Push Docker Image / build_and_push_image (push) Failing after 4s
2024-03-13 12:40:02 +01:00
4436c6ad5e test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 5s
Build and Push Docker Image / login_docker_registry (push) Successful in 6s
Build and Push Docker Image / build_and_push_image (push) Failing after 37s
2024-03-13 12:36:13 +01:00
76011f9644 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 5s
Build and Push Docker Image / login_docker_registry (push) Successful in 5s
Build and Push Docker Image / build_and_push_image (push) Failing after 4s
2024-03-13 12:33:34 +01:00
874e18e6cc test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 5s
Build and Push Docker Image / login_docker_registry (push) Successful in 5s
Build and Push Docker Image / build_and_push_image (push) Failing after 3s
2024-03-13 12:32:45 +01:00
0561fdf487 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 7s
Build and Push Docker Image / login_docker_registry (push) Successful in 5s
Build and Push Docker Image / build_and_push_image (push) Failing after 3s
2024-03-13 12:31:39 +01:00
414e9db9cf test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / login_docker_registry (push) Successful in 6s
Build and Push Docker Image / build_and_push_image (push) Failing after 4s
2024-03-13 12:26:43 +01:00
2259eee40b test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / login_docker_registry (push) Successful in 5s
Build and Push Docker Image / build_and_push_image (push) Failing after 3s
2024-03-13 12:22:15 +01:00
895f0f4852 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 5s
Build and Push Docker Image / login_docker_registry (push) Successful in 6s
Build and Push Docker Image / build_and_push_image (push) Failing after 3s
2024-03-13 12:20:08 +01:00
d2624cea51 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 5s
Build and Push Docker Image / login_docker_registry (push) Successful in 5s
Build and Push Docker Image / build_and_push_image (push) Failing after 2s
2024-03-13 12:18:23 +01:00
e846f5adf3 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / login_docker_registry (push) Successful in 5s
Build and Push Docker Image / build_and_push_image (push) Failing after 3s
2024-03-13 12:16:26 +01:00
6d9d24f643 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / login_docker_registry (push) Successful in 5s
Build and Push Docker Image / build_and_push_image (push) Failing after 3s
2024-03-13 12:14:58 +01:00
c42be42302 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / login_docker_registry (push) Successful in 6s
Build and Push Docker Image / build_and_push_image (push) Failing after 2s
2024-03-13 12:14:10 +01:00
73b7f8f907 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / login_docker_registry (push) Successful in 5s
Build and Push Docker Image / build_and_push_image (push) Failing after 3s
2024-03-13 12:12:43 +01:00
2433a4186c test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 5s
Build and Push Docker Image / login_docker_registry (push) Successful in 6s
Build and Push Docker Image / build_and_push_image (push) Failing after 9s
2024-03-13 12:11:49 +01:00
e16600ddd8 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / login_docker_registry (push) Successful in 6s
Build and Push Docker Image / build_and_push_image (push) Failing after 3s
2024-03-13 12:08:17 +01:00
c073ae6919 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / login_docker_registry (push) Successful in 5s
Build and Push Docker Image / build_and_push_image (push) Failing after 3s
2024-03-13 12:03:55 +01:00
93d220759d test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 5s
Build and Push Docker Image / login_docker_registry (push) Failing after 5s
Build and Push Docker Image / build_and_push_image (push) Failing after 3s
2024-03-13 12:02:51 +01:00
5a92886103 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / login_docker_registry (push) Failing after 5s
Build and Push Docker Image / build_and_push_image (push) Failing after 3s
2024-03-13 12:01:42 +01:00
acb9b06f2a test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / build_and_push_image (push) Failing after 5s
2024-03-13 11:57:22 +01:00
538d39b70a test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 5s
Build and Push Docker Image / build_and_push_image (push) Failing after 6s
2024-03-13 11:56:39 +01:00
cfbe46b95b test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 5s
Build and Push Docker Image / build_and_push_image (push) Failing after 1s
2024-03-13 11:55:53 +01:00
3d2cdde8e3 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 5s
Build and Push Docker Image / build_and_push_image (push) Failing after 10s
2024-03-13 11:54:56 +01:00
8b1846d16a test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / checkout_repository (push) Successful in 6s
Build and Push Docker Image / build_and_push_image (push) Failing after 9s
2024-03-13 11:52:52 +01:00
20bea61613 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 8s
2024-03-13 11:48:27 +01:00
d70449602d test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 2s
2024-03-13 11:47:43 +01:00
87ea725e51 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 12s
2024-03-13 11:46:36 +01:00
ef6f214cf6 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 20s
2024-03-13 11:43:28 +01:00
54c5b1e334 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 3s
2024-03-13 11:38:17 +01:00
50bb477493 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 3s
2024-03-13 11:37:46 +01:00
1c3be9f998 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 16s
2024-03-13 11:24:30 +01:00
255edf3390 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 11s
2024-03-13 11:23:49 +01:00
cc4629bbbd test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 16s
2024-03-13 10:18:33 +01:00
75050500b3 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 13s
2024-03-13 10:17:52 +01:00
96e0debef2 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 2s
2024-03-13 10:17:28 +01:00
dd9ea96f58 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 15s
2024-03-13 10:14:26 +01:00
703bbaf199 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Has been cancelled
2024-03-13 10:04:14 +01:00
0c3e7f8c45 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 49s
2024-03-13 09:31:16 +01:00
8cf1414944 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 44s
2024-03-13 09:21:01 +01:00
d5b575d9f9 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 42s
2024-03-13 09:16:22 +01:00
8f6dab04dc test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 47s
2024-03-13 09:10:10 +01:00
ecb4e5e219 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 20s
2024-03-13 09:08:57 +01:00
dba7d992d4 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 16s
2024-03-13 09:04:16 +01:00
d15a8be61a test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 38s
2024-03-08 17:34:19 +01:00
e02d969e52 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 42s
2024-03-08 17:32:22 +01:00
6b25143194 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 40s
2024-03-08 17:28:17 +01:00
066fe76a79 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 38s
2024-03-08 17:24:43 +01:00
afd4c41628 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 41s
2024-03-08 17:23:20 +01:00
5f3a9c4b89 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 37s
2024-03-08 17:19:36 +01:00
c7e3b96483 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 15s
2024-03-08 17:18:13 +01:00
001db0ec88 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 15s
2024-03-08 17:07:04 +01:00
f65721edf9 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 13s
2024-03-08 17:02:19 +01:00
e1f50d20c8 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 12s
2024-03-08 17:00:56 +01:00
cd7aa0f78e test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 12s
2024-03-08 16:58:32 +01:00
e933481eb3 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 14s
2024-03-08 16:53:28 +01:00
8865c48bb7 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 1m1s
2024-03-08 09:39:38 +01:00
6c7d67911a test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 54s
2024-03-08 09:26:30 +01:00
235e8c3ab5 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 56s
2024-03-08 09:25:25 +01:00
af62a79fcc test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 58s
2024-03-07 18:15:06 +01:00
ca65504097 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 9s
2024-03-07 18:12:12 +01:00
13af4fc1ff test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 54s
2024-03-07 18:09:01 +01:00
cbe36e0a9b test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 8s
2024-03-07 18:07:44 +01:00
e8b11218ad test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 8s
2024-03-07 18:07:23 +01:00
9745461048 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 54s
2024-03-07 18:01:45 +01:00
021c70808e test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 55s
2024-03-07 17:58:46 +01:00
04345ef47c test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 52s
2024-03-07 17:56:58 +01:00
76812b32d2 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 52s
2024-03-07 17:55:23 +01:00
17d0ee7f52 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 38s
2024-03-07 17:44:15 +01:00
374cc415b5 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 1m3s
2024-03-07 17:36:01 +01:00
311709f22f test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 31s
2024-03-07 17:33:02 +01:00
4408f007ef test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 44s
2024-03-07 17:31:28 +01:00
77118af695 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 34s
2024-03-07 17:30:38 +01:00
7d37028d93 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 23s
2024-03-07 17:29:54 +01:00
05298cf4b9 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 14s
2024-03-07 17:28:43 +01:00
8943b0aefa test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 21s
2024-03-07 09:24:08 +01:00
11a8839fcd test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 34s
2024-03-07 09:22:20 +01:00
02229478ec test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 36s
2024-03-07 09:14:48 +01:00
576e9f5774 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 35s
2024-03-07 09:13:11 +01:00
b30b9a6247 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 43s
2024-03-07 09:09:26 +01:00
c15d7469ba test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 43s
2024-03-07 09:08:08 +01:00
de14e3c440 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 43s
2024-03-07 09:06:06 +01:00
cb5b30bc47 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 8s
2024-03-07 09:01:16 +01:00
4535715db1 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 43s
2024-03-07 08:58:10 +01:00
08ec14cafe test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 35s
2024-03-07 08:56:32 +01:00
334cf422b1 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 49s
2024-03-06 17:41:04 +01:00
610573393c test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 40s
2024-03-06 16:26:01 +01:00
54ba2cf466 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 48s
2024-03-06 15:01:33 +01:00
82f7e98e94 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 57s
2024-03-06 14:59:01 +01:00
cdeaf22a92 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 40s
2024-03-06 12:21:08 +01:00
3ffca66344 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 38s
2024-03-06 12:20:03 +01:00
b1fbc33792 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Has been cancelled
2024-03-06 12:19:37 +01:00
24e89bd151 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 9s
2024-03-06 12:19:13 +01:00
4cf7fb9eba test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 11s
2024-03-06 12:16:12 +01:00
c89d6f0e00 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 1s
2024-03-06 12:16:03 +01:00
8030c13ff7 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 42s
2024-03-06 12:08:14 +01:00
883f678c1b test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 39s
2024-03-06 12:06:57 +01:00
d84a8594b4 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 37s
2024-03-06 12:05:37 +01:00
ffba1d1cce test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 39s
2024-03-06 12:03:50 +01:00
7be48ecdd8 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 39s
2024-03-06 11:59:35 +01:00
e49374606b test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 40s
2024-03-06 11:56:57 +01:00
240504349a test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 36s
2024-03-06 11:55:32 +01:00
6f70a042e1 test workflow build and push on gitea registry
Some checks failed
Build and Push Docker Image / build_and_push (push) Failing after 1m11s
2024-03-06 11:47:40 +01:00
316ea97e7e test workflow build and push on gitea registry 2024-03-06 11:46:42 +01:00
017beaf722 test Gitea actions
All checks were successful
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 36s
2024-03-06 11:16:39 +01:00
6a74c5166e Merge branch 'dev' of https://git.coopgo.io/coopgo-platform/mobility-accounts into dev 2023-11-27 10:47:48 +01:00
de94bd583f fix sum 2023-11-27 09:03:37 +01:00
3a80acae37 Fix issue with localauth conversion 2023-11-27 09:00:40 +01:00
045bcb7bf6 Merge branch 'master' 2023-11-27 08:52:16 +01:00
56dad2ee7d create branch mika 2023-09-06 13:37:31 +02:00
6f9d57c6d7 run go mod tidy 2023-08-21 14:58:18 +02:00
bde22b9ce9 fixing some issues 2023-07-18 12:38:07 +02:00
bac60f049f restrict migrate function to the right schema, and not the entire database 2023-05-02 20:00:34 +02:00
c6ba00b74f Extend PostgreSQL implementation and unit tests on MongoDB storage 2023-05-02 00:34:33 +02:00
1bf02aa132 Merge branch 'salim' of https://git.coopgo.io/coopgo-platform/mobility-accounts into salim 2023-04-30 13:54:49 +02:00
f5bb2e7c2c Fix issue in mongodb connection 2023-04-30 13:53:20 +02:00
49 changed files with 2130 additions and 3694 deletions

5
.gitignore vendored
View File

@@ -1,3 +1,6 @@
config.yaml config.yaml
.vscode .vscode
__debug_bin .idea/
__debug_bin
mobility-accounts
build/

31
.gitlab-ci.yml Normal file
View File

@@ -0,0 +1,31 @@
stages:
- test
- publish
variables:
GOLANG_VERSION: "1.25"
default:
image: golang:${GOLANG_VERSION}
test:
stage: test
script:
- go test ./...
docker:
stage: publish
image: docker:latest
services:
- docker:dind
variables:
DOCKER_BUILDKIT: "1"
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG
- docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG $CI_REGISTRY_IMAGE:latest
- docker push $CI_REGISTRY_IMAGE:latest
rules:
- if: $CI_COMMIT_TAG

8
.idea/.gitignore generated vendored
View File

@@ -1,8 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View File

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="Go" enabled="true" />
</module>

6
.idea/vcs.xml generated
View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

View File

@@ -1,28 +1,17 @@
FROM golang:alpine as builder FROM golang:alpine AS builder
ARG ACCESS_TOKEN_USR="nothing" WORKDIR /app
ARG ACCESS_TOKEN_PWD="nothing"
RUN apk add --no-cache ca-certificates tzdata
WORKDIR /
# Create a netrc file using the credentials specified using --build-arg
RUN printf "machine git.coopgo.io\n\
login ${ACCESS_TOKEN_USR}\n\
password ${ACCESS_TOKEN_PWD}\n"\
>> ~/.netrc
RUN chmod 600 ~/.netrc
COPY . . COPY . .
RUN go mod download && CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /server RUN CGO_ENABLED=0 go build -o /server
FROM gcr.io/distroless/static:nonroot
WORKDIR /
FROM scratch
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo
COPY --from=builder /server / COPY --from=builder /server /
COPY --from=builder /oidc-provider/templates /oidc-provider/templates COPY --from=builder /app/oidc-provider/web /web
EXPOSE 8080 EXPOSE 8080
EXPOSE 80 EXPOSE 80

View File

@@ -130,8 +130,17 @@ The OIDC provider needs [Etcd v3](https://etcd.io/) (see below for storage consi
COOPGO Mobility Accounts supports the following databases for storage : COOPGO Mobility Accounts supports the following databases for storage :
- [x] MongoDB - [x] MongoDB
- [x] PostgreSQL
Feel free to contribute any other storage option. #### SQL schema
SQL schema for PostgreSQL is available from file `storage/postgresql/schema.hcl` in the [atlasgo Data Definition Language](https://atlasgo.io/getting-started) format
To set your development DB with this schema easily, you can simply use atlasgo CLI :
```
atlas schema apply --url "postgresql://username:password@localhost:5432/coopgo_platform?sslmode=disable"
```
### OpenID Connect provider ### OpenID Connect provider

View File

@@ -7,6 +7,26 @@ import (
) )
func ReadConfig() (*viper.Viper, error) { func ReadConfig() (*viper.Viper, error) {
// defaults := map[string]any{
// "name": "COOPGO Mobility Accounts",
// "dev_env": false,
// "storage": map[string]any{
// "db": map[string]any{
// "type": "psql",
// "psql": map[string]any{
// "user": "postgres",
// "password": "postgres",
// "host": "localhost",
// "port": "5432",
// "dbname": "coopgo_platform",
// "sslmode": "disable",
// "schema": "mobilityaccounts",
// "tables": map[string]any{
// "accounts": "accounts",
// "accounts_auth_local": "accounts_auth_local",
// },
// },
// },
defaults := map[string]any{ defaults := map[string]any{
"name": "COOPGO Mobility Accounts", "name": "COOPGO Mobility Accounts",
"dev_env": false, "dev_env": false,

View File

@@ -1,7 +1,7 @@
module git.coopgo.io/coopgo-platform/mobility-accounts/examples/grpcclient module gitlab.com/mobicoop/solidarity/services/mobility-accounts/examples/grpcclient
require ( require (
git.coopgo.io/coopgo-platform/mobility-accounts v0.0.0 gitlab.com/mobicoop/solidarity/services/mobility-accounts v0.0.0
google.golang.org/grpc v1.48.0 google.golang.org/grpc v1.48.0
) )
@@ -51,6 +51,6 @@ require (
gopkg.in/yaml.v3 v3.0.0 // indirect gopkg.in/yaml.v3 v3.0.0 // indirect
) )
replace git.coopgo.io/coopgo-platform/mobility-accounts => ../../ replace gitlab.com/mobicoop/solidarity/services/mobility-accounts => ../../
go 1.18 go 1.18

View File

@@ -3,23 +3,26 @@ package main
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi" "gitlab.com/mobicoop/solidarity/services/mobility-accounts/grpcapi"
"git.coopgo.io/coopgo-platform/mobility-accounts/storage" "gitlab.com/mobicoop/solidarity/services/mobility-accounts/storage"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"google.golang.org/grpc" "google.golang.org/grpc"
) )
func main() { func main() {
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
if len(os.Args) < 2 { if len(os.Args) < 2 {
fmt.Println("missing JSON file path") log.Error().Msg("missing JSON file path")
return return
} }
conn, err := grpc.Dial("dns:///localhost:8090", grpc.WithInsecure(), grpc.WithDefaultServiceConfig(`{"loadBalancingPolicy":"round_robin"}`)) conn, err := grpc.Dial("dns:///localhost:8090", grpc.WithInsecure(), grpc.WithDefaultServiceConfig(`{"loadBalancingPolicy":"round_robin"}`))
if err != nil { if err != nil {
panic(err) log.Panic().Err(err).Msg("Cannot dial local server")
} }
client := grpcapi.NewMobilityAccountsClient(conn) client := grpcapi.NewMobilityAccountsClient(conn)
@@ -46,5 +49,5 @@ func main() {
panic(err) panic(err)
} }
fmt.Println(string(jsonresponse)) log.Debug().Str("response", string(jsonresponse)).Msg("JSOn response")
} }

140
go.mod
View File

@@ -1,84 +1,118 @@
module git.coopgo.io/coopgo-platform/mobility-accounts module gitlab.com/mobicoop/solidarity/services/mobility-accounts
go 1.18 go 1.24
require ( require (
github.com/google/uuid v1.3.0 ariga.io/atlas v0.31.1-0.20250212144724-069be8033e83
github.com/gorilla/csrf v1.7.1 github.com/dexidp/dex v0.0.0-20250219130842-7d1a7473c8a0
github.com/gorilla/mux v1.8.0 github.com/google/uuid v1.6.0
github.com/lib/pq v1.10.2 github.com/lib/pq v1.10.9
github.com/mitchellh/mapstructure v1.5.0 github.com/mitchellh/mapstructure v1.5.0
github.com/ory/fosite v0.42.2 github.com/rs/zerolog v1.33.0
github.com/santhosh-tekuri/jsonschema/v5 v5.0.0 github.com/santhosh-tekuri/jsonschema/v5 v5.0.0
github.com/spf13/viper v1.15.0 github.com/spf13/viper v1.15.0
go.etcd.io/etcd/client/v3 v3.5.6 github.com/stretchr/testify v1.10.0
go.etcd.io/etcd/client/v3 v3.5.18
go.mongodb.org/mongo-driver v1.11.4 go.mongodb.org/mongo-driver v1.11.4
golang.org/x/crypto v0.6.0 golang.org/x/crypto v0.33.0
google.golang.org/grpc v1.52.0 google.golang.org/grpc v1.70.0
google.golang.org/protobuf v1.28.1 google.golang.org/protobuf v1.36.5
gopkg.in/square/go-jose.v2 v2.5.2-0.20210529014059-a5c7eec3c614
) )
require ( require (
github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 // indirect cloud.google.com/go/auth v0.14.1 // indirect
github.com/cespare/xxhash v1.1.0 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.7 // indirect
cloud.google.com/go/compute/metadata v0.6.0 // indirect
dario.cat/mergo v1.0.1 // indirect
github.com/AppsFlyer/go-sundheit v0.6.0 // indirect
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.3.0 // indirect
github.com/Masterminds/sprig/v3 v3.3.0 // indirect
github.com/agext/levenshtein v1.2.1 // indirect
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
github.com/beevik/etree v1.5.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bmatcuk/doublestar v1.3.4 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/coreos/go-oidc/v3 v3.12.0 // indirect
github.com/coreos/go-semver v0.3.0 // indirect github.com/coreos/go-semver v0.3.0 // indirect
github.com/coreos/go-systemd/v22 v22.3.2 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/dgraph-io/ristretto v0.0.3 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/dexidp/dex/api/v2 v2.3.0 // indirect
github.com/go-stack/stack v1.8.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.8.0 // indirect
github.com/go-asn1-ber/asn1-ber v1.5.7 // indirect
github.com/go-jose/go-jose/v4 v4.0.4 // indirect
github.com/go-ldap/ldap/v3 v3.4.10 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/inflect v0.19.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.2 // indirect github.com/golang/protobuf v1.5.4 // indirect
github.com/golang/snappy v0.0.1 // indirect github.com/golang/snappy v0.0.1 // indirect
github.com/gorilla/securecookie v1.1.1 // indirect github.com/google/go-cmp v0.6.0 // indirect
github.com/gorilla/websocket v1.4.2 // indirect github.com/google/s2a-go v0.1.9 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect
github.com/googleapis/gax-go/v2 v2.14.1 // indirect
github.com/gorilla/handlers v1.5.2 // indirect
github.com/gorilla/mux v1.8.1 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/hashicorp/hcl/v2 v2.16.2 // indirect
github.com/jackc/chunkreader/v2 v2.0.1 // indirect github.com/huandu/xstrings v1.5.0 // indirect
github.com/jackc/pgconn v1.14.0 // indirect github.com/jonboulle/clockwork v0.2.2 // indirect
github.com/jackc/pgio v1.0.0 // indirect github.com/klauspost/compress v1.17.9 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgproto3/v2 v2.3.2 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/pgtype v1.14.0 // indirect
github.com/jackc/pgx/v4 v4.18.1 // indirect
github.com/klauspost/compress v1.13.6 // indirect
github.com/magiconair/properties v1.8.7 // indirect github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/goveralls v0.0.6 // indirect github.com/mattermost/xml-roundtrip-validator v0.1.0 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
github.com/ory/go-acc v0.2.6 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/ory/go-convenience v0.1.0 // indirect
github.com/ory/viper v1.7.5 // indirect
github.com/ory/x v0.0.214 // indirect
github.com/pborman/uuid v1.2.0 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pelletier/go-toml/v2 v2.0.6 // indirect github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.20.5 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.55.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/russellhaering/goxmldsig v1.4.0 // indirect
github.com/sergi/go-diff v1.1.0 // indirect
github.com/shopspring/decimal v1.4.0 // indirect
github.com/spf13/afero v1.9.3 // indirect github.com/spf13/afero v1.9.3 // indirect
github.com/spf13/cast v1.5.0 // indirect github.com/spf13/cast v1.7.0 // indirect
github.com/spf13/cobra v1.0.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/pflag v1.0.6 // indirect
github.com/subosito/gotenv v1.4.2 // indirect github.com/subosito/gotenv v1.4.2 // indirect
github.com/tidwall/pretty v1.1.0 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.1.1 // indirect github.com/xdg-go/scram v1.1.1 // indirect
github.com/xdg-go/stringprep v1.0.3 // indirect github.com/xdg-go/stringprep v1.0.3 // indirect
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
go.etcd.io/etcd/api/v3 v3.5.6 // indirect github.com/zclconf/go-cty v1.14.4 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.6 // indirect github.com/zclconf/go-cty-yaml v1.1.0 // indirect
go.etcd.io/etcd/api/v3 v3.5.18 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.18 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 // indirect
go.opentelemetry.io/otel v1.34.0 // indirect
go.opentelemetry.io/otel/metric v1.34.0 // indirect
go.opentelemetry.io/otel/trace v1.34.0 // indirect
go.uber.org/atomic v1.9.0 // indirect go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.8.0 // indirect go.uber.org/multierr v1.8.0 // indirect
go.uber.org/zap v1.21.0 // indirect go.uber.org/zap v1.21.0 // indirect
golang.org/x/net v0.6.0 // indirect golang.org/x/exp v0.0.0-20221004215720-b9f4876ce741 // indirect
golang.org/x/sync v0.1.0 // indirect golang.org/x/net v0.35.0 // indirect
golang.org/x/sys v0.5.0 // indirect golang.org/x/oauth2 v0.26.0 // indirect
golang.org/x/text v0.7.0 // indirect golang.org/x/sync v0.11.0 // indirect
golang.org/x/tools v0.1.12 // indirect golang.org/x/sys v0.30.0 // indirect
google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef // indirect golang.org/x/text v0.22.0 // indirect
google.golang.org/api v0.221.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250207221924-e9438ea467c6 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
) )
//replace github.com/ory/fosite => ../../../github.com/ory/fosite

1489
go.sum Executable file → Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -2,22 +2,24 @@ package grpcapi
import ( import (
"encoding/json" "encoding/json"
"fmt"
"git.coopgo.io/coopgo-platform/mobility-accounts/storage" "gitlab.com/mobicoop/solidarity/services/mobility-accounts/storage"
"github.com/rs/zerolog/log"
"google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/types/known/structpb" "google.golang.org/protobuf/types/known/structpb"
) )
func (a Account) ToStorageType() storage.Account { func (a Account) ToStorageType() storage.Account {
var localauth storage.LocalAuth var localauth *storage.LocalAuth
if a.Authentication != nil && a.Authentication.Local != nil { if a.Authentication != nil && a.Authentication.Local != nil {
localauth = a.Authentication.Local.ToStorageType() la := a.Authentication.Local.ToStorageType()
localauth = &la
} }
account := storage.Account{ account := storage.Account{
ID: a.Id, ID: a.Id,
Namespace: a.Namespace, Namespace: a.Namespace,
Data: map[string]any{}, Data: map[string]any{},
Metadata: map[string]any{},
Authentication: storage.AccountAuth{ Authentication: storage.AccountAuth{
Local: localauth, Local: localauth,
}, },
@@ -26,7 +28,7 @@ func (a Account) ToStorageType() storage.Account {
for k, d := range a.Data.GetFields() { for k, d := range a.Data.GetFields() {
jsondata, err := protojson.Marshal(d) jsondata, err := protojson.Marshal(d)
if err != nil { if err != nil {
fmt.Println(err) log.Error().Err(err).Msg("")
break break
} }
var data any var data any
@@ -34,20 +36,43 @@ func (a Account) ToStorageType() storage.Account {
account.Data[k] = data account.Data[k] = data
} }
for k, d := range a.Metadata.GetFields() {
jsondata, err := protojson.Marshal(d)
if err != nil {
log.Error().Err(err).Msg("")
break
}
var data any
json.Unmarshal(jsondata, &data)
account.Metadata[k] = data
}
return account return account
} }
func (lc LocalAuth) ToStorageType() storage.LocalAuth { func (lc LocalAuth) ToStorageType() storage.LocalAuth {
emailValidation := storage.Validation{}
if lc.EmailValidation != nil {
emailValidation.Validated = lc.EmailValidation.Validated
emailValidation.ValidationCode = lc.EmailValidation.ValidationCode
}
phoneValidation := storage.Validation{}
if lc.PhoneNumberValidation != nil {
phoneValidation.Validated = lc.PhoneNumberValidation.Validated
phoneValidation.ValidationCode = lc.PhoneNumberValidation.ValidationCode
}
return storage.LocalAuth{ return storage.LocalAuth{
Username: lc.Username, Username: lc.Username,
Password: lc.Password, Password: lc.Password,
Email: lc.Email, Email: lc.Email,
EmailValidation: storage.Validation{ EmailValidation: &storage.Validation{
Validated: lc.EmailValidation.Validated, Validated: lc.EmailValidation.Validated,
ValidationCode: lc.EmailValidation.ValidationCode, ValidationCode: lc.EmailValidation.ValidationCode,
}, },
PhoneNumber: lc.PhoneNumber, PhoneNumber: lc.PhoneNumber,
PhoneNumberValidation: storage.Validation{ PhoneNumberValidation: &storage.Validation{
Validated: lc.PhoneNumberValidation.Validated, Validated: lc.PhoneNumberValidation.Validated,
ValidationCode: lc.PhoneNumberValidation.ValidationCode, ValidationCode: lc.PhoneNumberValidation.ValidationCode,
}, },
@@ -55,7 +80,10 @@ func (lc LocalAuth) ToStorageType() storage.LocalAuth {
} }
func AccountFromStorageType(account *storage.Account) (*Account, error) { func AccountFromStorageType(account *storage.Account) (*Account, error) {
lc := LocalAuthFromStorageType(account.Authentication.Local) var lc *LocalAuth
if account.Authentication.Local != nil {
lc = LocalAuthFromStorageType(*account.Authentication.Local)
}
d, err := sanitizeData(account.Data) d, err := sanitizeData(account.Data)
if err != nil { if err != nil {
@@ -64,7 +92,18 @@ func AccountFromStorageType(account *storage.Account) (*Account, error) {
data, err := structpb.NewStruct(d) data, err := structpb.NewStruct(d)
if err != nil { if err != nil {
fmt.Println(err) log.Error().Err(err).Msg("")
return nil, err
}
m, err := sanitizeData(account.Metadata)
if err != nil {
return nil, err
}
metadata, err := structpb.NewStruct(m)
if err != nil {
log.Error().Err(err).Msg("")
return nil, err return nil, err
} }
@@ -72,6 +111,7 @@ func AccountFromStorageType(account *storage.Account) (*Account, error) {
Id: account.ID, Id: account.ID,
Namespace: account.Namespace, Namespace: account.Namespace,
Data: data, Data: data,
Metadata: metadata,
Authentication: &AccountAuth{ Authentication: &AccountAuth{
Local: lc, Local: lc,
}, },

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.28.0 // protoc-gen-go v1.36.7
// protoc v3.19.4 // protoc v6.31.1
// source: accounts.proto // source: accounts.proto
package grpcapi package grpcapi
@@ -12,6 +12,7 @@ import (
structpb "google.golang.org/protobuf/types/known/structpb" structpb "google.golang.org/protobuf/types/known/structpb"
reflect "reflect" reflect "reflect"
sync "sync" sync "sync"
unsafe "unsafe"
) )
const ( const (
@@ -22,23 +23,21 @@ const (
) )
type Account struct { type Account struct {
state protoimpl.MessageState state protoimpl.MessageState `protogen:"open.v1"`
sizeCache protoimpl.SizeCache Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
unknownFields protoimpl.UnknownFields Namespace string `protobuf:"bytes,2,opt,name=namespace,proto3" json:"namespace,omitempty"`
Authentication *AccountAuth `protobuf:"bytes,3,opt,name=authentication,proto3" json:"authentication,omitempty"`
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` Data *structpb.Struct `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"`
Namespace string `protobuf:"bytes,2,opt,name=namespace,proto3" json:"namespace,omitempty"` Metadata *structpb.Struct `protobuf:"bytes,5,opt,name=metadata,proto3" json:"metadata,omitempty"`
Authentication *AccountAuth `protobuf:"bytes,3,opt,name=authentication,proto3" json:"authentication,omitempty"` unknownFields protoimpl.UnknownFields
Data *structpb.Struct `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"` sizeCache protoimpl.SizeCache
} }
func (x *Account) Reset() { func (x *Account) Reset() {
*x = Account{} *x = Account{}
if protoimpl.UnsafeEnabled { mi := &file_accounts_proto_msgTypes[0]
mi := &file_accounts_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *Account) String() string { func (x *Account) String() string {
@@ -49,7 +48,7 @@ func (*Account) ProtoMessage() {}
func (x *Account) ProtoReflect() protoreflect.Message { func (x *Account) ProtoReflect() protoreflect.Message {
mi := &file_accounts_proto_msgTypes[0] mi := &file_accounts_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -92,21 +91,25 @@ func (x *Account) GetData() *structpb.Struct {
return nil return nil
} }
type AccountAuth struct { func (x *Account) GetMetadata() *structpb.Struct {
state protoimpl.MessageState if x != nil {
sizeCache protoimpl.SizeCache return x.Metadata
unknownFields protoimpl.UnknownFields }
return nil
}
Local *LocalAuth `protobuf:"bytes,7,opt,name=local,proto3" json:"local,omitempty"` type AccountAuth struct {
state protoimpl.MessageState `protogen:"open.v1"`
Local *LocalAuth `protobuf:"bytes,7,opt,name=local,proto3,oneof" json:"local,omitempty"` //TODO SSO
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
} }
func (x *AccountAuth) Reset() { func (x *AccountAuth) Reset() {
*x = AccountAuth{} *x = AccountAuth{}
if protoimpl.UnsafeEnabled { mi := &file_accounts_proto_msgTypes[1]
mi := &file_accounts_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *AccountAuth) String() string { func (x *AccountAuth) String() string {
@@ -117,7 +120,7 @@ func (*AccountAuth) ProtoMessage() {}
func (x *AccountAuth) ProtoReflect() protoreflect.Message { func (x *AccountAuth) ProtoReflect() protoreflect.Message {
mi := &file_accounts_proto_msgTypes[1] mi := &file_accounts_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -140,25 +143,22 @@ func (x *AccountAuth) GetLocal() *LocalAuth {
} }
type LocalAuth struct { type LocalAuth struct {
state protoimpl.MessageState state protoimpl.MessageState `protogen:"open.v1"`
sizeCache protoimpl.SizeCache Username *string `protobuf:"bytes,10,opt,name=username,proto3,oneof" json:"username,omitempty"`
unknownFields protoimpl.UnknownFields Password string `protobuf:"bytes,11,opt,name=password,proto3" json:"password,omitempty"`
Email *string `protobuf:"bytes,12,opt,name=email,proto3,oneof" json:"email,omitempty"`
Username string `protobuf:"bytes,10,opt,name=username,proto3" json:"username,omitempty"` PhoneNumber *string `protobuf:"bytes,13,opt,name=phone_number,json=phoneNumber,proto3,oneof" json:"phone_number,omitempty"`
Password string `protobuf:"bytes,11,opt,name=password,proto3" json:"password,omitempty"` EmailValidation *Validation `protobuf:"bytes,14,opt,name=email_validation,json=emailValidation,proto3,oneof" json:"email_validation,omitempty"`
Email string `protobuf:"bytes,12,opt,name=email,proto3" json:"email,omitempty"` PhoneNumberValidation *Validation `protobuf:"bytes,15,opt,name=phone_number_validation,json=phoneNumberValidation,proto3,oneof" json:"phone_number_validation,omitempty"`
PhoneNumber string `protobuf:"bytes,13,opt,name=phone_number,json=phoneNumber,proto3" json:"phone_number,omitempty"` unknownFields protoimpl.UnknownFields
EmailValidation *Validation `protobuf:"bytes,14,opt,name=email_validation,json=emailValidation,proto3" json:"email_validation,omitempty"` sizeCache protoimpl.SizeCache
PhoneNumberValidation *Validation `protobuf:"bytes,15,opt,name=phone_number_validation,json=phoneNumberValidation,proto3" json:"phone_number_validation,omitempty"`
} }
func (x *LocalAuth) Reset() { func (x *LocalAuth) Reset() {
*x = LocalAuth{} *x = LocalAuth{}
if protoimpl.UnsafeEnabled { mi := &file_accounts_proto_msgTypes[2]
mi := &file_accounts_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *LocalAuth) String() string { func (x *LocalAuth) String() string {
@@ -169,7 +169,7 @@ func (*LocalAuth) ProtoMessage() {}
func (x *LocalAuth) ProtoReflect() protoreflect.Message { func (x *LocalAuth) ProtoReflect() protoreflect.Message {
mi := &file_accounts_proto_msgTypes[2] mi := &file_accounts_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -185,8 +185,8 @@ func (*LocalAuth) Descriptor() ([]byte, []int) {
} }
func (x *LocalAuth) GetUsername() string { func (x *LocalAuth) GetUsername() string {
if x != nil { if x != nil && x.Username != nil {
return x.Username return *x.Username
} }
return "" return ""
} }
@@ -199,15 +199,15 @@ func (x *LocalAuth) GetPassword() string {
} }
func (x *LocalAuth) GetEmail() string { func (x *LocalAuth) GetEmail() string {
if x != nil { if x != nil && x.Email != nil {
return x.Email return *x.Email
} }
return "" return ""
} }
func (x *LocalAuth) GetPhoneNumber() string { func (x *LocalAuth) GetPhoneNumber() string {
if x != nil { if x != nil && x.PhoneNumber != nil {
return x.PhoneNumber return *x.PhoneNumber
} }
return "" return ""
} }
@@ -227,21 +227,18 @@ func (x *LocalAuth) GetPhoneNumberValidation() *Validation {
} }
type Validation struct { type Validation struct {
state protoimpl.MessageState state protoimpl.MessageState `protogen:"open.v1"`
sizeCache protoimpl.SizeCache Validated bool `protobuf:"varint,20,opt,name=validated,proto3" json:"validated,omitempty"`
unknownFields protoimpl.UnknownFields ValidationCode string `protobuf:"bytes,21,opt,name=validation_code,json=validationCode,proto3" json:"validation_code,omitempty"`
unknownFields protoimpl.UnknownFields
Validated bool `protobuf:"varint,20,opt,name=validated,proto3" json:"validated,omitempty"` sizeCache protoimpl.SizeCache
ValidationCode string `protobuf:"bytes,21,opt,name=validation_code,json=validationCode,proto3" json:"validation_code,omitempty"`
} }
func (x *Validation) Reset() { func (x *Validation) Reset() {
*x = Validation{} *x = Validation{}
if protoimpl.UnsafeEnabled { mi := &file_accounts_proto_msgTypes[3]
mi := &file_accounts_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi)
ms.StoreMessageInfo(mi)
}
} }
func (x *Validation) String() string { func (x *Validation) String() string {
@@ -252,7 +249,7 @@ func (*Validation) ProtoMessage() {}
func (x *Validation) ProtoReflect() protoreflect.Message { func (x *Validation) ProtoReflect() protoreflect.Message {
mi := &file_accounts_proto_msgTypes[3] mi := &file_accounts_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
@@ -283,64 +280,51 @@ func (x *Validation) GetValidationCode() string {
var File_accounts_proto protoreflect.FileDescriptor var File_accounts_proto protoreflect.FileDescriptor
var file_accounts_proto_rawDesc = []byte{ const file_accounts_proto_rawDesc = "" +
0x0a, 0x0e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, "\n" +
0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, "\x0eaccounts.proto\x1a\x1cgoogle/protobuf/struct.proto\"\xcf\x01\n" +
0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x9a, "\aAccount\x12\x0e\n" +
0x01, 0x0a, 0x07, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, "\x02id\x18\x01 \x01(\tR\x02id\x12\x1c\n" +
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x61, "\tnamespace\x18\x02 \x01(\tR\tnamespace\x124\n" +
0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, "\x0eauthentication\x18\x03 \x01(\v2\f.AccountAuthR\x0eauthentication\x12+\n" +
0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x34, 0x0a, 0x0e, 0x61, 0x75, 0x74, 0x68, "\x04data\x18\x04 \x01(\v2\x17.google.protobuf.StructR\x04data\x123\n" +
0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, "\bmetadata\x18\x05 \x01(\v2\x17.google.protobuf.StructR\bmetadata\">\n" +
0x32, 0x0c, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x75, 0x74, 0x68, 0x52, 0x0e, "\vAccountAuth\x12%\n" +
0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2b, "\x05local\x18\a \x01(\v2\n" +
0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, ".LocalAuthH\x00R\x05local\x88\x01\x01B\b\n" +
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, "\x06_local\"\xeb\x02\n" +
0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x2f, 0x0a, 0x0b, 0x41, "\tLocalAuth\x12\x1f\n" +
0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x75, 0x74, 0x68, 0x12, 0x20, 0x0a, 0x05, 0x6c, 0x6f, "\busername\x18\n" +
0x63, 0x61, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x4c, 0x6f, 0x63, 0x61, " \x01(\tH\x00R\busername\x88\x01\x01\x12\x1a\n" +
0x6c, 0x41, 0x75, 0x74, 0x68, 0x52, 0x05, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x22, 0xf9, 0x01, 0x0a, "\bpassword\x18\v \x01(\tR\bpassword\x12\x19\n" +
0x09, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, "\x05email\x18\f \x01(\tH\x01R\x05email\x88\x01\x01\x12&\n" +
0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, "\fphone_number\x18\r \x01(\tH\x02R\vphoneNumber\x88\x01\x01\x12;\n" +
0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, "\x10email_validation\x18\x0e \x01(\v2\v.ValidationH\x03R\x0femailValidation\x88\x01\x01\x12H\n" +
0x72, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, "\x17phone_number_validation\x18\x0f \x01(\v2\v.ValidationH\x04R\x15phoneNumberValidation\x88\x01\x01B\v\n" +
0x72, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x0c, 0x20, 0x01, 0x28, "\t_usernameB\b\n" +
0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x68, 0x6f, 0x6e, "\x06_emailB\x0f\n" +
0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, "\r_phone_numberB\x13\n" +
0x70, 0x68, 0x6f, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x36, 0x0a, 0x10, 0x65, "\x11_email_validationB\x1a\n" +
0x6d, 0x61, 0x69, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, "\x18_phone_number_validation\"S\n" +
0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, "\n" +
0x6f, 0x6e, 0x52, 0x0f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, "Validation\x12\x1c\n" +
0x69, 0x6f, 0x6e, 0x12, 0x43, 0x0a, 0x17, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x5f, 0x6e, 0x75, 0x6d, "\tvalidated\x18\x14 \x01(\bR\tvalidated\x12'\n" +
0x62, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0f, "\x0fvalidation_code\x18\x15 \x01(\tR\x0evalidationCodeBCZAgitlab.com/mobicoop/solidarity/services/mobility-accounts/grpcapib\x06proto3"
0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x52, 0x15, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x56, 0x61,
0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x53, 0x0a, 0x0a, 0x56, 0x61, 0x6c, 0x69,
0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61,
0x74, 0x65, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x76, 0x61, 0x6c, 0x69, 0x64,
0x61, 0x74, 0x65, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x76,
0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x42, 0x39, 0x5a,
0x37, 0x67, 0x69, 0x74, 0x2e, 0x63, 0x6f, 0x6f, 0x70, 0x67, 0x6f, 0x2e, 0x69, 0x6f, 0x2f, 0x63,
0x6f, 0x6f, 0x70, 0x67, 0x6f, 0x2d, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x6d,
0x6f, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x2d, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73,
0x2f, 0x67, 0x72, 0x70, 0x63, 0x61, 0x70, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var ( var (
file_accounts_proto_rawDescOnce sync.Once file_accounts_proto_rawDescOnce sync.Once
file_accounts_proto_rawDescData = file_accounts_proto_rawDesc file_accounts_proto_rawDescData []byte
) )
func file_accounts_proto_rawDescGZIP() []byte { func file_accounts_proto_rawDescGZIP() []byte {
file_accounts_proto_rawDescOnce.Do(func() { file_accounts_proto_rawDescOnce.Do(func() {
file_accounts_proto_rawDescData = protoimpl.X.CompressGZIP(file_accounts_proto_rawDescData) file_accounts_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_accounts_proto_rawDesc), len(file_accounts_proto_rawDesc)))
}) })
return file_accounts_proto_rawDescData return file_accounts_proto_rawDescData
} }
var file_accounts_proto_msgTypes = make([]protoimpl.MessageInfo, 4) var file_accounts_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_accounts_proto_goTypes = []interface{}{ var file_accounts_proto_goTypes = []any{
(*Account)(nil), // 0: Account (*Account)(nil), // 0: Account
(*AccountAuth)(nil), // 1: AccountAuth (*AccountAuth)(nil), // 1: AccountAuth
(*LocalAuth)(nil), // 2: LocalAuth (*LocalAuth)(nil), // 2: LocalAuth
@@ -350,14 +334,15 @@ var file_accounts_proto_goTypes = []interface{}{
var file_accounts_proto_depIdxs = []int32{ var file_accounts_proto_depIdxs = []int32{
1, // 0: Account.authentication:type_name -> AccountAuth 1, // 0: Account.authentication:type_name -> AccountAuth
4, // 1: Account.data:type_name -> google.protobuf.Struct 4, // 1: Account.data:type_name -> google.protobuf.Struct
2, // 2: AccountAuth.local:type_name -> LocalAuth 4, // 2: Account.metadata:type_name -> google.protobuf.Struct
3, // 3: LocalAuth.email_validation:type_name -> Validation 2, // 3: AccountAuth.local:type_name -> LocalAuth
3, // 4: LocalAuth.phone_number_validation:type_name -> Validation 3, // 4: LocalAuth.email_validation:type_name -> Validation
5, // [5:5] is the sub-list for method output_type 3, // 5: LocalAuth.phone_number_validation:type_name -> Validation
5, // [5:5] is the sub-list for method input_type 6, // [6:6] is the sub-list for method output_type
5, // [5:5] is the sub-list for extension type_name 6, // [6:6] is the sub-list for method input_type
5, // [5:5] is the sub-list for extension extendee 6, // [6:6] is the sub-list for extension type_name
0, // [0:5] is the sub-list for field type_name 6, // [6:6] is the sub-list for extension extendee
0, // [0:6] is the sub-list for field type_name
} }
func init() { file_accounts_proto_init() } func init() { file_accounts_proto_init() }
@@ -365,61 +350,13 @@ func file_accounts_proto_init() {
if File_accounts_proto != nil { if File_accounts_proto != nil {
return return
} }
if !protoimpl.UnsafeEnabled { file_accounts_proto_msgTypes[1].OneofWrappers = []any{}
file_accounts_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { file_accounts_proto_msgTypes[2].OneofWrappers = []any{}
switch v := v.(*Account); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_accounts_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*AccountAuth); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_accounts_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*LocalAuth); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_accounts_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Validation); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{} type x struct{}
out := protoimpl.TypeBuilder{ out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{ File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_accounts_proto_rawDesc, RawDescriptor: unsafe.Slice(unsafe.StringData(file_accounts_proto_rawDesc), len(file_accounts_proto_rawDesc)),
NumEnums: 0, NumEnums: 0,
NumMessages: 4, NumMessages: 4,
NumExtensions: 0, NumExtensions: 0,
@@ -430,7 +367,6 @@ func file_accounts_proto_init() {
MessageInfos: file_accounts_proto_msgTypes, MessageInfos: file_accounts_proto_msgTypes,
}.Build() }.Build()
File_accounts_proto = out.File File_accounts_proto = out.File
file_accounts_proto_rawDesc = nil
file_accounts_proto_goTypes = nil file_accounts_proto_goTypes = nil
file_accounts_proto_depIdxs = nil file_accounts_proto_depIdxs = nil
} }

View File

@@ -1,27 +1,29 @@
syntax = "proto3"; syntax = "proto3";
option go_package = "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi"; option go_package = "gitlab.com/mobicoop/solidarity/services/mobility-accounts/grpcapi";
import "google/protobuf/struct.proto"; import "google/protobuf/struct.proto";
message Account { message Account {
string id = 1; string id = 1;
string namespace = 2; string namespace = 2;
AccountAuth authentication = 3; AccountAuth authentication = 3;
google.protobuf.Struct data = 4; google.protobuf.Struct data = 4;
google.protobuf.Struct metadata = 5;
} }
message AccountAuth { message AccountAuth {
LocalAuth local = 7; optional LocalAuth local = 7;
//TODO SSO
} }
message LocalAuth { message LocalAuth {
string username = 10; optional string username = 10;
string password = 11; string password = 11;
string email = 12; optional string email = 12;
string phone_number = 13; optional string phone_number = 13;
Validation email_validation = 14; optional Validation email_validation = 14;
Validation phone_number_validation = 15; optional Validation phone_number_validation = 15;
} }
message Validation { message Validation {

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
syntax = "proto3"; syntax = "proto3";
option go_package = "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi"; option go_package = "gitlab.com/mobicoop/solidarity/services/mobility-accounts/grpcapi";
import "accounts.proto"; import "accounts.proto";
@@ -14,6 +14,7 @@ service MobilityAccounts {
rpc GetAccountUsername(GetAccountUsernameRequest) returns (GetAccountUsernameResponse) {} rpc GetAccountUsername(GetAccountUsernameRequest) returns (GetAccountUsernameResponse) {}
rpc GetAccounts(GetAccountsRequest) returns (GetAccountsResponse) {} rpc GetAccounts(GetAccountsRequest) returns (GetAccountsResponse) {}
rpc GetAccountsBatch(GetAccountsBatchRequest) returns (GetAccountsBatchResponse) {} rpc GetAccountsBatch(GetAccountsBatchRequest) returns (GetAccountsBatchResponse) {}
rpc DeleteAccount(DeleteAccountRequest) returns (DeleteAccountResponse) {}
// Authentication functions // Authentication functions
rpc Login(LoginRequest) returns (LoginResponse) {} rpc Login(LoginRequest) returns (LoginResponse) {}
@@ -95,4 +96,10 @@ message ChangePasswordRequest {
string password = 16; string password = 16;
} }
message ChangePasswordResponse {} message ChangePasswordResponse {}
message DeleteAccountRequest {
string id = 22;
}
message DeleteAccountResponse {}

View File

@@ -1,7 +1,9 @@
//COMA (COOPGO Mobility Accounts) gRPC service definition
// Code generated by protoc-gen-go-grpc. DO NOT EDIT. // Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions: // versions:
// - protoc-gen-go-grpc v1.2.0 // - protoc-gen-go-grpc v1.5.1
// - protoc v3.19.4 // - protoc v6.31.1
// source: comasvc.proto // source: comasvc.proto
package grpcapi package grpcapi
@@ -15,8 +17,21 @@ import (
// This is a compile-time assertion to ensure that this generated file // This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against. // is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later. // Requires gRPC-Go v1.64.0 or later.
const _ = grpc.SupportPackageIsVersion7 const _ = grpc.SupportPackageIsVersion9
const (
MobilityAccounts_Register_FullMethodName = "/MobilityAccounts/Register"
MobilityAccounts_UpdateData_FullMethodName = "/MobilityAccounts/UpdateData"
MobilityAccounts_UpdatePhoneNumber_FullMethodName = "/MobilityAccounts/UpdatePhoneNumber"
MobilityAccounts_GetAccount_FullMethodName = "/MobilityAccounts/GetAccount"
MobilityAccounts_GetAccountUsername_FullMethodName = "/MobilityAccounts/GetAccountUsername"
MobilityAccounts_GetAccounts_FullMethodName = "/MobilityAccounts/GetAccounts"
MobilityAccounts_GetAccountsBatch_FullMethodName = "/MobilityAccounts/GetAccountsBatch"
MobilityAccounts_DeleteAccount_FullMethodName = "/MobilityAccounts/DeleteAccount"
MobilityAccounts_Login_FullMethodName = "/MobilityAccounts/Login"
MobilityAccounts_ChangePassword_FullMethodName = "/MobilityAccounts/ChangePassword"
)
// MobilityAccountsClient is the client API for MobilityAccounts service. // MobilityAccountsClient is the client API for MobilityAccounts service.
// //
@@ -29,6 +44,7 @@ type MobilityAccountsClient interface {
GetAccountUsername(ctx context.Context, in *GetAccountUsernameRequest, opts ...grpc.CallOption) (*GetAccountUsernameResponse, error) GetAccountUsername(ctx context.Context, in *GetAccountUsernameRequest, opts ...grpc.CallOption) (*GetAccountUsernameResponse, error)
GetAccounts(ctx context.Context, in *GetAccountsRequest, opts ...grpc.CallOption) (*GetAccountsResponse, error) GetAccounts(ctx context.Context, in *GetAccountsRequest, opts ...grpc.CallOption) (*GetAccountsResponse, error)
GetAccountsBatch(ctx context.Context, in *GetAccountsBatchRequest, opts ...grpc.CallOption) (*GetAccountsBatchResponse, error) GetAccountsBatch(ctx context.Context, in *GetAccountsBatchRequest, opts ...grpc.CallOption) (*GetAccountsBatchResponse, error)
DeleteAccount(ctx context.Context, in *DeleteAccountRequest, opts ...grpc.CallOption) (*DeleteAccountResponse, error)
// Authentication functions // Authentication functions
Login(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error) Login(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error)
ChangePassword(ctx context.Context, in *ChangePasswordRequest, opts ...grpc.CallOption) (*ChangePasswordResponse, error) ChangePassword(ctx context.Context, in *ChangePasswordRequest, opts ...grpc.CallOption) (*ChangePasswordResponse, error)
@@ -43,8 +59,9 @@ func NewMobilityAccountsClient(cc grpc.ClientConnInterface) MobilityAccountsClie
} }
func (c *mobilityAccountsClient) Register(ctx context.Context, in *RegisterRequest, opts ...grpc.CallOption) (*RegisterResponse, error) { func (c *mobilityAccountsClient) Register(ctx context.Context, in *RegisterRequest, opts ...grpc.CallOption) (*RegisterResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(RegisterResponse) out := new(RegisterResponse)
err := c.cc.Invoke(ctx, "/MobilityAccounts/Register", in, out, opts...) err := c.cc.Invoke(ctx, MobilityAccounts_Register_FullMethodName, in, out, cOpts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -52,8 +69,9 @@ func (c *mobilityAccountsClient) Register(ctx context.Context, in *RegisterReque
} }
func (c *mobilityAccountsClient) UpdateData(ctx context.Context, in *UpdateDataRequest, opts ...grpc.CallOption) (*UpdateDataResponse, error) { func (c *mobilityAccountsClient) UpdateData(ctx context.Context, in *UpdateDataRequest, opts ...grpc.CallOption) (*UpdateDataResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(UpdateDataResponse) out := new(UpdateDataResponse)
err := c.cc.Invoke(ctx, "/MobilityAccounts/UpdateData", in, out, opts...) err := c.cc.Invoke(ctx, MobilityAccounts_UpdateData_FullMethodName, in, out, cOpts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -61,8 +79,9 @@ func (c *mobilityAccountsClient) UpdateData(ctx context.Context, in *UpdateDataR
} }
func (c *mobilityAccountsClient) UpdatePhoneNumber(ctx context.Context, in *UpdatePhoneNumberRequest, opts ...grpc.CallOption) (*UpdatePhoneNumberResponse, error) { func (c *mobilityAccountsClient) UpdatePhoneNumber(ctx context.Context, in *UpdatePhoneNumberRequest, opts ...grpc.CallOption) (*UpdatePhoneNumberResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(UpdatePhoneNumberResponse) out := new(UpdatePhoneNumberResponse)
err := c.cc.Invoke(ctx, "/MobilityAccounts/UpdatePhoneNumber", in, out, opts...) err := c.cc.Invoke(ctx, MobilityAccounts_UpdatePhoneNumber_FullMethodName, in, out, cOpts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -70,8 +89,9 @@ func (c *mobilityAccountsClient) UpdatePhoneNumber(ctx context.Context, in *Upda
} }
func (c *mobilityAccountsClient) GetAccount(ctx context.Context, in *GetAccountRequest, opts ...grpc.CallOption) (*GetAccountResponse, error) { func (c *mobilityAccountsClient) GetAccount(ctx context.Context, in *GetAccountRequest, opts ...grpc.CallOption) (*GetAccountResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetAccountResponse) out := new(GetAccountResponse)
err := c.cc.Invoke(ctx, "/MobilityAccounts/GetAccount", in, out, opts...) err := c.cc.Invoke(ctx, MobilityAccounts_GetAccount_FullMethodName, in, out, cOpts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -79,8 +99,9 @@ func (c *mobilityAccountsClient) GetAccount(ctx context.Context, in *GetAccountR
} }
func (c *mobilityAccountsClient) GetAccountUsername(ctx context.Context, in *GetAccountUsernameRequest, opts ...grpc.CallOption) (*GetAccountUsernameResponse, error) { func (c *mobilityAccountsClient) GetAccountUsername(ctx context.Context, in *GetAccountUsernameRequest, opts ...grpc.CallOption) (*GetAccountUsernameResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetAccountUsernameResponse) out := new(GetAccountUsernameResponse)
err := c.cc.Invoke(ctx, "/MobilityAccounts/GetAccountUsername", in, out, opts...) err := c.cc.Invoke(ctx, MobilityAccounts_GetAccountUsername_FullMethodName, in, out, cOpts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -88,8 +109,9 @@ func (c *mobilityAccountsClient) GetAccountUsername(ctx context.Context, in *Get
} }
func (c *mobilityAccountsClient) GetAccounts(ctx context.Context, in *GetAccountsRequest, opts ...grpc.CallOption) (*GetAccountsResponse, error) { func (c *mobilityAccountsClient) GetAccounts(ctx context.Context, in *GetAccountsRequest, opts ...grpc.CallOption) (*GetAccountsResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetAccountsResponse) out := new(GetAccountsResponse)
err := c.cc.Invoke(ctx, "/MobilityAccounts/GetAccounts", in, out, opts...) err := c.cc.Invoke(ctx, MobilityAccounts_GetAccounts_FullMethodName, in, out, cOpts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -97,8 +119,19 @@ func (c *mobilityAccountsClient) GetAccounts(ctx context.Context, in *GetAccount
} }
func (c *mobilityAccountsClient) GetAccountsBatch(ctx context.Context, in *GetAccountsBatchRequest, opts ...grpc.CallOption) (*GetAccountsBatchResponse, error) { func (c *mobilityAccountsClient) GetAccountsBatch(ctx context.Context, in *GetAccountsBatchRequest, opts ...grpc.CallOption) (*GetAccountsBatchResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetAccountsBatchResponse) out := new(GetAccountsBatchResponse)
err := c.cc.Invoke(ctx, "/MobilityAccounts/GetAccountsBatch", in, out, opts...) err := c.cc.Invoke(ctx, MobilityAccounts_GetAccountsBatch_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *mobilityAccountsClient) DeleteAccount(ctx context.Context, in *DeleteAccountRequest, opts ...grpc.CallOption) (*DeleteAccountResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(DeleteAccountResponse)
err := c.cc.Invoke(ctx, MobilityAccounts_DeleteAccount_FullMethodName, in, out, cOpts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -106,8 +139,9 @@ func (c *mobilityAccountsClient) GetAccountsBatch(ctx context.Context, in *GetAc
} }
func (c *mobilityAccountsClient) Login(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error) { func (c *mobilityAccountsClient) Login(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(LoginResponse) out := new(LoginResponse)
err := c.cc.Invoke(ctx, "/MobilityAccounts/Login", in, out, opts...) err := c.cc.Invoke(ctx, MobilityAccounts_Login_FullMethodName, in, out, cOpts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -115,8 +149,9 @@ func (c *mobilityAccountsClient) Login(ctx context.Context, in *LoginRequest, op
} }
func (c *mobilityAccountsClient) ChangePassword(ctx context.Context, in *ChangePasswordRequest, opts ...grpc.CallOption) (*ChangePasswordResponse, error) { func (c *mobilityAccountsClient) ChangePassword(ctx context.Context, in *ChangePasswordRequest, opts ...grpc.CallOption) (*ChangePasswordResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ChangePasswordResponse) out := new(ChangePasswordResponse)
err := c.cc.Invoke(ctx, "/MobilityAccounts/ChangePassword", in, out, opts...) err := c.cc.Invoke(ctx, MobilityAccounts_ChangePassword_FullMethodName, in, out, cOpts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -125,7 +160,7 @@ func (c *mobilityAccountsClient) ChangePassword(ctx context.Context, in *ChangeP
// MobilityAccountsServer is the server API for MobilityAccounts service. // MobilityAccountsServer is the server API for MobilityAccounts service.
// All implementations must embed UnimplementedMobilityAccountsServer // All implementations must embed UnimplementedMobilityAccountsServer
// for forward compatibility // for forward compatibility.
type MobilityAccountsServer interface { type MobilityAccountsServer interface {
Register(context.Context, *RegisterRequest) (*RegisterResponse, error) Register(context.Context, *RegisterRequest) (*RegisterResponse, error)
UpdateData(context.Context, *UpdateDataRequest) (*UpdateDataResponse, error) UpdateData(context.Context, *UpdateDataRequest) (*UpdateDataResponse, error)
@@ -134,15 +169,19 @@ type MobilityAccountsServer interface {
GetAccountUsername(context.Context, *GetAccountUsernameRequest) (*GetAccountUsernameResponse, error) GetAccountUsername(context.Context, *GetAccountUsernameRequest) (*GetAccountUsernameResponse, error)
GetAccounts(context.Context, *GetAccountsRequest) (*GetAccountsResponse, error) GetAccounts(context.Context, *GetAccountsRequest) (*GetAccountsResponse, error)
GetAccountsBatch(context.Context, *GetAccountsBatchRequest) (*GetAccountsBatchResponse, error) GetAccountsBatch(context.Context, *GetAccountsBatchRequest) (*GetAccountsBatchResponse, error)
DeleteAccount(context.Context, *DeleteAccountRequest) (*DeleteAccountResponse, error)
// Authentication functions // Authentication functions
Login(context.Context, *LoginRequest) (*LoginResponse, error) Login(context.Context, *LoginRequest) (*LoginResponse, error)
ChangePassword(context.Context, *ChangePasswordRequest) (*ChangePasswordResponse, error) ChangePassword(context.Context, *ChangePasswordRequest) (*ChangePasswordResponse, error)
mustEmbedUnimplementedMobilityAccountsServer() mustEmbedUnimplementedMobilityAccountsServer()
} }
// UnimplementedMobilityAccountsServer must be embedded to have forward compatible implementations. // UnimplementedMobilityAccountsServer must be embedded to have
type UnimplementedMobilityAccountsServer struct { // forward compatible implementations.
} //
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedMobilityAccountsServer struct{}
func (UnimplementedMobilityAccountsServer) Register(context.Context, *RegisterRequest) (*RegisterResponse, error) { func (UnimplementedMobilityAccountsServer) Register(context.Context, *RegisterRequest) (*RegisterResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Register not implemented") return nil, status.Errorf(codes.Unimplemented, "method Register not implemented")
@@ -165,6 +204,9 @@ func (UnimplementedMobilityAccountsServer) GetAccounts(context.Context, *GetAcco
func (UnimplementedMobilityAccountsServer) GetAccountsBatch(context.Context, *GetAccountsBatchRequest) (*GetAccountsBatchResponse, error) { func (UnimplementedMobilityAccountsServer) GetAccountsBatch(context.Context, *GetAccountsBatchRequest) (*GetAccountsBatchResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetAccountsBatch not implemented") return nil, status.Errorf(codes.Unimplemented, "method GetAccountsBatch not implemented")
} }
func (UnimplementedMobilityAccountsServer) DeleteAccount(context.Context, *DeleteAccountRequest) (*DeleteAccountResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeleteAccount not implemented")
}
func (UnimplementedMobilityAccountsServer) Login(context.Context, *LoginRequest) (*LoginResponse, error) { func (UnimplementedMobilityAccountsServer) Login(context.Context, *LoginRequest) (*LoginResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Login not implemented") return nil, status.Errorf(codes.Unimplemented, "method Login not implemented")
} }
@@ -172,6 +214,7 @@ func (UnimplementedMobilityAccountsServer) ChangePassword(context.Context, *Chan
return nil, status.Errorf(codes.Unimplemented, "method ChangePassword not implemented") return nil, status.Errorf(codes.Unimplemented, "method ChangePassword not implemented")
} }
func (UnimplementedMobilityAccountsServer) mustEmbedUnimplementedMobilityAccountsServer() {} func (UnimplementedMobilityAccountsServer) mustEmbedUnimplementedMobilityAccountsServer() {}
func (UnimplementedMobilityAccountsServer) testEmbeddedByValue() {}
// UnsafeMobilityAccountsServer may be embedded to opt out of forward compatibility for this service. // UnsafeMobilityAccountsServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to MobilityAccountsServer will // Use of this interface is not recommended, as added methods to MobilityAccountsServer will
@@ -181,6 +224,13 @@ type UnsafeMobilityAccountsServer interface {
} }
func RegisterMobilityAccountsServer(s grpc.ServiceRegistrar, srv MobilityAccountsServer) { func RegisterMobilityAccountsServer(s grpc.ServiceRegistrar, srv MobilityAccountsServer) {
// If the following call pancis, it indicates UnimplementedMobilityAccountsServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&MobilityAccounts_ServiceDesc, srv) s.RegisterService(&MobilityAccounts_ServiceDesc, srv)
} }
@@ -194,7 +244,7 @@ func _MobilityAccounts_Register_Handler(srv interface{}, ctx context.Context, de
} }
info := &grpc.UnaryServerInfo{ info := &grpc.UnaryServerInfo{
Server: srv, Server: srv,
FullMethod: "/MobilityAccounts/Register", FullMethod: MobilityAccounts_Register_FullMethodName,
} }
handler := func(ctx context.Context, req interface{}) (interface{}, error) { handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(MobilityAccountsServer).Register(ctx, req.(*RegisterRequest)) return srv.(MobilityAccountsServer).Register(ctx, req.(*RegisterRequest))
@@ -212,7 +262,7 @@ func _MobilityAccounts_UpdateData_Handler(srv interface{}, ctx context.Context,
} }
info := &grpc.UnaryServerInfo{ info := &grpc.UnaryServerInfo{
Server: srv, Server: srv,
FullMethod: "/MobilityAccounts/UpdateData", FullMethod: MobilityAccounts_UpdateData_FullMethodName,
} }
handler := func(ctx context.Context, req interface{}) (interface{}, error) { handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(MobilityAccountsServer).UpdateData(ctx, req.(*UpdateDataRequest)) return srv.(MobilityAccountsServer).UpdateData(ctx, req.(*UpdateDataRequest))
@@ -230,7 +280,7 @@ func _MobilityAccounts_UpdatePhoneNumber_Handler(srv interface{}, ctx context.Co
} }
info := &grpc.UnaryServerInfo{ info := &grpc.UnaryServerInfo{
Server: srv, Server: srv,
FullMethod: "/MobilityAccounts/UpdatePhoneNumber", FullMethod: MobilityAccounts_UpdatePhoneNumber_FullMethodName,
} }
handler := func(ctx context.Context, req interface{}) (interface{}, error) { handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(MobilityAccountsServer).UpdatePhoneNumber(ctx, req.(*UpdatePhoneNumberRequest)) return srv.(MobilityAccountsServer).UpdatePhoneNumber(ctx, req.(*UpdatePhoneNumberRequest))
@@ -248,7 +298,7 @@ func _MobilityAccounts_GetAccount_Handler(srv interface{}, ctx context.Context,
} }
info := &grpc.UnaryServerInfo{ info := &grpc.UnaryServerInfo{
Server: srv, Server: srv,
FullMethod: "/MobilityAccounts/GetAccount", FullMethod: MobilityAccounts_GetAccount_FullMethodName,
} }
handler := func(ctx context.Context, req interface{}) (interface{}, error) { handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(MobilityAccountsServer).GetAccount(ctx, req.(*GetAccountRequest)) return srv.(MobilityAccountsServer).GetAccount(ctx, req.(*GetAccountRequest))
@@ -266,7 +316,7 @@ func _MobilityAccounts_GetAccountUsername_Handler(srv interface{}, ctx context.C
} }
info := &grpc.UnaryServerInfo{ info := &grpc.UnaryServerInfo{
Server: srv, Server: srv,
FullMethod: "/MobilityAccounts/GetAccountUsername", FullMethod: MobilityAccounts_GetAccountUsername_FullMethodName,
} }
handler := func(ctx context.Context, req interface{}) (interface{}, error) { handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(MobilityAccountsServer).GetAccountUsername(ctx, req.(*GetAccountUsernameRequest)) return srv.(MobilityAccountsServer).GetAccountUsername(ctx, req.(*GetAccountUsernameRequest))
@@ -284,7 +334,7 @@ func _MobilityAccounts_GetAccounts_Handler(srv interface{}, ctx context.Context,
} }
info := &grpc.UnaryServerInfo{ info := &grpc.UnaryServerInfo{
Server: srv, Server: srv,
FullMethod: "/MobilityAccounts/GetAccounts", FullMethod: MobilityAccounts_GetAccounts_FullMethodName,
} }
handler := func(ctx context.Context, req interface{}) (interface{}, error) { handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(MobilityAccountsServer).GetAccounts(ctx, req.(*GetAccountsRequest)) return srv.(MobilityAccountsServer).GetAccounts(ctx, req.(*GetAccountsRequest))
@@ -302,7 +352,7 @@ func _MobilityAccounts_GetAccountsBatch_Handler(srv interface{}, ctx context.Con
} }
info := &grpc.UnaryServerInfo{ info := &grpc.UnaryServerInfo{
Server: srv, Server: srv,
FullMethod: "/MobilityAccounts/GetAccountsBatch", FullMethod: MobilityAccounts_GetAccountsBatch_FullMethodName,
} }
handler := func(ctx context.Context, req interface{}) (interface{}, error) { handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(MobilityAccountsServer).GetAccountsBatch(ctx, req.(*GetAccountsBatchRequest)) return srv.(MobilityAccountsServer).GetAccountsBatch(ctx, req.(*GetAccountsBatchRequest))
@@ -310,6 +360,24 @@ func _MobilityAccounts_GetAccountsBatch_Handler(srv interface{}, ctx context.Con
return interceptor(ctx, in, info, handler) return interceptor(ctx, in, info, handler)
} }
func _MobilityAccounts_DeleteAccount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DeleteAccountRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(MobilityAccountsServer).DeleteAccount(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: MobilityAccounts_DeleteAccount_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(MobilityAccountsServer).DeleteAccount(ctx, req.(*DeleteAccountRequest))
}
return interceptor(ctx, in, info, handler)
}
func _MobilityAccounts_Login_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { func _MobilityAccounts_Login_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(LoginRequest) in := new(LoginRequest)
if err := dec(in); err != nil { if err := dec(in); err != nil {
@@ -320,7 +388,7 @@ func _MobilityAccounts_Login_Handler(srv interface{}, ctx context.Context, dec f
} }
info := &grpc.UnaryServerInfo{ info := &grpc.UnaryServerInfo{
Server: srv, Server: srv,
FullMethod: "/MobilityAccounts/Login", FullMethod: MobilityAccounts_Login_FullMethodName,
} }
handler := func(ctx context.Context, req interface{}) (interface{}, error) { handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(MobilityAccountsServer).Login(ctx, req.(*LoginRequest)) return srv.(MobilityAccountsServer).Login(ctx, req.(*LoginRequest))
@@ -338,7 +406,7 @@ func _MobilityAccounts_ChangePassword_Handler(srv interface{}, ctx context.Conte
} }
info := &grpc.UnaryServerInfo{ info := &grpc.UnaryServerInfo{
Server: srv, Server: srv,
FullMethod: "/MobilityAccounts/ChangePassword", FullMethod: MobilityAccounts_ChangePassword_FullMethodName,
} }
handler := func(ctx context.Context, req interface{}) (interface{}, error) { handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(MobilityAccountsServer).ChangePassword(ctx, req.(*ChangePasswordRequest)) return srv.(MobilityAccountsServer).ChangePassword(ctx, req.(*ChangePasswordRequest))
@@ -381,6 +449,10 @@ var MobilityAccounts_ServiceDesc = grpc.ServiceDesc{
MethodName: "GetAccountsBatch", MethodName: "GetAccountsBatch",
Handler: _MobilityAccounts_GetAccountsBatch_Handler, Handler: _MobilityAccounts_GetAccountsBatch_Handler,
}, },
{
MethodName: "DeleteAccount",
Handler: _MobilityAccounts_DeleteAccount_Handler,
},
{ {
MethodName: "Login", MethodName: "Login",
Handler: _MobilityAccounts_Login_Handler, Handler: _MobilityAccounts_Login_Handler,

View File

@@ -2,11 +2,10 @@ package grpcapi
import ( import (
context "context" context "context"
"fmt"
"log"
"net" "net"
"git.coopgo.io/coopgo-platform/mobility-accounts/handlers" "gitlab.com/mobicoop/solidarity/services/mobility-accounts/handlers"
"github.com/rs/zerolog/log"
"github.com/spf13/viper" "github.com/spf13/viper"
"google.golang.org/grpc" "google.golang.org/grpc"
codes "google.golang.org/grpc/codes" codes "google.golang.org/grpc/codes"
@@ -31,7 +30,7 @@ func (s MobilityAccountsServerImpl) Login(ctx context.Context, req *LoginRequest
} }
response, err := AccountFromStorageType(account) response, err := AccountFromStorageType(account)
if err != nil { if err != nil {
fmt.Println(err) log.Error().Err(err).Msg("")
return nil, status.Errorf(codes.Internal, "issue while retrieving account : %v", err) return nil, status.Errorf(codes.Internal, "issue while retrieving account : %v", err)
} }
return &LoginResponse{Account: response}, nil return &LoginResponse{Account: response}, nil
@@ -40,12 +39,12 @@ func (s MobilityAccountsServerImpl) Register(ctx context.Context, req *RegisterR
a := req.Account.ToStorageType() a := req.Account.ToStorageType()
account, err := s.handler.Register(a) account, err := s.handler.Register(a)
if err != nil { if err != nil {
fmt.Println(err) log.Error().Err(err).Msg("")
return nil, status.Errorf(codes.AlreadyExists, "account creation failed : %v", err) return nil, status.Errorf(codes.AlreadyExists, "account creation failed : %v", err)
} }
response, err := AccountFromStorageType(account) response, err := AccountFromStorageType(account)
if err != nil { if err != nil {
fmt.Println(err) log.Error().Err(err).Msg("")
return nil, status.Errorf(codes.Internal, "issue while retrieving account : %v", err) return nil, status.Errorf(codes.Internal, "issue while retrieving account : %v", err)
} }
return &RegisterResponse{Account: response}, nil return &RegisterResponse{Account: response}, nil
@@ -58,7 +57,7 @@ func (s MobilityAccountsServerImpl) UpdateData(ctx context.Context, req *UpdateD
} }
response, err := AccountFromStorageType(account) response, err := AccountFromStorageType(account)
if err != nil { if err != nil {
fmt.Println(err) log.Error().Err(err).Msg("")
return nil, status.Errorf(codes.Internal, "issue while retrieving account : %v", err) return nil, status.Errorf(codes.Internal, "issue while retrieving account : %v", err)
} }
return &UpdateDataResponse{Account: response}, nil return &UpdateDataResponse{Account: response}, nil
@@ -78,12 +77,12 @@ func (s MobilityAccountsServerImpl) UpdatePhoneNumber(ctx context.Context, req *
func (s MobilityAccountsServerImpl) GetAccount(ctx context.Context, req *GetAccountRequest) (*GetAccountResponse, error) { func (s MobilityAccountsServerImpl) GetAccount(ctx context.Context, req *GetAccountRequest) (*GetAccountResponse, error) {
account, err := s.handler.GetAccount(req.Id) account, err := s.handler.GetAccount(req.Id)
if err != nil { if err != nil {
fmt.Println(err) log.Error().Err(err).Msg("")
return nil, status.Errorf(codes.AlreadyExists, "issue while retrieving account : %v", err) return nil, status.Errorf(codes.NotFound, "issue while retrieving account : %v", err)
} }
response, err := AccountFromStorageType(account) response, err := AccountFromStorageType(account)
if err != nil { if err != nil {
fmt.Println(err) log.Error().Err(err).Msg("")
return nil, status.Errorf(codes.Internal, "issue while retrieving account : %v", err) return nil, status.Errorf(codes.Internal, "issue while retrieving account : %v", err)
} }
return &GetAccountResponse{Account: response}, nil return &GetAccountResponse{Account: response}, nil
@@ -91,12 +90,12 @@ func (s MobilityAccountsServerImpl) GetAccount(ctx context.Context, req *GetAcco
func (s MobilityAccountsServerImpl) GetAccountUsername(ctx context.Context, req *GetAccountUsernameRequest) (*GetAccountUsernameResponse, error) { func (s MobilityAccountsServerImpl) GetAccountUsername(ctx context.Context, req *GetAccountUsernameRequest) (*GetAccountUsernameResponse, error) {
account, err := s.handler.GetAccountUsername(req.Username, req.Namespace) account, err := s.handler.GetAccountUsername(req.Username, req.Namespace)
if err != nil { if err != nil {
fmt.Println(err) log.Error().Err(err).Msg("")
return nil, status.Errorf(codes.AlreadyExists, "issue while retrieving account : %v", err) return nil, status.Errorf(codes.NotFound, "issue while retrieving account : %v", err)
} }
response, err := AccountFromStorageType(account) response, err := AccountFromStorageType(account)
if err != nil { if err != nil {
fmt.Println(err) log.Error().Err(err).Msg("")
return nil, status.Errorf(codes.Internal, "issue while retrieving account : %v", err) return nil, status.Errorf(codes.Internal, "issue while retrieving account : %v", err)
} }
return &GetAccountUsernameResponse{Account: response}, nil return &GetAccountUsernameResponse{Account: response}, nil
@@ -140,6 +139,13 @@ func (s MobilityAccountsServerImpl) ChangePassword(ctx context.Context, req *Cha
} }
return &ChangePasswordResponse{}, nil return &ChangePasswordResponse{}, nil
} }
func (s MobilityAccountsServerImpl) DeleteAccount(ctx context.Context, req *DeleteAccountRequest) (*DeleteAccountResponse, error) {
err := s.handler.DeleteAccount(req.Id)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to delete account: %v", err)
}
return &DeleteAccountResponse{}, nil
}
func (MobilityAccountsServerImpl) mustEmbedUnimplementedMobilityAccountsServer() {} func (MobilityAccountsServerImpl) mustEmbedUnimplementedMobilityAccountsServer() {}
func Run(done chan error, cfg *viper.Viper, handler handlers.MobilityAccountsHandler) { func Run(done chan error, cfg *viper.Viper, handler handlers.MobilityAccountsHandler) {
@@ -147,13 +153,13 @@ func Run(done chan error, cfg *viper.Viper, handler handlers.MobilityAccountsHan
dev_env = cfg.GetBool("dev_env") dev_env = cfg.GetBool("dev_env")
address = ":" + cfg.GetString("services.grpc.port") address = ":" + cfg.GetString("services.grpc.port")
) )
fmt.Println("-> GRPC server on", address) log.Info().Str("address", address).Msg("Running gRPC server")
server := grpc.NewServer() server := grpc.NewServer()
RegisterMobilityAccountsServer(server, NewMobilityAccountsServer(handler)) RegisterMobilityAccountsServer(server, NewMobilityAccountsServer(handler))
l, err := net.Listen("tcp", address) l, err := net.Listen("tcp", address)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal().Str("address", address).Err(err).Msg("gRPC server cannot listen")
} }
if dev_env { if dev_env {
@@ -161,7 +167,7 @@ func Run(done chan error, cfg *viper.Viper, handler handlers.MobilityAccountsHan
} }
if err := server.Serve(l); err != nil { if err := server.Serve(l); err != nil {
fmt.Println("gRPC service ended") log.Error().Err(err).Msg("gRPC service ended")
done <- err done <- err
} }
} }

View File

@@ -2,56 +2,68 @@ package handlers
import ( import (
"errors" "errors"
"fmt"
"strings" "strings"
"time" "time"
"git.coopgo.io/coopgo-platform/mobility-accounts/storage" "gitlab.com/mobicoop/solidarity/services/mobility-accounts/storage"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/rs/zerolog/log"
"github.com/santhosh-tekuri/jsonschema/v5" "github.com/santhosh-tekuri/jsonschema/v5"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
) )
func (h MobilityAccountsHandler) Login(username string, password string, namespace string) (*storage.Account, error) { func (h MobilityAccountsHandler) Login(username string, password string, namespace string) (*storage.Account, error) {
if password == "" { if password == "" {
return nil, errors.New("empty password not allowed") return nil, errors.New("empty password not allowed")
} }
account, err := h.storage.DB.LocalAuthentication(namespace, strings.ToLower(username), "", "") u := strings.ToLower(username)
account, err := h.storage.DB.LocalAuthentication(namespace, &u, nil, nil)
if err != nil { if err != nil {
log.Error().Err(err).Msg("")
return nil, err return nil, err
} }
if err = bcrypt.CompareHashAndPassword([]byte(account.Authentication.Local.Password), []byte(password)); err != nil { if err = bcrypt.CompareHashAndPassword([]byte(account.Authentication.Local.Password), []byte(password)); err != nil {
log.Error().Err(err).Msg("")
return nil, err return nil, err
} }
return account, nil return account, nil
} }
func (h MobilityAccountsHandler) Register(account storage.Account) (*storage.Account, error) { func (h MobilityAccountsHandler) Register(account storage.Account) (*storage.Account, error) {
if account.ID != "" { if account.ID != "" {
return nil, errors.New("id should be empty") return nil, errors.New("id should be empty")
} }
account.Authentication.Local.Username = strings.ToLower(account.Authentication.Local.Username)
account.Authentication.Local.Email = strings.ToLower(account.Authentication.Local.Email)
_, err := h.storage.DB.LocalAuthentication(account.Namespace, account.Authentication.Local.Username, account.Authentication.Local.Email, account.Authentication.Local.PhoneNumber)
if err == nil {
return nil, errors.New("user already exists")
}
// Generate new UUID // Generate new UUID
account.ID = uuid.NewString() account.ID = uuid.NewString()
// If a password was sent, hash the password if account.Authentication.Local != nil && account.Authentication.Local.Username != nil {
if account.Authentication.Local.Password != "" { username := strings.ToLower(*account.Authentication.Local.Username)
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(account.Authentication.Local.Password), bcrypt.DefaultCost) account.Authentication.Local.Username = &username
if err != nil { }
return nil, err if account.Authentication.Local != nil && account.Authentication.Local.Email != nil {
email := strings.ToLower(*account.Authentication.Local.Email)
account.Authentication.Local.Email = &email
}
if account.Authentication.Local != nil {
// Check if account with same username/email/phone already exists
existing, _ := h.storage.DB.LocalAuthentication(account.Namespace, account.Authentication.Local.Username, account.Authentication.Local.Email, account.Authentication.Local.PhoneNumber)
if existing != nil {
return nil, errors.New("account with same credentials already exists")
}
// If a password was sent, hash the password
if account.Authentication.Local.Password != "" {
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(account.Authentication.Local.Password), bcrypt.DefaultCost)
if err != nil {
return nil, err
}
account.Authentication.Local.Password = string(hashedPassword)
} }
account.Authentication.Local.Password = string(hashedPassword)
} }
// Validate data schemas // Validate data schemas
@@ -98,7 +110,7 @@ func (h MobilityAccountsHandler) UpdateData(accountid string, datas map[string]a
dataschemas := h.config.GetStringMap("data_schemas") dataschemas := h.config.GetStringMap("data_schemas")
for k, v := range datas { for k, v := range datas {
if !h.config.GetBool("allow_any_data") && dataschemas[k] == nil { if !h.config.GetBool("allow_any_data") && dataschemas[k] == nil {
fmt.Println("data scope not allowed") log.Error().Msg("data scope not allowed")
return nil, errors.New("data scope not allowed") return nil, errors.New("data scope not allowed")
} }
@@ -106,19 +118,19 @@ func (h MobilityAccountsHandler) UpdateData(accountid string, datas map[string]a
s := dataschemas[k].(map[string]string) s := dataschemas[k].(map[string]string)
sch, err := jsonschema.Compile(s["schema"]) sch, err := jsonschema.Compile(s["schema"])
if err != nil { if err != nil {
fmt.Println(err) log.Error().Err(err).Msg("")
return nil, err return nil, err
} }
if err = sch.Validate(v); err != nil { if err = sch.Validate(v); err != nil {
fmt.Println(err) log.Error().Err(err).Msg("")
return nil, err return nil, err
} }
} }
account.Data[k] = v account.Data[k] = v
} }
if err = h.storage.DB.UpdateAccount(*account); err != nil { if err = h.storage.DB.UpdateAccount(*account); err != nil {
fmt.Println(err) log.Error().Err(err).Msg("")
return nil, err return nil, err
} }
@@ -131,18 +143,17 @@ func (h MobilityAccountsHandler) UpdatePhoneNumber(accountid, phone_number strin
return err return err
} }
account2, err := h.storage.DB.LocalAuthentication(account.Namespace, "", "", phone_number) account2, err := h.storage.DB.LocalAuthentication(account.Namespace, nil, nil, &phone_number)
if err == nil && account.ID != account2.ID { if err == nil && account.ID != account2.ID {
return errors.New("user with this phone number already exists") return errors.New("user with this phone number already exists")
} }
account.Authentication.Local.PhoneNumber = &phone_number
account.Authentication.Local.PhoneNumber = phone_number
account.Authentication.Local.PhoneNumberValidation.Validated = verified account.Authentication.Local.PhoneNumberValidation.Validated = verified
account.Authentication.Local.PhoneNumberValidation.ValidationCode = verification_code account.Authentication.Local.PhoneNumberValidation.ValidationCode = verification_code
if err = h.storage.DB.UpdateAccount(*account); err != nil { if err = h.storage.DB.UpdateAccount(*account); err != nil {
fmt.Println(err) log.Error().Err(err).Msg("")
return err return err
} }
@@ -155,7 +166,7 @@ func (h MobilityAccountsHandler) GetAccount(id string) (account *storage.Account
} }
func (h MobilityAccountsHandler) GetAccountUsername(username string, namespace string) (account *storage.Account, err error) { func (h MobilityAccountsHandler) GetAccountUsername(username string, namespace string) (account *storage.Account, err error) {
account, err = h.storage.DB.LocalAuthentication(namespace, username, "", "") account, err = h.storage.DB.LocalAuthentication(namespace, &username, nil, nil)
return return
} }
@@ -185,9 +196,12 @@ func (h MobilityAccountsHandler) ChangePassword(accountid string, newpassword st
account.Authentication.Local.Password = string(hashedPassword) account.Authentication.Local.Password = string(hashedPassword)
if err = h.storage.DB.UpdateAccount(*account); err != nil { if err = h.storage.DB.UpdateAccount(*account); err != nil {
fmt.Println(err)
return err return err
} }
return nil return nil
} }
func (h MobilityAccountsHandler) DeleteAccount(id string) error {
return h.storage.DB.DeleteAccount(id)
}

View File

@@ -1,7 +1,7 @@
package handlers package handlers
import ( import (
"git.coopgo.io/coopgo-platform/mobility-accounts/storage" "gitlab.com/mobicoop/solidarity/services/mobility-accounts/storage"
"github.com/spf13/viper" "github.com/spf13/viper"
) )

28
main.go
View File

@@ -1,12 +1,14 @@
package main package main
import ( import (
"fmt" "os"
"git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi" "gitlab.com/mobicoop/solidarity/services/mobility-accounts/grpcapi"
"git.coopgo.io/coopgo-platform/mobility-accounts/handlers" "gitlab.com/mobicoop/solidarity/services/mobility-accounts/handlers"
op "git.coopgo.io/coopgo-platform/mobility-accounts/oidc-provider" op "gitlab.com/mobicoop/solidarity/services/mobility-accounts/oidc-provider"
"git.coopgo.io/coopgo-platform/mobility-accounts/storage" "gitlab.com/mobicoop/solidarity/services/mobility-accounts/storage"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
) )
func main() { func main() {
@@ -22,20 +24,22 @@ func main() {
dev_env = cfg.GetBool("dev_env") dev_env = cfg.GetBool("dev_env")
) )
if dev_env {
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
}
storage, err := storage.NewStorage(cfg) storage, err := storage.NewStorage(cfg)
if err != nil { if err != nil {
panic(err) log.Panic().Err(err).Msg("Cannot connect to storage")
return
} }
handler := handlers.NewHandler(cfg, storage) handler := handlers.NewHandler(cfg, storage)
fmt.Println("Running", service_name, ":")
if dev_env {
fmt.Printf("\033]0;%s\007", service_name)
}
failed := make(chan error) failed := make(chan error)
log.Info().Str("service_name", service_name).Msg("Running service")
if grpc_enable { if grpc_enable {
go grpcapi.Run(failed, cfg, handler) go grpcapi.Run(failed, cfg, handler)
} }
@@ -46,6 +50,6 @@ func main() {
err = <-failed err = <-failed
fmt.Println("Terminating :", err) log.Fatal().Err(err).Msg("Terminating server")
} }

View File

@@ -0,0 +1,151 @@
package connector
import (
"context"
"encoding/json"
"fmt"
"log/slog"
"github.com/dexidp/dex/connector"
"gitlab.com/mobicoop/solidarity/services/mobility-accounts/handlers"
"gitlab.com/mobicoop/solidarity/services/mobility-accounts/storage"
)
// Config is the connector configuration used by Dex's ConnectorConfig interface.
// Fields are injected in-process (not via JSON unmarshaling).
type Config struct {
Handler *handlers.MobilityAccountsHandler
Storage storage.Storage
Namespace string
}
// Open satisfies server.ConnectorConfig. It returns a Connector that implements
// connector.PasswordConnector and connector.RefreshConnector.
func (c *Config) Open(id string, logger *slog.Logger) (connector.Connector, error) {
if c.Handler == nil {
return nil, fmt.Errorf("mobilityaccounts connector: handler is nil")
}
return &Connector{
handler: c.Handler,
storage: c.Storage,
namespace: c.Namespace,
logger: logger,
}, nil
}
// Connector bridges Dex authentication to the mobility-accounts handler.
// It implements connector.PasswordConnector and connector.RefreshConnector.
type Connector struct {
handler *handlers.MobilityAccountsHandler
storage storage.Storage
namespace string
logger *slog.Logger
}
// Prompt returns the label displayed on the password form input.
func (c *Connector) Prompt() string { return "Email" }
// Login authenticates a user via the mobility-accounts handler and maps the
// account data to a Dex Identity with standard OIDC claims.
func (c *Connector) Login(ctx context.Context, s connector.Scopes, username, password string) (connector.Identity, bool, error) {
account, err := c.handler.Login(username, password, c.namespace)
if err != nil {
// Invalid credentials: return validPassword=false, no error
return connector.Identity{}, false, nil
}
c.logger.Info("connector login", "account_id", account.ID, "data_keys", dataKeys(account.Data), "groups_raw", fmt.Sprintf("%T: %v", account.Data["groups"], account.Data["groups"]))
identity := buildIdentity(account)
c.logger.Info("connector identity", "groups", identity.Groups, "email", identity.Email, "username", identity.Username)
return identity, true, nil
}
// Refresh is called when a client uses a refresh token. It reloads the account
// from storage to reflect any changes since the last authentication.
func (c *Connector) Refresh(ctx context.Context, s connector.Scopes, identity connector.Identity) (connector.Identity, error) {
account, err := c.storage.DB.GetAccount(identity.UserID)
if err != nil {
return identity, fmt.Errorf("mobilityaccounts connector: refresh failed: %w", err)
}
return buildIdentity(account), nil
}
// buildIdentity maps a mobility-accounts Account to a Dex connector.Identity.
// Dex maps Identity.Username to the "name" OIDC claim and
// Identity.PreferredUsername to the "preferred_username" claim.
func buildIdentity(account *storage.Account) connector.Identity {
displayName := getStringData(account, "display_name")
if displayName == "" {
displayName = derefString(account.Authentication.Local.Username)
}
return connector.Identity{
UserID: account.ID,
Username: displayName,
PreferredUsername: derefString(account.Authentication.Local.Username),
Email: getStringData(account, "email"),
EmailVerified: true,
Groups: getGroups(account),
ConnectorData: nil,
}
}
// dataKeys returns the keys of a map for debug logging.
func dataKeys(m map[string]any) []string {
keys := make([]string, 0, len(m))
for k := range m {
keys = append(keys, k)
}
return keys
}
// derefString safely dereferences a *string, returning "" if nil.
func derefString(s *string) string {
if s == nil {
return ""
}
return *s
}
// getStringData retrieves a string value from account.Data by key.
func getStringData(account *storage.Account, key string) string {
if account.Data == nil {
return ""
}
v, ok := account.Data[key]
if !ok {
return ""
}
s, ok := v.(string)
if !ok {
return ""
}
return s
}
// getGroups retrieves the groups slice from account.Data["groups"].
// Uses JSON round-tripping to handle any BSON/primitive type from MongoDB.
func getGroups(account *storage.Account) []string {
if account.Data == nil {
return []string{}
}
v, ok := account.Data["groups"]
if !ok || v == nil {
return []string{}
}
// JSON round-trip handles primitive.A, []interface{}, []string, etc.
b, err := json.Marshal(v)
if err != nil {
return []string{}
}
var groups []string
if err := json.Unmarshal(b, &groups); err != nil {
return []string{}
}
if groups == nil {
return []string{}
}
return groups
}

View File

@@ -1,101 +0,0 @@
package op
import (
"fmt"
"html/template"
"net/http"
"time"
"github.com/gorilla/csrf"
"github.com/gorilla/mux"
"github.com/ory/fosite"
"github.com/ory/fosite/handler/openid"
"github.com/ory/fosite/token/jwt"
)
func (op *OIDCHandler) AuthEndpoint(w http.ResponseWriter, r *http.Request) {
namespace := mux.Vars(r)["namespace"]
oauth2Provider := op.NamespaceProviders[namespace]
templates_dir := op.config.Namespaces[namespace].TemplatesDir
t := template.New("auth")
t = template.Must(t.ParseFiles(
templates_dir + "/auth.html",
))
ctx := r.Context()
ar, err := oauth2Provider.NewAuthorizeRequest(ctx, r)
if err != nil {
oauth2Provider.WriteAuthorizeError(w, ar, err)
return
}
if r.Method == "POST" {
if r.Form.Get("username") == "" || r.Form.Get("password") == "" {
oauth2Provider.WriteAuthorizeError(w, ar, fosite.ErrAccessDenied)
return
}
account, err := op.handler.Login(r.Form.Get("username"), r.Form.Get("password"), namespace)
if err != nil {
if err = t.ExecuteTemplate(w, "auth", map[string]any{
csrf.TemplateTag: csrf.TemplateField(r),
"error": fmt.Sprintf("Wrong username (%v) or password (%v) in namespace \"%v\"", r.Form.Get("username"), r.Form.Get("password"), namespace),
"realError": err,
}); err != nil {
oauth2Provider.WriteAuthorizeError(w, ar, err)
}
return
}
sessionData := &openid.DefaultSession{
Claims: &jwt.IDTokenClaims{
Issuer: fmt.Sprintf("%s://%s/%s", op.Protocol, r.Host, namespace),
Subject: account.ID,
Audience: []string{},
ExpiresAt: time.Now().Add(time.Hour * 30),
IssuedAt: time.Now(),
RequestedAt: time.Now(),
AuthTime: time.Now(),
Extra: make(map[string]interface{}),
},
Username: r.Form.Get("username"),
Subject: account.ID,
Headers: &jwt.Headers{
Extra: make(map[string]interface{}),
},
}
// Manage claims
for _, v := range ar.GetRequestedScopes() {
ar.GrantScope(v)
if v != "openid" { // TODO handle standard claims like profile, email, ...
if mc, ok := op.config.Namespaces[namespace].MatchClaims[v]; ok {
if d, ok := account.Data[mc]; ok {
sessionData.Claims.Extra[v] = d
}
} else if d, ok := account.Data[v]; ok {
sessionData.Claims.Extra[v] = d
}
}
}
response, err := oauth2Provider.NewAuthorizeResponse(ctx, ar, sessionData)
if err != nil {
oauth2Provider.WriteAuthorizeError(w, ar, err)
return
}
oauth2Provider.WriteAuthorizeResponse(w, ar, response)
return
}
err = t.ExecuteTemplate(w, "auth", map[string]any{
// csrf.TemplateTag: csrf.TemplateField(r),
})
if err != nil {
panic(err)
}
}

View File

@@ -1,26 +0,0 @@
package op
import (
"log"
"net/http"
"github.com/gorilla/mux"
"github.com/ory/fosite"
)
func (op *OIDCHandler) IntrospectionEndpoint(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
namespace := mux.Vars(r)["namespace"]
oauth2Provider := op.NamespaceProviders[namespace]
ctx := r.Context()
mySessionData := new(fosite.DefaultSession)
ir, err := oauth2Provider.NewIntrospectionRequest(ctx, r, mySessionData)
if err != nil {
log.Printf("Error occurred in NewIntrospectionRequest: %+v", err)
oauth2Provider.WriteIntrospectionError(w, err)
return
}
oauth2Provider.WriteIntrospectionResponse(w, ir)
}

View File

@@ -1,41 +0,0 @@
package op
import (
"fmt"
"net/http"
"github.com/gorilla/mux"
"github.com/ory/fosite/handler/openid"
)
func (op *OIDCHandler) TokenEndpoint(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
namespace := mux.Vars(req)["namespace"]
provider := op.NamespaceProviders[namespace]
ctx := req.Context()
mySessionData := openid.NewDefaultSession()
accessRequest, err := provider.NewAccessRequest(ctx, req, mySessionData)
if err != nil {
fmt.Printf("Error occurred in NewAccessRequest: %+v", err)
provider.WriteAccessError(w, accessRequest, err)
return
}
if accessRequest.GetGrantTypes().ExactOne("client_credentials") {
for _, scope := range accessRequest.GetRequestedScopes() {
accessRequest.GrantScope(scope)
}
}
response, err := provider.NewAccessResponse(ctx, accessRequest)
if err != nil {
fmt.Printf("Error occurred in NewAccessResponse: %+v", err)
provider.WriteAccessError(w, accessRequest, err)
return
}
provider.WriteAccessResponse(w, accessRequest, response)
}

View File

@@ -1,8 +0,0 @@
package op
import "net/http"
func (op *OIDCHandler) UserinfoEndpoint(w http.ResponseWriter, req *http.Request) {
// TODO
w.WriteHeader(http.StatusNotFound)
}

View File

@@ -1,63 +0,0 @@
package op
import (
"encoding/json"
"fmt"
"net/http"
"github.com/gorilla/mux"
"gopkg.in/square/go-jose.v2"
)
func (op *OIDCHandler) WellKnownOIDCEndpoint(w http.ResponseWriter, r *http.Request) {
var (
host = r.Host
namespace = mux.Vars(r)["namespace"]
protocol = op.Protocol
issuer = fmt.Sprintf("%s://%s/%s", protocol, host, namespace)
)
response := map[string]any{
"issuer": issuer,
"authorization_endpoint": issuer + "/auth",
"token_endpoint": issuer + "/token",
"userinfo_endpoint": issuer + "/userinfo",
"id_token_signing_alg_values_supported": []string{"RS256"},
"grant_types_supported": []string{"authorization_code", "implicit", "client_credentials", "refresh_token"},
"response_types": []string{"code", "code id_token", "id_token", "token id_token", "token", "token id_token code"},
"response_modes_supported": []string{"query", "fragment"},
"jwks_uri": issuer + "/.well-known/jwks.json",
}
json, err := json.Marshal(response)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write(json)
}
func (op *OIDCHandler) WellKnownJWKSEndpoint(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
jwks := &jose.JSONWebKeySet{
Keys: []jose.JSONWebKey{
{
KeyID: "kid-foo",
Use: "sig",
Key: &op.PrivateKey.PublicKey,
},
},
}
jsonJwks, err := json.Marshal(jwks)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
}
w.WriteHeader(http.StatusOK)
w.Write(jsonJwks)
}

View File

@@ -1,565 +0,0 @@
package op
import (
"context"
"crypto/rsa"
"errors"
"reflect"
"time"
"git.coopgo.io/coopgo-platform/mobility-accounts/handlers"
"git.coopgo.io/coopgo-platform/mobility-accounts/storage"
"github.com/mitchellh/mapstructure"
"github.com/ory/fosite"
"github.com/ory/fosite/compose"
"github.com/ory/fosite/handler/openid"
"gopkg.in/square/go-jose.v2"
)
func NewProvider(c OIDCNamespaceConfig, h handlers.MobilityAccountsHandler, s storage.Storage, privateKey *rsa.PrivateKey) fosite.OAuth2Provider {
config := &compose.Config{}
storage := NewOIDCProviderStore(c, h, s.KV)
secret := []byte(c.SecretKey)
return compose.ComposeAllEnabled(config, storage, secret, privateKey)
}
type OIDCProviderStore struct {
Namespace string
MobilityAccountsHandler handlers.MobilityAccountsHandler
KV storage.KVStore
Clients map[string]fosite.Client
}
func NewOIDCProviderStore(c OIDCNamespaceConfig, h handlers.MobilityAccountsHandler, storage storage.KVStore) *OIDCProviderStore {
clients := map[string]fosite.Client{}
for _, v := range c.Clients {
client := &fosite.DefaultClient{
ID: v.ID,
Secret: []byte(v.Secret),
RedirectURIs: v.RedirectURIs,
ResponseTypes: v.ResponseTypes,
GrantTypes: v.GrantTypes,
Scopes: v.Scopes,
Audience: v.Audience,
Public: v.Public,
}
if v.OIDC {
oidc_client := &fosite.DefaultOpenIDConnectClient{
DefaultClient: client,
TokenEndpointAuthMethod: v.TokenEndpointAuthMethod,
}
clients[v.ID] = oidc_client
} else {
clients[v.ID] = client
}
}
return &OIDCProviderStore{
MobilityAccountsHandler: h,
KV: storage,
Clients: clients,
}
}
func (s *OIDCProviderStore) GetClient(_ context.Context, id string) (fosite.Client, error) {
cl, ok := s.Clients[id]
if !ok {
return nil, fosite.ErrNotFound
}
return cl, nil
}
func (s *OIDCProviderStore) Authenticate(_ context.Context, name string, secret string) error {
_, err := s.MobilityAccountsHandler.Login(name, secret, s.Namespace)
if err != nil {
return fosite.ErrNotFound
}
return nil
}
func (s *OIDCProviderStore) CreateOpenIDConnectSession(_ context.Context, authorizeCode string, requester fosite.Requester) error {
err := s.KV.Put("id_sessions/"+authorizeCode, requester)
if err != nil {
return err
}
return nil
}
func (s *OIDCProviderStore) GetOpenIDConnectSession(_ context.Context, authorizeCode string, requester fosite.Requester) (fosite.Requester, error) {
d, err := s.KV.Get("id_sessions/" + authorizeCode)
if err != nil {
return nil, fosite.ErrNotFound
}
//return d.(fosite.Requester), nil
return DecodeRequest(d)
// req := fosite.NewRequest()
// req.Session = new(openid.DefaultSession)
// decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
// Metadata: nil,
// DecodeHook: mapstructure.ComposeDecodeHookFunc(
// ToTimeHookFunc()),
// Result: &req,
// })
// if err != nil {
// return req, err
// }
// if err = decoder.Decode(d); err != nil {
// return req, err
// }
// return req, nil
}
// DeleteOpenIDConnectSession is not really called from anywhere and it is deprecated.
func (s *OIDCProviderStore) DeleteOpenIDConnectSession(_ context.Context, authorizeCode string) error {
err := s.KV.Delete("id_sessions/" + authorizeCode)
if err != nil {
return err
}
return nil
}
func (s *OIDCProviderStore) ClientAssertionJWTValid(_ context.Context, jti string) error {
if _, exists := s.KV.Get("blacklisted_jtis/" + jti); exists == nil {
return fosite.ErrJTIKnown
}
return nil
}
func (s *OIDCProviderStore) SetClientAssertionJWT(_ context.Context, jti string, exp time.Time) error {
if _, exists := s.KV.Get("blacklisted_jtis/" + jti); exists == nil {
return fosite.ErrJTIKnown
}
duration := exp.Sub(time.Now())
if duration < 0 {
return errors.New("already expired")
}
err := s.KV.PutWithTTL("blacklisted_jtis/"+jti, true, duration)
if err != nil {
return err
}
return nil
}
func (s *OIDCProviderStore) CreateAuthorizeCodeSession(_ context.Context, code string, req fosite.Requester) error {
res := StoreAuthorizeCode{
Active: true,
Requester: req.(*fosite.Request),
}
err := s.KV.Put("authorize_codes/"+code, res)
if err != nil {
return err
}
return nil
}
func (s *OIDCProviderStore) GetAuthorizeCodeSession(_ context.Context, code string, _ fosite.Session) (fosite.Requester, error) {
rel, err := s.KV.Get("authorize_codes/" + code)
if err != nil {
return nil, fosite.ErrNotFound
}
sac, err := DecodeStoreAuthorizeCode(rel)
if err != nil {
return nil, err
}
if !sac.Active {
return sac.Requester, fosite.ErrInvalidatedAuthorizeCode
}
return sac.Requester, nil
}
func (s *OIDCProviderStore) InvalidateAuthorizeCodeSession(ctx context.Context, code string) error {
rel, err := s.KV.Get("authorize_codes/" + code)
if err != nil {
return fosite.ErrNotFound
}
sac, err := DecodeStoreAuthorizeCode(rel)
if err != nil {
return err
}
sac.Active = false
err = s.KV.Put("authorize_codes/"+code, sac)
if err != nil {
return err
}
return nil
}
func (s *OIDCProviderStore) CreatePKCERequestSession(_ context.Context, code string, req fosite.Requester) error {
err := s.KV.Put("pkce/"+code, req)
if err != nil {
return err
}
return nil
}
func (s *OIDCProviderStore) GetPKCERequestSession(_ context.Context, code string, _ fosite.Session) (fosite.Requester, error) {
rel, err := s.KV.Get("pkce/" + code)
if err != nil {
return nil, fosite.ErrNotFound
}
req := fosite.NewRequest()
req.Session = new(fosite.DefaultSession)
decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
Metadata: nil,
DecodeHook: mapstructure.ComposeDecodeHookFunc(
ToTimeHookFunc()),
Result: &req,
})
if err != nil {
return req, err
}
if err = decoder.Decode(rel); err != nil {
return req, err
}
return req, nil
}
func (s *OIDCProviderStore) DeletePKCERequestSession(_ context.Context, code string) error {
err := s.KV.Delete("pkce/" + code)
if err != nil {
return fosite.ErrNotFound
}
return nil
}
func (s *OIDCProviderStore) CreateAccessTokenSession(_ context.Context, signature string, req fosite.Requester) error {
err := s.KV.Put("access_tokens/"+signature, req)
if err != nil {
return err
}
err = s.KV.Put("access_tokens_request_ids/"+req.GetID(), signature)
if err != nil {
return err
}
return nil
}
func (s *OIDCProviderStore) GetAccessTokenSession(_ context.Context, signature string, _ fosite.Session) (fosite.Requester, error) {
rel, err := s.KV.Get("access_tokens/" + signature)
if err != nil {
return nil, fosite.ErrNotFound
}
//return rel.(fosite.Requester), nil
req := fosite.NewRequest()
req.Session = new(fosite.DefaultSession)
decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
Metadata: nil,
DecodeHook: mapstructure.ComposeDecodeHookFunc(
ToTimeHookFunc()),
Result: &req,
})
if err != nil {
return req, err
}
if err = decoder.Decode(rel); err != nil {
return req, err
}
return req, nil
}
func (s *OIDCProviderStore) DeleteAccessTokenSession(_ context.Context, signature string) error {
err := s.KV.Delete("access_tokens/" + signature)
if err != nil {
return fosite.ErrNotFound
}
return nil
}
func (s *OIDCProviderStore) CreateRefreshTokenSession(_ context.Context, signature string, req fosite.Requester) error {
err := s.KV.Put("refresh_tokens/"+signature, StoreRefreshToken{Active: true, Requester: req})
if err != nil {
return err
}
err = s.KV.Put("refresh_tokens_request_ids/"+req.GetID(), signature)
if err != nil {
return err
}
return nil
}
func (s *OIDCProviderStore) GetRefreshTokenSession(_ context.Context, signature string, _ fosite.Session) (fosite.Requester, error) {
rel, err := s.KV.Get("refresh_tokens/" + signature)
if err != nil {
return nil, fosite.ErrNotFound
}
var srt StoreRefreshToken
if err = mapstructure.Decode(rel.(map[string]any), &srt); err != nil {
return nil, err
}
if !srt.Active {
return nil, fosite.ErrInactiveToken
}
return srt.Requester, nil
}
func (s *OIDCProviderStore) DeleteRefreshTokenSession(_ context.Context, signature string) error {
err := s.KV.Delete("refresh_tokens/" + signature)
if err != nil {
return fosite.ErrNotFound
}
return nil
}
func (s *OIDCProviderStore) RevokeRefreshToken(ctx context.Context, requestID string) error {
if signature, err := s.KV.Get("refresh_tokens_request_ids" + requestID); err == nil {
rel, err := s.KV.Get("refresh_tokens/" + signature.(string))
if err != nil {
return fosite.ErrNotFound
}
var srt StoreRefreshToken
if err = mapstructure.Decode(rel.(map[string]any), &srt); err != nil {
return err
}
srt.Active = false
err = s.KV.Put("refresh_tokens/"+signature.(string), srt)
if err != nil {
return err
}
}
return nil
}
func (s *OIDCProviderStore) RevokeRefreshTokenMaybeGracePeriod(ctx context.Context, requestID string, signature string) error {
// no configuration option is available; grace period is not available with memory store
return s.RevokeRefreshToken(ctx, requestID)
}
func (s *OIDCProviderStore) RevokeAccessToken(ctx context.Context, requestID string) error {
if signature, err := s.KV.Get("access_tokens_request_ids/" + requestID); err != nil {
if err := s.DeleteAccessTokenSession(ctx, signature.(string)); err != nil {
return err
}
}
return nil
}
func (s *OIDCProviderStore) GetPublicKey(ctx context.Context, issuer string, subject string, keyId string) (*jose.JSONWebKey, error) {
if issuerKeys, err := s.KV.Get("issuer_public_keys/" + issuer); err == nil {
var ipk IssuerPublicKeys
if err = mapstructure.Decode(issuerKeys.(map[string]any), &ipk); err != nil {
return nil, err
}
if subKeys, ok := ipk.KeysBySub[subject]; ok {
if keyScopes, ok := subKeys.Keys[keyId]; ok {
return keyScopes.Key, nil
}
}
}
return nil, fosite.ErrNotFound
}
func (s *OIDCProviderStore) GetPublicKeys(ctx context.Context, issuer string, subject string) (*jose.JSONWebKeySet, error) {
if issuerKeys, err := s.KV.Get("issuer_public_keys/" + issuer); err == nil {
var ipk IssuerPublicKeys
if err = mapstructure.Decode(issuerKeys.(map[string]any), &ipk); err != nil {
return nil, err
}
if subKeys, ok := ipk.KeysBySub[subject]; ok {
if len(subKeys.Keys) == 0 {
return nil, fosite.ErrNotFound
}
keys := make([]jose.JSONWebKey, 0, len(subKeys.Keys))
for _, keyScopes := range subKeys.Keys {
keys = append(keys, *keyScopes.Key)
}
return &jose.JSONWebKeySet{Keys: keys}, nil
}
}
return nil, fosite.ErrNotFound
}
func (s *OIDCProviderStore) GetPublicKeyScopes(ctx context.Context, issuer string, subject string, keyId string) ([]string, error) {
if issuerKeys, err := s.KV.Get("issuer_public_keys/" + issuer); err == nil {
var ipk IssuerPublicKeys
if err = mapstructure.Decode(issuerKeys.(map[string]any), &ipk); err != nil {
return nil, err
}
if subKeys, ok := ipk.KeysBySub[subject]; ok {
if keyScopes, ok := subKeys.Keys[keyId]; ok {
return keyScopes.Scopes, nil
}
}
}
return nil, fosite.ErrNotFound
}
func (s *OIDCProviderStore) IsJWTUsed(ctx context.Context, jti string) (bool, error) {
err := s.ClientAssertionJWTValid(ctx, jti)
if err != nil {
return true, nil
}
return false, nil
}
func (s *OIDCProviderStore) MarkJWTUsedForTime(ctx context.Context, jti string, exp time.Time) error {
return s.SetClientAssertionJWT(ctx, jti, exp)
}
// CreatePARSession stores the pushed authorization request context. The requestURI is used to derive the key.
func (s *OIDCProviderStore) CreatePARSession(ctx context.Context, requestURI string, request fosite.AuthorizeRequester) error {
err := s.KV.Put("par_sessions/"+requestURI, request)
if err != nil {
return err
}
return nil
}
// GetPARSession gets the push authorization request context. If the request is nil, a new request object
// is created. Otherwise, the same object is updated.
func (s *OIDCProviderStore) GetPARSession(ctx context.Context, requestURI string) (fosite.AuthorizeRequester, error) {
rel, err := s.KV.Get("par_sessions/" + requestURI)
if err != nil {
return nil, fosite.ErrNotFound
}
return rel.(fosite.AuthorizeRequester), nil
}
// DeletePARSession deletes the context.
func (s *OIDCProviderStore) DeletePARSession(ctx context.Context, requestURI string) error {
err := s.KV.Delete("par_sessions/" + requestURI)
if err != nil {
return fosite.ErrNotFound
}
return nil
}
type StoreAuthorizeCode struct {
Active bool `json:"active"`
Requester *fosite.Request `json:"requester"`
}
func DecodeStoreAuthorizeCode(rel interface{}) (StoreAuthorizeCode, error) {
sac := StoreAuthorizeCode{
Active: false,
Requester: fosite.NewRequest(),
}
// metadata := mapstructure.Metadata{}
sac.Requester.Session = new(openid.DefaultSession)
decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
// Metadata: &metadata,
DecodeHook: mapstructure.ComposeDecodeHookFunc(
ToTimeHookFunc(),
ToBytes(),
),
TagName: "json",
Result: &sac,
})
if err != nil {
return sac, err
}
if err = decoder.Decode(rel); err != nil {
return sac, err
}
return sac, nil
}
func DecodeRequest(rel interface{}) (*fosite.Request, error) {
req := fosite.NewRequest()
req.Session = new(openid.DefaultSession)
decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
// Metadata: &metadata,
DecodeHook: mapstructure.ComposeDecodeHookFunc(
ToTimeHookFunc(),
ToBytes(),
),
TagName: "json",
Result: &req,
})
if err != nil {
return req, err
}
if err = decoder.Decode(rel); err != nil {
return req, err
}
return req, nil
}
type StoreRefreshToken struct {
Active bool
Requester fosite.Requester
}
type IssuerPublicKeys struct {
Issuer string
KeysBySub map[string]SubjectPublicKeys `mapstructure:"keys_by_sub"`
}
type SubjectPublicKeys struct {
Subject string
Keys map[string]PublicKeyScopes
}
type PublicKeyScopes struct {
Key *jose.JSONWebKey
Scopes []string
}
func ToTimeHookFunc() mapstructure.DecodeHookFunc {
return func(
f reflect.Type,
t reflect.Type,
data interface{}) (interface{}, error) {
if t != reflect.TypeOf(time.Time{}) {
return data, nil
}
switch f.Kind() {
case reflect.String:
return time.Parse(time.RFC3339, data.(string))
case reflect.Float64:
return time.Unix(0, int64(data.(float64))*int64(time.Millisecond)), nil
case reflect.Int64:
return time.Unix(0, data.(int64)*int64(time.Millisecond)), nil
default:
return data, nil
}
// Convert it by parsing
}
}
func ToBytes() mapstructure.DecodeHookFunc {
return func(
f reflect.Type,
t reflect.Type,
data interface{}) (interface{}, error) {
if t == reflect.TypeOf([]byte("")) && f.Kind() == reflect.String {
return []byte(data.(string)), nil
}
return data, nil
}
}

View File

@@ -1,24 +1,33 @@
package op package op
import ( import (
"crypto/rand" "context"
"crypto/rsa"
"fmt" "fmt"
"log/slog"
"net/http"
"os"
"time"
"git.coopgo.io/coopgo-platform/mobility-accounts/handlers" "github.com/dexidp/dex/server"
"git.coopgo.io/coopgo-platform/mobility-accounts/storage" dexstorage "github.com/dexidp/dex/storage"
"github.com/dexidp/dex/storage/memory"
"github.com/mitchellh/mapstructure" "github.com/mitchellh/mapstructure"
"github.com/ory/fosite" "github.com/rs/zerolog/log"
"github.com/spf13/viper" "github.com/spf13/viper"
"gitlab.com/mobicoop/solidarity/services/mobility-accounts/handlers"
maconnector "gitlab.com/mobicoop/solidarity/services/mobility-accounts/oidc-provider/connector"
"gitlab.com/mobicoop/solidarity/services/mobility-accounts/storage"
) )
// OIDCConfig holds the full OIDC provider configuration, decoded from viper.
type OIDCConfig struct { type OIDCConfig struct {
Enable bool Enable bool
CSRFKey bool `mapstructure:"csrf_key"` Port string
Port bool BaseURL string `mapstructure:"base_url"`
Namespaces map[string]OIDCNamespaceConfig Namespaces map[string]OIDCNamespaceConfig
} }
// OIDCNamespaceConfig holds per-namespace OIDC settings.
type OIDCNamespaceConfig struct { type OIDCNamespaceConfig struct {
Namespace string Namespace string
SecretKey string `mapstructure:"secret_key"` SecretKey string `mapstructure:"secret_key"`
@@ -27,6 +36,7 @@ type OIDCNamespaceConfig struct {
Clients []OIDCClient Clients []OIDCClient
} }
// OIDCClient represents a static OIDC client.
type OIDCClient struct { type OIDCClient struct {
ID string ID string
OIDC bool OIDC bool
@@ -41,60 +51,137 @@ type OIDCClient struct {
TokenEndpointAuthMethod string `mapstructure:"token_endpoint_auth_method"` TokenEndpointAuthMethod string `mapstructure:"token_endpoint_auth_method"`
} }
type OIDCHandler struct { // NewDexServer creates an http.ServeMux that hosts one Dex OIDC server per namespace.
NamespaceProviders map[string]fosite.OAuth2Provider // Each namespace is mounted at /{namespaceName}/ and has its own storage, clients,
config OIDCConfig // and connector instance.
handler handlers.MobilityAccountsHandler func NewDexServer(handler *handlers.MobilityAccountsHandler, stor storage.Storage, cfg *viper.Viper) (*http.ServeMux, error) {
Protocol string //HTTP (dev env) or HTTPS var oidcConfig OIDCConfig
PrivateKey *rsa.PrivateKey mapstructure.Decode(cfg.Get("services.oidc_provider").(map[string]any), &oidcConfig)
baseURL := oidcConfig.BaseURL
if baseURL == "" {
protocol := "https"
if cfg.GetBool("dev_env") {
protocol = "http"
}
baseURL = fmt.Sprintf("%s://0.0.0.0:%s", protocol, cfg.GetString("services.oidc_provider.port"))
}
mux := http.NewServeMux()
logger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelInfo}))
// Register our custom connector type in Dex's global registry
server.ConnectorsConfig["mobilityaccounts"] = func() server.ConnectorConfig {
return &maconnector.Config{
Handler: handler,
Storage: stor,
Namespace: "", // will be set per-namespace below
}
}
for nsName, nsCfg := range oidcConfig.Namespaces {
dexServer, err := createNamespaceDexServer(handler, stor, nsCfg, nsName, baseURL, logger)
if err != nil {
return nil, fmt.Errorf("failed to create Dex server for namespace %q: %w", nsName, err)
}
prefix := "/" + nsName
mux.Handle(prefix+"/", dexServer)
}
return mux, nil
} }
func NewOIDCHandler(h handlers.MobilityAccountsHandler, storage storage.Storage, config *viper.Viper) *OIDCHandler { // createNamespaceDexServer builds a single Dex server.Server for one namespace.
var oidc_config OIDCConfig func createNamespaceDexServer(handler *handlers.MobilityAccountsHandler, stor storage.Storage, nsCfg OIDCNamespaceConfig, nsName, baseURL string, logger *slog.Logger) (*server.Server, error) {
ctx := context.Background()
mapstructure.Decode(config.Get("services.oidc_provider").(map[string]any), &oidc_config) // In-memory Dex storage
dexStore := memory.New(logger)
providers := map[string]fosite.OAuth2Provider{} // Register static clients
clients := buildDexClients(nsCfg.Clients)
dexStore = dexstorage.WithStaticClients(dexStore, clients)
privateKey, err := rsa.GenerateKey(rand.Reader, 2048) // Register the connector — we override ConnectorsConfig factory for this namespace
// so that Open() will get the right handler/storage/namespace.
server.ConnectorsConfig["mobilityaccounts"] = func() server.ConnectorConfig {
return &maconnector.Config{
Handler: handler,
Storage: stor,
Namespace: nsCfg.Namespace,
}
}
conn := dexstorage.Connector{
ID: "mobilityaccounts",
Type: "mobilityaccounts",
Name: "Mobility Accounts",
}
dexStore = dexstorage.WithStaticConnectors(dexStore, []dexstorage.Connector{conn})
issuer := fmt.Sprintf("%s/%s", baseURL, nsName)
// Determine web config
webCfg := server.WebConfig{
Dir: "/web",
Issuer: nsName,
}
// Dex v2.42 manages signing keys internally via storage.
dexServer, err := server.NewServer(ctx, server.Config{
Issuer: issuer,
Storage: dexStore,
SkipApprovalScreen: true,
IDTokensValidFor: 30 * time.Hour,
Web: webCfg,
Logger: logger,
Now: time.Now,
})
if err != nil { if err != nil {
return nil return nil, fmt.Errorf("failed to create Dex server: %w", err)
} }
for _, c := range oidc_config.Namespaces { return dexServer, nil
np := NewProvider(c, h, storage, privateKey)
providers[c.Namespace] = np
}
protocol := "https"
if config.GetBool("dev_env") {
protocol = "http"
}
return &OIDCHandler{
config: oidc_config,
handler: h,
NamespaceProviders: providers,
Protocol: protocol,
PrivateKey: privateKey,
}
} }
func Run(done chan error, cfg *viper.Viper, handler handlers.MobilityAccountsHandler, storage storage.Storage) { // buildDexClients converts the config OIDCClient list to Dex storage.Client list.
var ( func buildDexClients(clients []OIDCClient) []dexstorage.Client {
address = "0.0.0.0:" + cfg.GetString("services.oidc_provider.port") dexClients := make([]dexstorage.Client, 0, len(clients))
) for _, c := range clients {
dexClients = append(dexClients, dexstorage.Client{
ID: c.ID,
Secret: c.Secret,
RedirectURIs: c.RedirectURIs,
Public: c.Public,
Name: c.ID,
})
}
return dexClients
}
fmt.Println("-> OIDC provider endpoints on", address) // Run starts the OIDC provider HTTP server. Called from main.go as a goroutine.
func Run(done chan error, cfg *viper.Viper, handler handlers.MobilityAccountsHandler, stor storage.Storage) {
s := NewOIDCHandler(handler, storage, cfg) address := "0.0.0.0:" + cfg.GetString("services.oidc_provider.port")
log.Info().Str("address", address).Msg("Running Dex OIDC provider")
err := NewOIDCServer(s, cfg)
mux, err := NewDexServer(&handler, stor, cfg)
if err != nil { if err != nil {
fmt.Println("OIDC server ended") log.Error().Err(err).Msg("Failed to create Dex OIDC server")
done <- err
return
} }
srv := &http.Server{
Handler: mux,
Addr: address,
WriteTimeout: 15 * time.Second,
ReadTimeout: 15 * time.Second,
}
err = srv.ListenAndServe()
if err != nil {
log.Error().Err(err).Msg("Dex OIDC server ended")
}
done <- err done <- err
} }

View File

@@ -1,40 +0,0 @@
package op
import (
"net/http"
"time"
"github.com/gorilla/csrf"
"github.com/gorilla/mux"
"github.com/spf13/viper"
)
func NewOIDCServer(oidc_handler *OIDCHandler, cfg *viper.Viper) error {
var (
dev_env = cfg.GetBool("dev_env")
address = "0.0.0.0:" + cfg.GetString("services.oidc_provider.port")
//csrf_key = cfg.GetString("services.oidc_provider.csrf_key")
)
router := mux.NewRouter()
router.HandleFunc("/{namespace}/auth", oidc_handler.AuthEndpoint)
router.HandleFunc("/{namespace}/token", oidc_handler.TokenEndpoint)
router.HandleFunc("/{namespace}/introspect", oidc_handler.IntrospectionEndpoint)
router.HandleFunc("/{namespace}/userinfo", oidc_handler.UserinfoEndpoint)
router.HandleFunc("/{namespace}/.well-known/openid-configuration", oidc_handler.WellKnownOIDCEndpoint)
router.HandleFunc("/{namespace}/.well-known/jwks.json", oidc_handler.WellKnownJWKSEndpoint)
if dev_env {
csrf.Secure(false)
}
srv := &http.Server{
Handler: router,
Addr: address,
WriteTimeout: 15 * time.Second,
ReadTimeout: 15 * time.Second,
}
err := srv.ListenAndServe()
return err
}

View File

@@ -0,0 +1,2 @@
User-agent: *
Disallow: /

View File

@@ -0,0 +1 @@
/* Mobicoop Solidaire — static styles are inlined in header.html */

View File

@@ -0,0 +1,22 @@
{{ template "header.html" . }}
<h2>Autorisation</h2>
<p style="text-align:center; font-size:0.875rem; margin-bottom:1rem;">
<strong>{{ .Client }}</strong> souhaite acceder a votre compte.
</p>
{{ if .Scopes }}
<p style="font-size:0.875rem;">Permissions demandees :</p>
<ul class="scopes-list">
{{ range $s := .Scopes }}
<li>{{ $s }}</li>
{{ end }}
</ul>
{{ end }}
<form method="POST" action="{{ .Approval }}">
<button type="submit" class="btn-primary">Autoriser</button>
</form>
{{ template "footer.html" . }}

View File

@@ -0,0 +1,21 @@
{{ template "header.html" . }}
<h2>Connexion appareil</h2>
{{ if .Invalid }}
<div class="error-box">
Code invalide. Veuillez reessayer.
</div>
{{ end }}
<form method="POST" action="{{ .PostURL }}">
<div class="form-group">
<label for="user_code">Code utilisateur</label>
<input required id="user_code" name="user_code" type="text"
{{ if .UserCode }}value="{{ .UserCode }}"{{ end }}
placeholder="XXXX-XXXX" autofocus>
</div>
<button type="submit" class="btn-primary">Valider</button>
</form>
{{ template "footer.html" . }}

View File

@@ -0,0 +1,9 @@
{{ template "header.html" . }}
<h2>Appareil connecte</h2>
<p style="text-align:center; font-size:0.875rem;">
Votre appareil <strong>{{ .ClientName }}</strong> est maintenant connecte. Vous pouvez fermer cette page.
</p>
{{ template "footer.html" . }}

View File

@@ -0,0 +1,14 @@
{{ template "header.html" . }}
<h2>Erreur</h2>
<div class="error-box">
{{ if .ErrType }}<strong>{{ .ErrType }}</strong><br>{{ end }}
{{ if .ErrMsg }}{{ .ErrMsg }}{{ else }}Une erreur inattendue est survenue.{{ end }}
</div>
<div class="link-center">
<a href="javascript:history.back()">Retour</a>
</div>
{{ template "footer.html" . }}

View File

@@ -0,0 +1,3 @@
</div>
</body>
</html>

View File

@@ -0,0 +1,161 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ issuer }} - Connexion</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: 'Poppins', sans-serif;
background-color: #f9fafb;
color: #1f2937;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.card {
background: #fff;
border-radius: 1rem;
box-shadow: 0 1px 3px rgba(0,0,0,0.08);
padding: 2.5rem 2rem;
width: 100%;
max-width: 28rem;
margin: 1rem;
}
.logo {
display: block;
margin: 0 auto 1.5rem;
max-width: 200px;
height: auto;
}
h2 {
text-align: center;
font-size: 1.5rem;
font-weight: 600;
color: #243887;
margin-bottom: 1.5rem;
}
.form-group { margin-bottom: 1rem; }
label {
display: block;
font-size: 0.875rem;
font-weight: 500;
color: #374151;
margin-bottom: 0.25rem;
}
input[type="text"],
input[type="email"],
input[type="password"] {
width: 100%;
padding: 0.625rem 0.875rem;
border: 1px solid #d1d5db;
border-radius: 1rem;
font-family: 'Poppins', sans-serif;
font-size: 0.875rem;
outline: none;
transition: border-color 0.15s;
}
input[type="text"]:focus,
input[type="email"]:focus,
input[type="password"]:focus {
border-color: #243887;
box-shadow: 0 0 0 2px rgba(36,56,135,0.15);
}
.btn-primary {
display: block;
width: 100%;
padding: 0.625rem;
background-color: #243887;
color: #fff;
border: none;
border-radius: 1rem;
font-family: 'Poppins', sans-serif;
font-size: 0.875rem;
font-weight: 600;
cursor: pointer;
transition: background-color 0.15s;
margin-top: 1.25rem;
}
.btn-primary:hover { background-color: #1c2d6e; }
.error-box {
background-color: #fef2f2;
border: 1px solid #fecaca;
color: #991b1b;
padding: 0.75rem 1rem;
border-radius: 0.75rem;
font-size: 0.8125rem;
margin-bottom: 1rem;
}
.link-center {
text-align: center;
margin-top: 1rem;
}
.link-center a {
color: #243887;
font-size: 0.8125rem;
text-decoration: none;
font-weight: 500;
}
.link-center a:hover { text-decoration: underline; }
.back-link {
text-align: center;
margin-top: 0.75rem;
}
.back-link a {
color: #6b7280;
font-size: 0.8125rem;
text-decoration: none;
}
.back-link a:hover { text-decoration: underline; }
.connector-list { list-style: none; }
.connector-list li { margin-bottom: 0.5rem; }
.connector-list a {
display: block;
text-align: center;
padding: 0.625rem;
background-color: #243887;
color: #fff;
border-radius: 1rem;
text-decoration: none;
font-weight: 600;
font-size: 0.875rem;
transition: background-color 0.15s;
}
.connector-list a:hover { background-color: #1c2d6e; }
.scopes-list {
list-style: disc;
padding-left: 1.5rem;
margin: 1rem 0;
font-size: 0.875rem;
}
</style>
</head>
<body>
<div class="card">

View File

@@ -0,0 +1,18 @@
{{ template "header.html" . }}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 48" class="logo">
<text x="50%" y="50%" dominant-baseline="central" text-anchor="middle"
font-family="Poppins, sans-serif" font-weight="700" font-size="18" fill="#243887">
Mobicoop Solidaire
</text>
</svg>
<h2>Connexion</h2>
<ul class="connector-list">
{{ range $c := .Connectors }}
<li><a href="{{ $c.URL }}">{{ $c.Name }}</a></li>
{{ end }}
</ul>
{{ template "footer.html" . }}

View File

@@ -0,0 +1,13 @@
{{ template "header.html" . }}
<h2>Code d'autorisation</h2>
<p style="text-align:center; font-size:0.875rem; margin-bottom:1rem;">
Copiez ce code dans votre application :
</p>
<div style="text-align:center; font-size:1.25rem; font-weight:600; color:#243887; background:#f3f4f6; padding:1rem; border-radius:0.75rem; font-family:monospace;">
{{ .Code }}
</div>
{{ template "footer.html" . }}

View File

@@ -0,0 +1,41 @@
{{ template "header.html" . }}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 48" class="logo">
<text x="50%" y="50%" dominant-baseline="central" text-anchor="middle"
font-family="Poppins, sans-serif" font-weight="700" font-size="18" fill="#243887">
Mobicoop Solidaire
</text>
</svg>
<h2>Connexion</h2>
{{ if .Invalid }}
<div class="error-box">
Identifiant ou mot de passe incorrect.
</div>
{{ end }}
<form method="POST" action="{{ .PostURL }}">
<div class="form-group">
<label for="login">{{ .UsernamePrompt }}</label>
<input tabindex="1" required id="login" name="login" type="email"
placeholder="email@exemple.fr"
{{ if .Username }}value="{{ .Username }}"{{ else }}autofocus{{ end }}>
</div>
<div class="form-group">
<label for="password">Mot de passe</label>
<input tabindex="2" required id="password" name="password" type="password"
placeholder="mot de passe" {{ if .Invalid }}autofocus{{ end }}>
</div>
<button tabindex="3" type="submit" class="btn-primary">Se connecter</button>
</form>
{{ if .BackLink }}
<div class="back-link">
<a href="{{ .BackLink }}">Choisir une autre methode de connexion</a>
</div>
{{ end }}
{{ template "footer.html" . }}

View File

@@ -0,0 +1 @@
/* Mobicoop Solidaire theme — styles are inlined in header.html */

View File

@@ -6,20 +6,21 @@ type Account struct {
Authentication AccountAuth `json:"-" bson:"authentication"` Authentication AccountAuth `json:"-" bson:"authentication"`
Data map[string]any `json:"data"` Data map[string]any `json:"data"`
Metadata map[string]any `json:"metadata"` Metadata map[string]any `json:"metadata"`
Deleted bool `json:"deleted" bson:"deleted"`
} }
type AccountAuth struct { type AccountAuth struct {
Local LocalAuth Local *LocalAuth `bson:"local,omitempty"`
//TODO handle SSO //TODO handle SSO
} }
type LocalAuth struct { type LocalAuth struct {
Username string `json:"username"` Username *string `json:"username" bson:"username,omitempty"`
Password string `json:"password"` Password string `json:"password" bson:"password"`
Email string `json:"email"` Email *string `json:"email" bson:"email,omitempty"`
EmailValidation Validation `json:"email_validation" bson:"email_validation"` EmailValidation *Validation `json:"email_validation" bson:"email_validation,omitempty"`
PhoneNumber string `json:"phone_number" bson:"phone_number"` PhoneNumber *string `json:"phone_number" bson:"phone_number,omitempty"`
PhoneNumberValidation Validation `json:"phone_number_validation" bson:"phone_number_validation"` PhoneNumberValidation *Validation `json:"phone_number_validation" bson:"phone_number_validation,omitempty"`
} }
type Validation struct { type Validation struct {

View File

@@ -5,6 +5,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/rs/zerolog/log"
"github.com/spf13/viper" "github.com/spf13/viper"
"go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo"
@@ -27,7 +28,7 @@ func NewMongoDBStorage(cfg *viper.Viper) (MongoDBStorage, error) {
) )
if mongodb_uri == "" { if mongodb_uri == "" {
mongodb_uri = fmt.Sprintf("mongodb://%s:%s/%s", mongodb_host, mongodb_port, mongodb_dbname) mongodb_uri = fmt.Sprintf("mongodb://%s:%s", mongodb_host, mongodb_port)
} }
client, err := mongo.NewClient(options.Client().ApplyURI(mongodb_uri)) client, err := mongo.NewClient(options.Client().ApplyURI(mongodb_uri))
@@ -65,27 +66,26 @@ func NewMongoDBStorage(cfg *viper.Viper) (MongoDBStorage, error) {
// If username, is provided (not an empty string), it will search by username only // If username, is provided (not an empty string), it will search by username only
// If username is an empty string and email is provided, it will search by email // If username is an empty string and email is provided, it will search by email
// If both username and email are empty strings, phone_number must be provided and it will search by phone number // If both username and email are empty strings, phone_number must be provided and it will search by phone number
func (s MongoDBStorage) LocalAuthentication(namespace string, username string, email string, phone_number string) (*Account, error) { func (s MongoDBStorage) LocalAuthentication(namespace string, username *string, email *string, phone_number *string) (*Account, error) {
collection := s.Client.Database(s.DbName).Collection(s.Collections["users"]) collection := s.Client.Database(s.DbName).Collection(s.Collections["users"])
account := &Account{} account := &Account{}
if username != "" { if username != nil {
if err := collection.FindOne(context.TODO(), bson.M{"namespace": namespace, "authentication.local.username": username}).Decode(account); err != nil { if err := collection.FindOne(context.TODO(), bson.M{"namespace": namespace, "authentication.local.username": *username}).Decode(account); err != nil {
return nil, err return nil, err
} }
} else if email != "" { } else if email != nil {
if err := collection.FindOne(context.TODO(), bson.M{"namespace": namespace, "authentication.local.email": email}).Decode(account); err != nil { if err := collection.FindOne(context.TODO(), bson.M{"namespace": namespace, "authentication.local.email": *email}).Decode(account); err != nil {
return nil, err return nil, err
} }
} else if phone_number != "" { } else if phone_number != nil {
if err := collection.FindOne(context.TODO(), bson.M{"namespace": namespace, "authentication.local.phone_number": phone_number}).Decode(account); err != nil { if err := collection.FindOne(context.TODO(), bson.M{"namespace": namespace, "authentication.local.phone_number": *phone_number}).Decode(account); err != nil {
return nil, err return nil, err
} }
} else {
return nil, errors.New("missing username, email or password")
} }
// else {
// return nil, errors.New("missing username, email or password")
// }
return account, nil return account, nil
} }
@@ -186,9 +186,28 @@ func (s MongoDBStorage) CreateAccount(account Account) error {
func (s MongoDBStorage) UpdateAccount(account Account) error { func (s MongoDBStorage) UpdateAccount(account Account) error {
collection := s.Client.Database(s.DbName).Collection(s.Collections["users"]) collection := s.Client.Database(s.DbName).Collection(s.Collections["users"])
if _, err := collection.ReplaceOne(context.TODO(), bson.M{"_id": account.ID}, account); err != nil { if _, err := collection.ReplaceOne(context.TODO(), bson.M{"_id": account.ID}, account); err != nil {
fmt.Println(err) log.Error().Err(err).Msg("")
return err return err
} }
return nil return nil
} }
func (s MongoDBStorage) DeleteAccount(id string) error {
collection := s.Client.Database(s.DbName).Collection(s.Collections["users"])
update := bson.M{
"$set": bson.M{"deleted": true},
"$unset": bson.M{"authentication": ""},
}
if _, err := collection.UpdateOne(context.TODO(), bson.M{"_id": id}, update); err != nil {
log.Error().Err(err).Msg("")
return err
}
return nil
}
func (s MongoDBStorage) Migrate() error {
log.Error().Msg("no migration")
return nil
}

View File

@@ -1,50 +1,59 @@
/*
___ ___ ___ _ __ __ _ ___
/ __/ _ \ / _ \| '_ \ / _` |/ _ \
| (_| (_) | (_) | |_) | (_| | (_) |
\___\___/ \___/| .__/ \__, |\___/
| | __/ |
|_| |___/
*/
package storage package storage
import ( import (
"context"
"database/sql" "database/sql"
"encoding/json" "encoding/json"
"fmt" "fmt"
_ "github.com/lib/pq" "os"
"github.com/spf13/viper"
"strconv" "strconv"
"strings" "strings"
"ariga.io/atlas/sql/postgres"
"ariga.io/atlas/sql/schema"
"github.com/lib/pq"
_ "github.com/lib/pq"
"github.com/rs/zerolog/log"
"github.com/spf13/viper"
) )
type PostgresqlStorage struct { type PostgresqlStorage struct {
DbConnection *sql.DB DbConnection *sql.DB
Schema string
Tables map[string]string
} }
func NewPostgresqlStorage(cfg *viper.Viper) (PostgresqlStorage, error) { func NewPostgresqlStorage(cfg *viper.Viper) (PostgresqlStorage, error) {
var ( var (
host = cfg.GetString("storage.db.psql.host") host = cfg.GetString("storage.db.psql.host")
port = cfg.GetString("storage.db.psql.port") port = cfg.GetString("storage.db.psql.port")
user = cfg.GetString("storage.db.psql.user") user = cfg.GetString("storage.db.psql.user")
password = cfg.GetString("storage.db.psql.password") password = cfg.GetString("storage.db.psql.password")
dbname = cfg.GetString("storage.db.psql.dbname") dbname = cfg.GetString("storage.db.psql.dbname")
sslmode = cfg.GetString("storage.db.psql.sslmode")
pg_schema = cfg.GetString("storage.db.psql.schema")
pgtables_accounts = cfg.GetString("storage.db.psql.tables.accounts")
pgtables_accounts_auth_local = cfg.GetString("storage.db.psql.tables.accounts_auth_local")
) )
portInt, _ := strconv.Atoi(port) portInt, _ := strconv.Atoi(port)
psqlconn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", host, portInt, psqlconn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=%s", host, portInt, user, password, dbname, sslmode)
user, password, dbname)
db, err := sql.Open("postgres", psqlconn) db, err := sql.Open("postgres", psqlconn)
if err != nil { if err != nil {
fmt.Println("error", err) log.Error().Err(err).Msg("error opening postgresql connection")
return PostgresqlStorage{}, fmt.Errorf("connection to postgresql failed") return PostgresqlStorage{}, fmt.Errorf("connection to postgresql failed")
} }
err = db.Ping() err = db.Ping()
if err != nil { if err != nil {
log.Error().Err(err).Msg("")
return PostgresqlStorage{}, fmt.Errorf("connection to postgresql database failed") return PostgresqlStorage{}, fmt.Errorf("connection to postgresql database failed")
} }
return PostgresqlStorage{ return PostgresqlStorage{
DbConnection: db, DbConnection: db,
Schema: pg_schema,
Tables: map[string]string{
"accounts": fmt.Sprintf("%s.%s", pg_schema, pgtables_accounts),
"accounts_auth_local": fmt.Sprintf("%s.%s", pg_schema, pgtables_accounts_auth_local),
},
}, nil }, nil
} }
@@ -53,28 +62,26 @@ func (psql PostgresqlStorage) GetAccount(id string) (*Account, error) {
data, metadata, emailValidation, phoneValidation []byte data, metadata, emailValidation, phoneValidation []byte
) )
account := &Account{} account := &Account{}
stmtAccounts, err := psql.DbConnection.Prepare("" +
"SELECT id, namespace, data, " + var username, password, email, phonenumber *string
"metadata, username, password, email, email_validation, " +
"phone_number, phone_number_validation FROM accounts a JOIN " + req := fmt.Sprintf(`SELECT id, namespace, data, metadata, username, password, email, email_validation, phone_number, phone_number_validation
"account_auth auth ON id = account_id WHERE id = $1") FROM %s a
if err != nil { LEFT JOIN %s auth ON id = account_id WHERE id = $1`, psql.Tables["accounts"], psql.Tables["accounts_auth_local"])
return nil, fmt.Errorf("psql connection failed") err := psql.DbConnection.QueryRow(req, id).Scan(&account.ID,
}
defer stmtAccounts.Close()
err = stmtAccounts.QueryRow(id).Scan(&account.ID,
&account.Namespace, &account.Namespace,
&data, &data,
&metadata, &metadata,
&account.Authentication.Local.Username, &username,
&account.Authentication.Local.Password, &password,
&account.Authentication.Local.Email, &email,
&emailValidation, &emailValidation,
&account.Authentication.Local.PhoneNumber, &phonenumber,
&phoneValidation) &phoneValidation)
if err != nil { if err != nil {
return nil, fmt.Errorf("psql select account query failed") return nil, fmt.Errorf("psql select account query failed : %s", err)
} }
err = json.Unmarshal(data, &account.Data) err = json.Unmarshal(data, &account.Data)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -83,153 +90,92 @@ func (psql PostgresqlStorage) GetAccount(id string) (*Account, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
err = json.Unmarshal(emailValidation, &account.Authentication.Local.EmailValidation)
if err != nil { if password != nil || username != nil || email != nil || phonenumber != nil {
return nil, err account.Authentication.Local = &LocalAuth{
} Username: username,
err = json.Unmarshal(phoneValidation, &account.Authentication.Local.PhoneNumberValidation) Password: *password,
if err != nil { Email: email,
return nil, err PhoneNumber: phonenumber,
}
err = json.Unmarshal(emailValidation, &account.Authentication.Local.EmailValidation)
if err != nil {
return nil, err
}
err = json.Unmarshal(phoneValidation, &account.Authentication.Local.PhoneNumberValidation)
if err != nil {
return nil, err
}
} }
return account, nil return account, nil
} }
func (psql PostgresqlStorage) LocalAuthentication(namespace string, username string, email string, func (psql PostgresqlStorage) LocalAuthentication(namespace string, username *string, email *string, phone_number *string) (*Account, error) {
phone_number string) (*Account, error) {
account := &Account{} account := &Account{}
var ( var (
data, metadata, emailValidation, phoneValidation []byte data, metadata, emailValidation, phoneValidation []byte
) )
if username != "" { req := fmt.Sprintf(`SELECT id, namespace, data, metadata, username, password, email, email_validation, phone_number, phone_number_validation
usernameStmt, err := psql.DbConnection.Prepare("SELECT id, namespace, data, metadata, username, " + FROM %s INNER JOIN %s ON id = account_id
"password, email, email_validation, phone_number, phone_number_validation " + WHERE account_namespace = '%s'`, psql.Tables["accounts"], psql.Tables["accounts_auth_local"], namespace)
"FROM accounts INNER JOIN account_auth ON accounts.id = account_auth.account_id WHERE " +
"namespace = $1 AND username = $2;") if username != nil && *username != "" {
if err != nil { req += fmt.Sprintf(` AND username = '%s'`, *username)
return nil, err
}
err = usernameStmt.QueryRow(namespace, username).Scan(
&account.ID,
&account.Namespace, &data, &metadata,
&account.Authentication.Local.Username,
&account.Authentication.Local.Password,
&account.Authentication.Local.Email,
&emailValidation, &account.Authentication.Local.PhoneNumber,
&phoneValidation)
if err != nil {
return nil, err
}
err = json.Unmarshal(metadata, &account.Metadata)
if err != nil {
return nil, err
}
err = json.Unmarshal(data, &account.Data)
if err != nil {
return nil, err
}
err = json.Unmarshal(emailValidation, &account.Authentication.Local.EmailValidation)
if err != nil {
return nil, err
}
err = json.Unmarshal(phoneValidation, &account.Authentication.Local.PhoneNumberValidation)
if err != nil {
return nil, err
}
return account, nil
} else if email != "" {
account.Authentication.Local.Email = email
emailStmt, err := psql.DbConnection.Prepare("SELECT id, namespace, data, metadata, username, " +
"password, email_validation, phone_number, phone_number_validation " +
"FROM accounts INNER JOIN account_auth ON " +
"accounts.id = account_auth.account_id WHERE namespace = $1 AND email = $2;")
if err != nil {
return nil, err
}
err = emailStmt.QueryRow(namespace, email).Scan(
&account.ID,
&account.Namespace,
&data, &metadata,
&account.Authentication.Local.Username,
&account.Authentication.Local.Password,
&emailValidation,
&account.Authentication.Local.PhoneNumber,
&phoneValidation)
if err != nil {
return nil, err
}
err = json.Unmarshal(metadata, &account.Metadata)
if err != nil {
return nil, err
}
err = json.Unmarshal(data, &account.Data)
if err != nil {
return nil, err
}
err = json.Unmarshal(emailValidation, &account.Authentication.Local.EmailValidation)
if err != nil {
return nil, err
}
err = json.Unmarshal(phoneValidation, &account.Authentication.Local.PhoneNumberValidation)
if err != nil {
return nil, err
}
return account, nil
} else if phone_number != "" {
account.Authentication.Local.PhoneNumber = phone_number
phoneStmt, err := psql.DbConnection.Prepare("SELECT id, namespace, " +
"data, metadata, username, password, email, " +
"email_validation, phone_number_validation FROM accounts " +
"INNER JOIN account_auth ON accounts.id = account_auth.account_id WHERE " +
"namespace = $1 AND phone_number = $2;")
if err != nil {
return nil, err
}
err = phoneStmt.QueryRow(namespace, phone_number).Scan(&account.ID,
&account.Namespace,
&data,
&metadata,
&account.Authentication.Local.Username,
&account.Authentication.Local.Password,
&account.Authentication.Local.Email,
&emailValidation,
&phoneValidation)
if err != nil {
return nil, err
}
err = json.Unmarshal(metadata, &account.Metadata)
if err != nil {
return nil, err
}
err = json.Unmarshal(data, &account.Data)
if err != nil {
return nil, err
}
err = json.Unmarshal(emailValidation, &account.Authentication.Local.EmailValidation)
if err != nil {
return nil, err
}
err = json.Unmarshal(phoneValidation, &account.Authentication.Local.PhoneNumberValidation)
if err != nil {
return nil, err
}
return account, nil
} }
return nil, fmt.Errorf("localauthentication func error PSQL") if email != nil && *email != "" {
req += fmt.Sprintf(` AND email = '%s'`, *email)
}
if phone_number != nil && *phone_number != "" {
req += fmt.Sprintf(` AND phone_number = '%s'`, *phone_number)
}
req += ";"
account.Authentication.Local = &LocalAuth{}
err := psql.DbConnection.QueryRow(req).Scan(
&account.ID,
&account.Namespace, &data, &metadata,
&account.Authentication.Local.Username,
&account.Authentication.Local.Password,
&account.Authentication.Local.Email,
&emailValidation,
&account.Authentication.Local.PhoneNumber,
&phoneValidation)
if err != nil {
return nil, err
}
err = json.Unmarshal(metadata, &account.Metadata)
if err != nil {
log.Error().Err(err).Msg("error unmarshalling account metadata")
return nil, err
}
err = json.Unmarshal(data, &account.Data)
if err != nil {
log.Error().Err(err).Msg("error unmarshalling account data")
return nil, err
}
err = json.Unmarshal(emailValidation, &account.Authentication.Local.EmailValidation)
if err != nil {
log.Error().Err(err).Msg("error unmarshalling email validation")
return nil, err
}
err = json.Unmarshal(phoneValidation, &account.Authentication.Local.PhoneNumberValidation)
if err != nil {
log.Error().Err(err).Msg("error unmarshalling phone validation")
return nil, err
}
return account, nil
} }
func (psql PostgresqlStorage) GetAccounts(namespaces []string) ([]Account, error) { func (psql PostgresqlStorage) GetAccounts(namespaces []string) ([]Account, error) {
var accounts []Account var accounts []Account
namespacesStr := "'" + strings.Join(namespaces, "', '") + "'" namespacesStr := "'" + strings.Join(namespaces, "', '") + "'"
query := ` query := `
SELECT accounts.id, accounts.namespace, accounts.data, accounts.metadata, SELECT id, namespace, data, metadata, username, password, email, email_validation, phone_number, phone_number_validation
account_auth.username, account_auth.password, FROM %s LEFT JOIN %s ON id = account_id
account_auth.email, account_auth.email_validation, WHERE namespace IN (%s)
account_auth.phone_number, account_auth.phone_number_validation
FROM accounts
INNER JOIN account_auth ON accounts.id = account_auth.account_id
WHERE accounts.namespace IN (%s)
` `
query = fmt.Sprintf(query, namespacesStr) query = fmt.Sprintf(query, psql.Tables["accounts"], psql.Tables["accounts_auth_local"], namespacesStr)
rows, err := psql.DbConnection.Query(query) rows, err := psql.DbConnection.Query(query)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -239,19 +185,20 @@ func (psql PostgresqlStorage) GetAccounts(namespaces []string) ([]Account, error
var account Account var account Account
var dataBytes []byte var dataBytes []byte
var metadataBytes []byte var metadataBytes []byte
var emailValidationBytes []byte var emailValidation []byte
var phoneNumberValidationBytes []byte var phoneValidation []byte
var username, password, email, phonenumber *string
err := rows.Scan( err := rows.Scan(
&account.ID, &account.ID,
&account.Namespace, &account.Namespace,
&dataBytes, &dataBytes,
&metadataBytes, &metadataBytes,
&account.Authentication.Local.Username, &username,
&account.Authentication.Local.Password, &password,
&account.Authentication.Local.Email, &email,
&emailValidationBytes, &emailValidation,
&account.Authentication.Local.PhoneNumber, &phonenumber,
&phoneNumberValidationBytes, &phoneValidation,
) )
if err != nil { if err != nil {
return nil, err return nil, err
@@ -266,14 +213,22 @@ func (psql PostgresqlStorage) GetAccounts(namespaces []string) ([]Account, error
if err != nil { if err != nil {
return nil, err return nil, err
} }
err = json.Unmarshal(emailValidationBytes, &account.Authentication.Local.EmailValidation)
if err != nil {
return nil, err
}
err = json.Unmarshal(phoneNumberValidationBytes, &account.Authentication.Local.PhoneNumberValidation) if password != nil || username != nil || email != nil || phonenumber != nil {
if err != nil { account.Authentication.Local = &LocalAuth{
return nil, err Username: username,
Password: *password,
Email: email,
PhoneNumber: phonenumber,
}
err = json.Unmarshal(emailValidation, &account.Authentication.Local.EmailValidation)
if err != nil {
return nil, err
}
err = json.Unmarshal(phoneValidation, &account.Authentication.Local.PhoneNumberValidation)
if err != nil {
return nil, err
}
} }
accounts = append(accounts, account) accounts = append(accounts, account)
} }
@@ -282,18 +237,15 @@ func (psql PostgresqlStorage) GetAccounts(namespaces []string) ([]Account, error
func (psql PostgresqlStorage) GetAccountsByIds(accountids []string) ([]Account, error) { func (psql PostgresqlStorage) GetAccountsByIds(accountids []string) ([]Account, error) {
var accounts []Account var accounts []Account
accountIdsStr := "'" + strings.Join(accountids, "', '") + "'"
query := ` query := `
SELECT accounts.id, accounts.namespace, accounts.data, accounts.metadata, SELECT id, namespace, data, metadata, username, password, email, email_validation, phone_number, phone_number_validation
account_auth.username, account_auth.password, FROM %s
account_auth.email, account_auth.email_validation, LEFT JOIN %s ON id = account_id
account_auth.phone_number, account_auth.phone_number_validation WHERE id = ANY ($1)
FROM accounts
INNER JOIN account_auth ON accounts.id = account_auth.account_id
WHERE accounts.id IN (%s)
` `
query = fmt.Sprintf(query, accountIdsStr) query = fmt.Sprintf(query, psql.Tables["accounts"], psql.Tables["accounts_auth_local"]) //, accountIdsStr)
rows, err := psql.DbConnection.Query(query) rows, err := psql.DbConnection.Query(query, pq.Array(accountids))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -302,19 +254,21 @@ func (psql PostgresqlStorage) GetAccountsByIds(accountids []string) ([]Account,
var account Account var account Account
var dataBytes []byte var dataBytes []byte
var metadataBytes []byte var metadataBytes []byte
var emailValidationBytes []byte var emailValidation []byte
var phoneNumberValidationBytes []byte var phoneValidation []byte
var username, password, email, phonenumber *string
err := rows.Scan( err := rows.Scan(
&account.ID, &account.ID,
&account.Namespace, &account.Namespace,
&dataBytes, &dataBytes,
&metadataBytes, &metadataBytes,
&account.Authentication.Local.Username, &username,
&account.Authentication.Local.Password, &password,
&account.Authentication.Local.Email, &email,
&emailValidationBytes, &emailValidation,
&account.Authentication.Local.PhoneNumber, &phonenumber,
&phoneNumberValidationBytes) &phoneValidation,
)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -329,14 +283,21 @@ func (psql PostgresqlStorage) GetAccountsByIds(accountids []string) ([]Account,
return nil, err return nil, err
} }
err = json.Unmarshal(emailValidationBytes, &account.Authentication.Local.EmailValidation) if password != nil || username != nil || email != nil || phonenumber != nil {
if err != nil { account.Authentication.Local = &LocalAuth{
return nil, err Username: username,
} Password: *password,
Email: email,
err = json.Unmarshal(phoneNumberValidationBytes, &account.Authentication.Local.PhoneNumberValidation) PhoneNumber: phonenumber,
if err != nil { }
return nil, err err = json.Unmarshal(emailValidation, &account.Authentication.Local.EmailValidation)
if err != nil {
return nil, err
}
err = json.Unmarshal(phoneValidation, &account.Authentication.Local.PhoneNumberValidation)
if err != nil {
return nil, err
}
} }
accounts = append(accounts, account) accounts = append(accounts, account)
} }
@@ -344,11 +305,6 @@ func (psql PostgresqlStorage) GetAccountsByIds(accountids []string) ([]Account,
} }
func (psql PostgresqlStorage) CreateAccount(account Account) error { func (psql PostgresqlStorage) CreateAccount(account Account) error {
insertAccountStmt, err := psql.DbConnection.Prepare("INSERT INTO accounts (id, namespace, data, metadata)" +
" VALUES ($1, $2, $3, $4)")
if err != nil {
return err
}
dataAccountJson, err := json.Marshal(account.Data) dataAccountJson, err := json.Marshal(account.Data)
if err != nil { if err != nil {
return err return err
@@ -357,43 +313,67 @@ func (psql PostgresqlStorage) CreateAccount(account Account) error {
if err != nil { if err != nil {
return err return err
} }
tx, err := psql.DbConnection.BeginTx(context.Background(), nil)
if err != nil {
return err
}
defer tx.Rollback()
insertAccountStmt, err := tx.Prepare(fmt.Sprintf("INSERT INTO %s (id, namespace, data, metadata) VALUES ($1, $2, $3, $4)", psql.Tables["accounts"]))
if err != nil {
return err
}
defer insertAccountStmt.Close()
_, err = insertAccountStmt.Exec(account.ID, account.Namespace, dataAccountJson, metadataAccountJson) _, err = insertAccountStmt.Exec(account.ID, account.Namespace, dataAccountJson, metadataAccountJson)
if err != nil { if err != nil {
return err return err
} }
insertAccountAuthStmt, err := psql.DbConnection.Prepare("INSERT INTO account_auth (account_id, username," +
" password, email, email_validation,phone_number,phone_number_validation) " + if account.Authentication.Local != nil {
"values($1, $2, $3, $4, $5, $6, $7)")
if err != nil { emailValidationJson, err := json.Marshal(account.Authentication.Local.EmailValidation)
return err if err != nil {
return err
}
phoneValidationJson, err := json.Marshal(account.Authentication.Local.PhoneNumberValidation)
if err != nil {
return err
}
insertAccountAuthStmt, err := tx.Prepare(fmt.Sprintf(`INSERT INTO %s (account_id, account_namespace, username, password, email, email_validation, phone_number, phone_number_validation)
VALUES($1, $2, $3, $4, $5, $6, $7, $8);`, psql.Tables["accounts_auth_local"]))
if err != nil {
return err
}
defer insertAccountAuthStmt.Close()
_, err = insertAccountAuthStmt.Exec(account.ID,
account.Namespace,
account.Authentication.Local.Username,
account.Authentication.Local.Password,
account.Authentication.Local.Email,
emailValidationJson,
account.Authentication.Local.PhoneNumber,
phoneValidationJson)
if err != nil {
return err
}
} }
emailValidationJson, err := json.Marshal(account.Authentication.Local.EmailValidation)
if err != nil { if err := tx.Commit(); err != nil {
return err
}
phoneValidationJson, err := json.Marshal(account.Authentication.Local.PhoneNumberValidation)
if err != nil {
return err
}
_, err = insertAccountAuthStmt.Exec(account.ID,
account.Authentication.Local.Username,
account.Authentication.Local.Password,
account.Authentication.Local.Email,
emailValidationJson,
account.Authentication.Local.PhoneNumber,
phoneValidationJson)
if err != nil {
return err return err
} }
return nil return nil
} }
func (psql PostgresqlStorage) UpdateAccount(account Account) error { func (psql PostgresqlStorage) UpdateAccount(account Account) error {
updateAccountStmt, err := psql.DbConnection.Prepare("update accounts set namespace=$1, data=$2, " +
" metadata=$3 where id= $4") tx, err := psql.DbConnection.BeginTx(context.Background(), nil)
if err != nil { if err != nil {
return err return err
} }
defer tx.Rollback()
dataAccountJson, err := json.Marshal(account.Data) dataAccountJson, err := json.Marshal(account.Data)
if err != nil { if err != nil {
return err return err
@@ -402,33 +382,105 @@ func (psql PostgresqlStorage) UpdateAccount(account Account) error {
if err != nil { if err != nil {
return err return err
} }
_, err = updateAccountStmt.Exec(account.Namespace, dataAccountJson, metadataAccountJson, account.ID)
req := fmt.Sprintf("UPDATE %s SET namespace=$1, data=$2, metadata=$3 where id= $4", psql.Tables["accounts"])
_, err = tx.Exec(req, account.Namespace, dataAccountJson, metadataAccountJson, account.ID)
if err != nil { if err != nil {
return err return err
} }
updateAccountAuthStmt, err := psql.DbConnection.Prepare("update account_auth set username = $1," +
" password = $2," + if account.Authentication.Local != nil {
" email = $3, email_validation = $4 ," + emailValidationJson, err := json.Marshal(account.Authentication.Local.EmailValidation)
"phone_number = $5,phone_number_validation = $6 where account_id = $7") if err != nil {
if err != nil { return err
return err }
} phoneValidationJson, err := json.Marshal(account.Authentication.Local.PhoneNumberValidation)
emailValidationJson, err := json.Marshal(account.Authentication.Local.EmailValidation) if err != nil {
if err != nil { return err
return err }
}
phoneValidationJson, err := json.Marshal(account.Authentication.Local.PhoneNumberValidation) req = fmt.Sprintf(`UPDATE %s
if err != nil { SET username = $1, password = $2, email = $3, email_validation = $4,
return err phone_number = $5,phone_number_validation = $6 where account_id = $7`, psql.Tables["accounts_auth_local"])
} _, err = tx.Exec(req, account.Authentication.Local.Username,
_, err = updateAccountAuthStmt.Exec(account.Authentication.Local.Username, account.Authentication.Local.Password,
account.Authentication.Local.Password, account.Authentication.Local.Email,
account.Authentication.Local.Email, emailValidationJson,
emailValidationJson, account.Authentication.Local.PhoneNumber,
account.Authentication.Local.PhoneNumber, phoneValidationJson, account.ID)
phoneValidationJson, account.ID) if err != nil {
if err != nil { return err
}
}
if err := tx.Commit(); err != nil {
return err return err
} }
return nil
}
func (psql PostgresqlStorage) DeleteAccount(id string) error {
tx, err := psql.DbConnection.BeginTx(context.Background(), nil)
if err != nil {
return err
}
defer tx.Rollback()
// Delete authentication info
req := fmt.Sprintf(`DELETE FROM %s WHERE account_id = $1`, psql.Tables["accounts_auth_local"])
_, err = tx.Exec(req, id)
if err != nil {
return err
}
// Mark account as deleted
req = fmt.Sprintf(`UPDATE %s SET deleted = true WHERE id = $1`, psql.Tables["accounts"])
_, err = tx.Exec(req, id)
if err != nil {
return err
}
if err := tx.Commit(); err != nil {
return err
}
return nil
}
func (psql PostgresqlStorage) Migrate() error {
ctx := context.Background()
driver, err := postgres.Open(psql.DbConnection)
if err != nil {
return err
}
existing, err := driver.InspectRealm(ctx, &schema.InspectRealmOption{Schemas: []string{psql.Schema}})
if err != nil {
return err
}
var desired schema.Realm
hcl, err := os.ReadFile("postgresql/schema.hcl")
if err != nil {
return err
}
err = postgres.EvalHCLBytes(hcl, &desired, nil)
if err != nil {
return err
}
diff, err := driver.RealmDiff(existing, &desired)
if err != nil {
return err
}
err = driver.ApplyChanges(ctx, diff)
if err != nil {
return err
}
return nil return nil
} }

View File

@@ -0,0 +1,86 @@
table "accounts" {
schema = schema.mobilityaccounts
column "id" {
null = false
type = uuid
}
column "namespace" {
null = true
type = text
}
column "data" {
null = true
type = jsonb
}
column "metadata" {
null = true
type = jsonb
}
column "deleted" {
null = true
type = boolean
default = false
}
primary_key {
columns = [column.id]
}
}
table "accounts_auth_local" {
schema = schema.mobilityaccounts
column "account_id" {
null = true
type = uuid
}
column "account_namespace" {
null = true
type = text
}
column "username" {
null = true
type = text
}
column "password" {
null = true
type = text
}
column "email" {
null = true
type = text
}
column "email_validation" {
null = true
type = jsonb
}
column "phone_number" {
null = true
type = text
}
column "phone_number_validation" {
null = true
type = jsonb
}
foreign_key "accounts_auth_local_account_id_fkey" {
columns = [column.account_id]
ref_columns = [table.accounts.column.id]
on_update = NO_ACTION
on_delete = NO_ACTION
}
index "accounts_auth_local_account_id_key" {
unique = true
columns = [column.account_id]
}
index "accounts_auth_local_idx_email" {
unique = true
columns = [column.account_namespace, column.email]
}
index "accounts_auth_local_idx_phone_number" {
unique = true
columns = [column.account_namespace, column.phone_number]
}
index "accounts_auth_local_idx_username" {
unique = true
columns = [column.account_namespace, column.username]
}
}
schema "mobilityaccounts" {
}

View File

@@ -1,369 +0,0 @@
package storage
import (
"crypto/rand"
"encoding/hex"
"encoding/json"
"fmt"
"github.com/spf13/viper"
"reflect"
"testing"
)
// Tests must be run in order
// Table creation:
/* #####################################################################################################################
CREATE TABLE accounts (
id TEXT PRIMARY KEY,
namespace TEXT,
data JSONB,
metadata JSONB
);
CREATE TABLE account_auth (
account_id TEXT PRIMARY KEY,
username TEXT,
password TEXT,
email TEXT,
email_validation JSONB,
phone_number TEXT,
phone_number_validation JSONB,
FOREIGN KEY (account_id) REFERENCES accounts(id)
);
#######################################################################################################################
*/
/* Inserting an Account: (Password = test)
#######################################################################################################################
INSERT INTO accounts (id, namespace, data, metadata)
VALUES ('2faa137b-27be-476f-b98c-8b7eed6f1f3a', 'parcoursmob', '{"email": "salimbouaram12@gmail.com", "gender": "9",
"groups": ["483280d0-db2d-4f06-b361-02e4be5012d2", "483280d0-db2d-4f06-b361-02e4be5012d2:admin"], "last_name": "salim",
"first_name": "salim", "display_name": "salim salim", "phone_number": ""}', '{"created": "2023-04-24T09:29:18.262+00:00"}');
#######################################################################################################################
INSERT INTO account_auth (account_id, username, password, email, email_validation, phone_number, phone_number_validation)
VALUES ('2faa137b-27be-476f-b98c-8b7eed6f1f3a', 'salim-amine.bou-aram@coopgo.fr',
'$2a$10$j9LwkGYT6HhLpWxUvpEniOJ3nBKEhwAn52G.t4QYMgje4HnJuWqHK', 'salim-amine.bou-aram@coopgo.fr',
'{"validated": false, "validation_code": ""}', '0749331953', '{"validated": false, "validation_code": ""}');
#######################################################################################################################
*/
var cfg *viper.Viper
func init() {
cfg = viper.New()
cfg.Set("storage.db.psql.host", "localhost")
cfg.Set("storage.db.psql.port", "5432")
cfg.Set("storage.db.psql.user", "postgres")
cfg.Set("storage.db.psql.password", "postgres")
cfg.Set("storage.db.psql.dbname", "mobilityaccounts")
}
func TestNewPostgresqlStorage(t *testing.T) {
storage, err := NewPostgresqlStorage(cfg)
storage.DbConnection.Exec("Delete from account_auth ;")
storage.DbConnection.Exec("Delete from accounts ;")
if err != nil {
t.Errorf("error creating new PostgreSQL storage: %v", err)
}
defer storage.DbConnection.Close()
}
func generateUUIDv4() string {
uuid := make([]byte, 16)
_, err := rand.Read(uuid)
if err != nil {
panic(err)
}
uuid[6] = (uuid[6] & 0x0f) | 0x40
uuid[8] = (uuid[8] & 0xbf) | 0x80
return hex.EncodeToString(uuid[:4]) + "-" + hex.EncodeToString(uuid[4:6]) + "-" +
hex.EncodeToString(uuid[6:8]) + "-" + hex.EncodeToString(uuid[8:10]) + "-" +
hex.EncodeToString(uuid[10:])
}
func TestGetAccount(t *testing.T) {
// Open a database connection
db, err := NewPostgresqlStorage(cfg)
Id := generateUUIDv4()
if err != nil {
t.Errorf("failed to create new psql connection")
}
// Insert data into accounts table
accountData := map[string]any{
"key1": "value1",
"key2": "value2",
}
accountMetadata := map[string]any{
"key1": "value1",
"key2": "value2",
}
account := Account{
ID: Id,
Namespace: "test_namespace",
Data: accountData,
Metadata: accountMetadata,
}
dataJSON, err := json.Marshal(map[string]any{
"key1": "value1",
"key2": "value2",
})
if err != nil {
t.Errorf("error account data and metdata")
}
_, err = db.DbConnection.Exec("INSERT INTO accounts (id, namespace, data, metadata) "+
"VALUES ($1, $2, $3, $4)", account.ID, account.Namespace, dataJSON, dataJSON)
if err != nil {
t.Errorf("error in inserting a new account")
}
// Insert data into account_auth table
emailValidation := Validation{
Validated: true,
ValidationCode: "code",
}
localAuth := LocalAuth{
Username: "testuser",
Password: "testpassword",
Email: "test@test.com",
EmailValidation: emailValidation,
PhoneNumber: "1234567890",
PhoneNumberValidation: emailValidation,
}
localAuthJSON, err := json.Marshal(emailValidation)
if err != nil {
t.Errorf("error account_auth localAuth")
}
_, err = db.DbConnection.Exec("INSERT INTO account_auth (account_id, username, password, "+
"email, email_validation, "+
"phone_number,phone_number_validation) VALUES ($1, $2, $3, $4, $5, $6, $7)", account.ID,
localAuth.Username, localAuth.Password, localAuth.Email, localAuthJSON, localAuth.PhoneNumber, localAuthJSON)
if err != nil {
fmt.Println(err)
t.Errorf("error in iserting a new account in account_auth")
}
account_, err := db.GetAccount(Id)
if err != nil {
t.Errorf("failed")
fmt.Println(err)
}
expectedAccount := &Account{
ID: Id,
Namespace: "test_namespace",
Data: accountData,
Metadata: accountMetadata,
Authentication: AccountAuth{
Local: localAuth,
},
}
if reflect.DeepEqual(account_, expectedAccount) {
fmt.Println("PASS")
} else {
t.Errorf("The received account is not the same as expected")
}
}
func TestPostgresqlStorage_CreateAccount(t *testing.T) {
db, err := NewPostgresqlStorage(cfg)
Id := generateUUIDv4()
if err != nil {
t.Errorf("failed to create new psql connection")
}
emailValidation := Validation{
Validated: true,
ValidationCode: "code",
}
localAuth := LocalAuth{
Username: "salim",
Password: "testpassword",
Email: "test@test.com",
EmailValidation: emailValidation,
PhoneNumber: "1234567890",
PhoneNumberValidation: emailValidation,
}
accountData := map[string]any{
"key1": "value1",
"key2": "value2",
}
accountMetadata := map[string]any{
"key1": "value1",
"key2": "value2",
}
account := Account{
ID: Id,
Namespace: "namespace",
Authentication: AccountAuth{
Local: localAuth,
},
Data: accountData,
Metadata: accountMetadata,
}
err = db.CreateAccount(account)
if err != nil {
fmt.Println(err)
t.Errorf("Failed to create account")
}
}
func TestPostgresqlStorage_UpdateAccount(t *testing.T) {
db, err := NewPostgresqlStorage(cfg)
Id := generateUUIDv4()
if err != nil {
t.Errorf("failed to create new psql connection")
}
emailValidation := Validation{
Validated: true,
ValidationCode: "code",
}
localAuth := LocalAuth{
Username: "salim",
Password: "testpassword",
Email: "test@test.com",
EmailValidation: emailValidation,
PhoneNumber: "1234567890",
PhoneNumberValidation: emailValidation,
}
accountData := map[string]any{
"key1": "value1",
"key2": "value2",
}
accountMetadata := map[string]any{
"key1": "value1",
"key2": "value2",
}
account := Account{
ID: Id,
Namespace: "test_namespace",
Authentication: AccountAuth{
Local: localAuth,
},
Data: accountData,
Metadata: accountMetadata,
}
err = db.CreateAccount(account)
if err != nil {
fmt.Println(err)
t.Errorf("Failed to create account")
}
account2 := Account{
ID: Id,
Namespace: "salim",
Authentication: AccountAuth{
Local: LocalAuth{
Username: "salim",
Password: "salim",
Email: "salim@test.com",
EmailValidation: Validation{
Validated: false,
ValidationCode: "123",
},
PhoneNumber: "12345",
PhoneNumberValidation: Validation{
Validated: true,
ValidationCode: "1233",
},
},
},
Data: map[string]any{
"key1": "salim1",
"key2": "salim2",
},
Metadata: map[string]any{
"key1": "salim1",
"key2": "salim2",
},
}
err = db.UpdateAccount(account2)
if err != nil {
fmt.Println(err)
t.Errorf("failed")
}
}
func TestPostgresqlStorage_LocalAuthentication(t *testing.T) {
db, err := NewPostgresqlStorage(cfg)
if err != nil {
t.Errorf("failed to create new psql connection")
}
accountByUsername, err := db.LocalAuthentication("test_namespace", "testuser",
"", "")
if err != nil {
t.Errorf("Failed LocalAuthentication based on username and namespace")
}
fmt.Println(accountByUsername)
accountByEmail, err := db.LocalAuthentication("test_namespace", "",
"test@test.com", "")
if err != nil {
t.Errorf("Failed LocalAuthentication based on username and namespace")
}
fmt.Println(accountByEmail)
accountByPhone, err := db.LocalAuthentication("test_namespace", "",
"", "1234567890")
if err != nil {
t.Errorf("Failed LocalAuthentication based on username and namespace")
}
fmt.Println(accountByPhone)
accountByAll, err := db.LocalAuthentication("test_namespace", "testuser",
"test@test.com", "1234567890")
if err != nil {
t.Errorf("Failed LocalAuthentication based on username and namespace")
}
fmt.Println(accountByAll)
}
func TestPostgresqlStorage_GetAccounts(t *testing.T) {
db, err := NewPostgresqlStorage(cfg)
if err != nil {
t.Errorf("failed to create new psql connection")
}
accounts, err := db.GetAccounts([]string{"test_namespace", "salim", "namespace"})
if err != nil {
t.Errorf("Failed")
}
for _, account := range accounts {
fmt.Println(account)
}
}
func TestPostgresqlStorage_GetAccountsByIds(t *testing.T) {
db, err := NewPostgresqlStorage(cfg)
if err != nil {
t.Errorf("failed to create new psql connection")
}
account := Account{
ID: "772315f1-8113-486a-90c7-9073410065bd",
Namespace: "oo",
Authentication: AccountAuth{
Local: LocalAuth{
Username: "username",
Password: "password",
Email: "salim@test.com",
EmailValidation: Validation{
Validated: true,
ValidationCode: "123",
},
PhoneNumber: "12345",
PhoneNumberValidation: Validation{
Validated: true,
ValidationCode: "1233",
},
},
},
Data: map[string]any{
"key1": "salim1",
"key2": "salim2",
},
Metadata: map[string]any{
"key1": "salim1",
"key2": "salim2",
},
}
err = db.CreateAccount(account)
if err != nil {
t.Errorf("Failed to create account")
}
accounts, err := db.GetAccountsByIds([]string{"772315f1-8113-486a-90c7-9073410065bd"})
if err != nil {
t.Errorf("Failed to get account by ID")
}
for _, acc := range accounts {
fmt.Println(acc)
}
}

View File

@@ -30,11 +30,16 @@ func NewStorage(cfg *viper.Viper) (Storage, error) {
type DBStorage interface { type DBStorage interface {
GetAccount(id string) (*Account, error) GetAccount(id string) (*Account, error)
LocalAuthentication(namespace string, username string, email string, phone_number string) (*Account, error) LocalAuthentication(namespace string, username *string, email *string, phone_number *string) (*Account, error)
GetAccounts(namespaces []string) ([]Account, error) GetAccounts(namespaces []string) ([]Account, error)
GetAccountsByIds(accountids []string) ([]Account, error) GetAccountsByIds(accountids []string) ([]Account, error)
CreateAccount(account Account) error CreateAccount(account Account) error
//TODO : remove UpdateAccount, implement UpdateAccountData and UpdateAccountLocalAuthentication
UpdateAccount(account Account) error UpdateAccount(account Account) error
DeleteAccount(id string) error
Migrate() error
} }
func NewDBStorage(cfg *viper.Viper) (DBStorage, error) { func NewDBStorage(cfg *viper.Viper) (DBStorage, error) {
@@ -66,3 +71,7 @@ func NewKVStore(cfg *viper.Viper) (KVStore, error) {
kv, err := NewEtcdKVStore(cfg) kv, err := NewEtcdKVStore(cfg)
return kv, err return kv, err
} }
func Ptr[T any](v T) *T {
return &v
}