Compare commits

...

107 Commits

Author SHA1 Message Date
TIP Automation User
c3a1d84bcd Chg: update image tag in helm values to v2.7.0-RC4 2022-10-03 11:14:18 +00:00
Dmitry Dunaev
a34d8eb625 Merge pull request #84 from Telecominfraproject/main
[WIFI-10581] Add: postgresql-client in Dockerfile
2022-10-03 14:04:49 +03:00
Dmitry Dunaev
6ae42fe206 [WIFI-10581] Fix: Helm image to main
Signed-off-by: Dmitry Dunaev <dmitry@opsfleet.com>
2022-10-03 12:11:37 +03:00
Dmitry Dunaev
4539bfb53b Merge pull request #83 from Telecominfraproject/fix/wifi-10581--postgres-client
[WIFI-10581] Add: postgresql-client in Dockerfile
2022-10-03 11:22:33 +03:00
Dmitry Dunaev
dc57a94416 [WIFI-10581] Add: postgresql-client in Dockerfile
Signed-off-by: Dmitry Dunaev <dmitry@opsfleet.com>
2022-10-03 11:22:14 +03:00
Stephane Bourque
68e2d20264 Merge pull request #82 from Telecominfraproject/main
https://telecominfraproject.atlassian.net/browse/WIFI-10942
2022-10-02 23:02:28 -07:00
stephb9959
6025b7a74e https://telecominfraproject.atlassian.net/browse/WIFI-10942
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-10-02 23:00:31 -07:00
stephb9959
3fcf6114c0 https://telecominfraproject.atlassian.net/browse/WIFI-10942
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-10-02 22:36:33 -07:00
stephb9959
de0c1423af Merge remote-tracking branch 'origin/main' 2022-10-02 22:21:37 -07:00
stephb9959
f4984247d2 https://telecominfraproject.atlassian.net/browse/WIFI-10942
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-10-02 22:21:30 -07:00
stephb9959
e0b80a2640 Merge remote-tracking branch 'origin/main' 2022-10-02 22:09:02 -07:00
stephb9959
f2c36882be https://telecominfraproject.atlassian.net/browse/WIFI-10942
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-10-02 22:08:54 -07:00
stephb9959
3a1e4d66b4 https://telecominfraproject.atlassian.net/browse/WIFI-10942 2022-10-02 21:51:32 -07:00
stephb9959
6ea62c12c5 https://telecominfraproject.atlassian.net/browse/WIFI-10942 2022-10-02 14:35:59 -07:00
stephb9959
517b46d275 Merge remote-tracking branch 'origin/main' 2022-10-02 14:22:10 -07:00
Stephane Bourque
2503cb842e https://telecominfraproject.atlassian.net/browse/WIFI-10942 2022-10-02 14:22:01 -07:00
Stephane Bourque
3310b7c565 Merge pull request #81 from Telecominfraproject/main
https://telecominfraproject.atlassian.net/browse/WIFI-10942
2022-10-02 11:03:57 -07:00
Stephane Bourque
2878e2aa25 Merge branch 'release/v2.7.0' into main 2022-10-02 11:03:35 -07:00
Stephane Bourque
3b7e6da952 Merge pull request #80 from Telecominfraproject/WIFI-10942
https://telecominfraproject.atlassian.net/browse/WIFI-10942
2022-10-02 11:00:03 -07:00
Stephane Bourque
bbf1c61ea8 Merge branch 'main' into WIFI-10942 2022-10-02 10:59:56 -07:00
Stephane Bourque
e76fedb207 https://telecominfraproject.atlassian.net/browse/WIFI-10942 2022-10-02 10:58:25 -07:00
Stephane Bourque
4ab026b88c Merge pull request #68 from Telecominfraproject/WIFI-10581-switch-images-to-debian-slim
[WIFI-10581] Switch microservice Docker images from Alpine to Debian-slim
2022-10-02 10:52:40 -07:00
TIP Automation User
06267690fc Chg: update image tag in helm values to v2.7.0-RC3 2022-09-30 16:31:27 +00:00
Stephane Bourque
db751e31a3 Merge pull request #79 from Telecominfraproject/WIFI-10942
https://telecominfraproject.atlassian.net/browse/WIFI-10942
2022-09-30 08:52:49 -07:00
stephb9959
49b8664dc0 https://telecominfraproject.atlassian.net/browse/WIFI-10942 2022-09-30 08:44:56 -07:00
TIP Automation User
26e54f8433 Chg: update image tag in helm values to v2.7.0-RC2 2022-09-29 23:27:33 +00:00
jaspreetsachdev
a4ebfdc2e9 Merge pull request #78 from Telecominfraproject/main
Fixes for WIFI-10245 and others
2022-09-29 19:17:40 -04:00
Dmitry Dunaev
7cf7d011bd Merge pull request #77 from Telecominfraproject/feature/wifi-10932--docker-support-http
[WIFI-10932] Add: restapi disable property in docker entrypoint
2022-09-28 17:39:40 +03:00
Dmitry Dunaev
bce53ff61c [WIFI-10932] Add: restapi disable property in docker entrypoint
Signed-off-by: Dmitry Dunaev <dmitry@opsfleet.com>
2022-09-28 17:39:20 +03:00
Dmitry Dunaev
428a2edcdf Merge pull request #76 from Telecominfraproject/feature/wifi-10582--helm-global-cert-secret
[WIFI-10582] Add: functionality to use external existing certificates secret
2022-09-28 17:06:12 +03:00
Dmitry Dunaev
ac897e8a8b [WIFI-10582] Add: functionality to use external existing certificates secret
Signed-off-by: Dmitry Dunaev <dmitry@opsfleet.com>
2022-09-28 13:34:26 +03:00
Stephane Bourque
939869948f Merge pull request #75 from Telecominfraproject/WIFI-10245
https://telecominfraproject.atlassian.net/browse/WIFI-10245
2022-09-26 13:32:13 -07:00
stephb9959
85a4661914 https://telecominfraproject.atlassian.net/browse/WIFI-10245
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-09-26 13:31:31 -07:00
Stephane Bourque
adce4a8238 Merge pull request #74 from Telecominfraproject/WIFI-10245
https://telecominfraproject.atlassian.net/browse/WIFI-10245
2022-09-22 21:57:11 -07:00
stephb9959
180d270f9b https://telecominfraproject.atlassian.net/browse/WIFI-10245
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-09-22 21:56:42 -07:00
Stephane Bourque
6a44c0a220 Merge pull request #73 from Telecominfraproject/WIFI-10245
https://telecominfraproject.atlassian.net/browse/WIFI-10245
2022-09-22 20:34:38 -07:00
stephb9959
87c8084c89 https://telecominfraproject.atlassian.net/browse/WIFI-10245
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-09-22 20:34:15 -07:00
Stephane Bourque
d65d1418a2 Merge pull request #72 from Telecominfraproject/WIFI-10245
https://telecominfraproject.atlassian.net/browse/WIFI-10245
2022-09-22 13:53:22 -07:00
stephb9959
5bb1a1b68a https://telecominfraproject.atlassian.net/browse/WIFI-10245
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-09-22 13:52:48 -07:00
Stephane Bourque
003662508e Merge pull request #71 from Telecominfraproject/WIFI-10245
https://telecominfraproject.atlassian.net/browse/WIFI-10245
2022-09-21 19:47:49 -07:00
stephb9959
bdf577ecbe https://telecominfraproject.atlassian.net/browse/WIFI-10245
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-09-21 19:47:20 -07:00
TIP Automation User
4b1fbf055f Chg: update image tag in helm values to v2.7.0-RC1 2022-09-16 19:54:50 +00:00
Dmitry Dunaev
8b5c9dd5e9 Merge pull request #70 from Telecominfraproject/feature/wifi-10069--add-wait-postgres-initcontainer
[WIFI-10069] Add: helm - wait-postgres init container
2022-09-02 14:44:45 +03:00
Dmitry Dunaev
02a315ab0d [WIFI-10069] Add: helm - wait-postgres init container
Signed-off-by: Dmitry Dunaev <dmitry@opsfleet.com>
2022-09-02 14:44:27 +03:00
Stephane Bourque
1e4d9ea4e8 Merge pull request #69 from Telecominfraproject/WIFI-10245
https://telecominfraproject.atlassian.net/browse/WIFI-10245
2022-08-22 08:52:22 -07:00
stephb9959
0b1d7e39eb https://telecominfraproject.atlassian.net/browse/WIFI-10245
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-22 08:51:43 -07:00
Johann Hoffmann
4b184bae24 Fix self-signed cert file extension for Debian
Signed-off-by: Johann Hoffmann <johann.hoffmann@mailbox.org>
2022-08-19 17:20:36 +02:00
Johann Hoffmann
c483c99802 Create necessary library links in Docker image
Signed-off-by: Johann Hoffmann <johann.hoffmann@mailbox.org>
2022-08-19 16:16:05 +02:00
Johann Hoffmann
7ea1ccc9d9 Switch to Debian-slim base images
Signed-off-by: Johann Hoffmann <johann.hoffmann@mailbox.org>
2022-08-18 18:14:38 +02:00
Dmitry Dunaev
af190e9967 Merge pull request #67 from Telecominfraproject/fix/wifi-10413--cve-fix
[WIFI-10413] Fix: vulnerable base Docker image version
2022-08-15 13:31:01 +03:00
Dmitry Dunaev
80d3dfb89f [WIFI-10413] Fix: vulnerable base Docker image version
Signed-off-by: Dmitry Dunaev <dmitry@opsfleet.com>
2022-08-15 11:15:49 +03:00
Stephane Bourque
62c6b119c9 Merge pull request #66 from Telecominfraproject/WIFI-10245
https://telecominfraproject.atlassian.net/browse/WIFI-10245
2022-08-10 16:32:18 -07:00
stephb9959
4ea8aa9958 https://telecominfraproject.atlassian.net/browse/WIFI-10245
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-10 16:31:50 -07:00
Stephane Bourque
6a30353b3a Merge pull request #65 from Telecominfraproject/feature/wifi-10388--versioning
[WIFI-10388] Chg: use Docker build arg to define dependency version
2022-08-08 12:12:25 -07:00
Dmitry Dunaev
b355b41d4f [WIFI-10388] Chg: use Docker build arg to define dependency version
Signed-off-by: Dmitry Dunaev <dmitry@opsfleet.com>
2022-08-08 17:38:58 +03:00
Stephane Bourque
19b2afb469 Merge pull request #64 from Telecominfraproject/WIFI-10388
https://telecominfraproject.atlassian.net/browse/WIFI-10388
2022-08-07 22:27:31 -07:00
stephb9959
7d65da3abc https://telecominfraproject.atlassian.net/browse/WIFI-10388
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-07 22:27:08 -07:00
Stephane Bourque
c25059e2aa Merge pull request #62 from Telecominfraproject/WIFI-10388
https://telecominfraproject.atlassian.net/browse/WIFI-10388
2022-08-01 09:44:42 -07:00
stephb9959
122a73f35e https://telecominfraproject.atlassian.net/browse/WIFI-10388
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-01 09:43:48 -07:00
Stephane Bourque
a454b56c7a Merge pull request #61 from Telecominfraproject/WIFI-10388
https://telecominfraproject.atlassian.net/browse/WIFI-10388
2022-08-01 09:16:54 -07:00
stephb9959
ae82160c7f https://telecominfraproject.atlassian.net/browse/WIFI-10388
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-08-01 09:13:18 -07:00
stephb9959
4d73bbd605 https://telecominfraproject.atlassian.net/browse/WIFI-10345
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-26 14:51:32 -07:00
stephb9959
13bec235a1 https://telecominfraproject.atlassian.net/browse/WIFI-10345
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-25 23:25:03 -07:00
stephb9959
e6c196cd67 https://telecominfraproject.atlassian.net/browse/WIFI-10345
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-25 11:13:48 -07:00
stephb9959
6d9a1cac09 https://telecominfraproject.atlassian.net/browse/WIFI-10345
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-24 21:42:23 -07:00
stephb9959
55a43ed40d https://telecominfraproject.atlassian.net/browse/WIFI-10345
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-24 20:04:14 -07:00
stephb9959
3a230e4250 https://telecominfraproject.atlassian.net/browse/WIFI-10345
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-24 19:36:40 -07:00
stephb9959
0a6ee4ea47 https://telecominfraproject.atlassian.net/browse/WIFI-10345
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-24 12:28:40 -07:00
Stephane Bourque
a430ad7e71 Merge pull request #59 from Telecominfraproject/WIFI-100079
Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10079
2022-07-08 21:16:35 -07:00
stephb9959
d1c13ad2dd Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10079
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-08 21:15:54 -07:00
Stephane Bourque
b837e41569 Merge pull request #58 from Telecominfraproject/WIFI-100079
Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10079
2022-07-08 08:55:10 -07:00
stephb9959
5e39987e36 Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10079
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-08 08:49:53 -07:00
Stephane Bourque
890eb7311a Merge pull request #57 from Telecominfraproject/WIFI-10040
Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10040
2022-07-04 21:40:16 -07:00
stephb9959
fc509adf01 Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10040
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-04 14:11:59 -07:00
Stephane Bourque
767331f575 Merge pull request #55 from Telecominfraproject/WIFI-10040
Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10040
2022-07-01 10:34:35 -07:00
stephb9959
d26ef6eeba Fix: https://telecominfraproject.atlassian.net/browse/WIFI-10040
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-07-01 09:50:21 -07:00
Johann Hoffmann
8c672f058f Always re-generate config file if TEMPLATE_CONFIG is set to true (#53)
Signed-off-by: Johann Hoffmann <johann.hoffmann@mailbox.org>
2022-06-24 18:49:02 +02:00
stephb9959
448563ab06 Merge remote-tracking branch 'origin/main' 2022-06-18 22:02:30 -07:00
stephb9959
2a22a35e58 Framework update.
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-06-18 22:02:22 -07:00
Johann Hoffmann
e745d4efe7 Supress curl output in PR cleanup workflow
Signed-off-by: Johann Hoffmann <johann.hoffmann@mailbox.org>
2022-06-17 12:03:20 +02:00
Johann Hoffmann
701e0b50ff [WIFI-9534] OWSEC error while doing GIT pull. (#52)
* Add condition to avoid deleting default and release branch images

Signed-off-by: Johann Hoffmann <johann.hoffmann@mailbox.org>

* Fix regex

Signed-off-by: Johann Hoffmann <johann.hoffmann@mailbox.org>

* Fix condition

Signed-off-by: Johann Hoffmann <johann.hoffmann@mailbox.org>
2022-06-17 12:00:54 +02:00
Johann Hoffmann
df082a969e Temporarily disable cleanup for merges into release branches
Signed-off-by: Johann Hoffmann <johann.hoffmann@mailbox.org>
2022-06-15 14:50:15 +02:00
jaspreetsachdev
5e1937ec4f Merge branch 'main' of https://github.com/Telecominfraproject/wlan-cloud-ucentralsec 2022-06-14 16:22:46 -04:00
Stephane Bourque
e679dc7458 Fixing bug: https://telecominfraproject.atlassian.net/browse/WIFI-9471
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
Signed-off-by: jaspreetsachdev <jaspreetsachdev@fb.com>
2022-06-14 16:22:19 -04:00
stephb9959
7e1a962b57 Fixing bug
Signed-off-by: jaspreetsachdev <jaspreetsachdev@fb.com>
2022-06-14 16:22:19 -04:00
Dmitry Dunaev
8ad2e12f12 [WIFI-9174] Fix: switch from deprecated bitnami charts to mirrored ones
Signed-off-by: Dmitry Dunaev <dmitry@opsfleet.com>
Signed-off-by: jaspreetsachdev <jaspreetsachdev@fb.com>
2022-06-14 16:22:19 -04:00
stephb9959
23d16e619a Framework update.
Signed-off-by: jaspreetsachdev <jaspreetsachdev@fb.com>
2022-06-14 16:22:19 -04:00
stephb9959
760cad9a14 Framework update.
Signed-off-by: jaspreetsachdev <jaspreetsachdev@fb.com>
2022-06-14 16:22:19 -04:00
stephb9959
94997a1f9f Framework update.
Signed-off-by: jaspreetsachdev <jaspreetsachdev@fb.com>
2022-06-14 16:22:19 -04:00
Dmitry Dunaev
9060fef03d [WIFI-7555] Fix: helm path
Signed-off-by: Dmitry Dunaev <dmitry@opsfleet.com>
Signed-off-by: jaspreetsachdev <jaspreetsachdev@fb.com>
2022-06-14 16:22:19 -04:00
Johann Hoffmann
2f8eb90c5a Enable CI for pull requests in release branches
Signed-off-by: Johann Hoffmann <johann.hoffmann@mailbox.org>
Signed-off-by: jaspreetsachdev <jaspreetsachdev@fb.com>
2022-06-14 16:22:19 -04:00
stephb9959
c0d0435efa Framework update.
Signed-off-by: jaspreetsachdev <jaspreetsachdev@fb.com>
2022-06-14 16:22:19 -04:00
stephb9959
6942de0475 Framework update.
Signed-off-by: jaspreetsachdev <jaspreetsachdev@fb.com>
2022-06-14 16:22:19 -04:00
stephb9959
cce2528ec4 Framework update.
Signed-off-by: jaspreetsachdev <jaspreetsachdev@fb.com>
2022-06-14 16:22:19 -04:00
stephb9959
3be0fd45d9 Framework update.
Signed-off-by: jaspreetsachdev <jaspreetsachdev@fb.com>
2022-06-14 16:22:19 -04:00
stephb9959
8b1a80ce09 Merge remote-tracking branch 'origin/main' 2022-06-14 07:44:17 -07:00
Stephane Bourque
5e12f00558 Fixing bug: https://telecominfraproject.atlassian.net/browse/WIFI-9471
Signed-off-by: stephb9959 <stephane.bourque@gmail.com>
2022-06-14 07:44:04 -07:00
stephb9959
1d534cb974 Fixing bug 2022-06-14 07:26:44 -07:00
stephb9959
a7e9c96f8d Fixing bug 2022-06-14 07:22:17 -07:00
stephb9959
cb3f7a0872 Merge remote-tracking branch 'origin/main' 2022-06-14 07:13:19 -07:00
stephb9959
6ad434c02f Framework update. 2022-06-14 07:13:10 -07:00
Dmitry Dunaev
62e3ada15c Merge pull request #47 from Telecominfraproject/fix/wifi-9174--dep-charts
[WIFI-9174] Fix: switch from deprecated bitnami charts to mirrored ones
2022-06-03 19:31:44 +03:00
Dmitry Dunaev
2beef2daba [WIFI-9174] Fix: switch from deprecated bitnami charts to mirrored ones
Signed-off-by: Dmitry Dunaev <dmitry@opsfleet.com>
2022-06-03 19:31:22 +03:00
stephb9959
4b131465fb Framework update. 2022-05-31 23:53:47 -07:00
stephb9959
cafc243e55 Framework update. 2022-05-31 23:26:05 -07:00
stephb9959
5c44134f9d Merge remote-tracking branch 'origin/main' 2022-05-31 11:50:44 -07:00
stephb9959
8ed86d3582 Framework update. 2022-05-31 11:50:37 -07:00
91 changed files with 2440 additions and 778 deletions

View File

@@ -17,4 +17,10 @@ jobs:
steps:
- run: |
export PR_BRANCH_TAG=$(echo ${GITHUB_HEAD_REF#refs/heads/} | tr '/' '-')
curl -uucentral:${{ secrets.DOCKER_REGISTRY_PASSWORD }} -X DELETE "https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral/owsec/$PR_BRANCH_TAG"
if [[ ! $PR_BRANCH_TAG =~ (main|master|release-*) ]]; then
echo "PR branch is $PR_BRANCH_TAG, deleting Docker image"
curl -s -uucentral:${{ secrets.DOCKER_REGISTRY_PASSWORD }} -X DELETE "https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral/owsec/$PR_BRANCH_TAG"
else
echo "PR branch is $PR_BRANCH_TAG, not deleting Docker image"
fi

View File

@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.13)
project(owsec VERSION 2.6.0)
project(owsec VERSION 2.7.0)
set(CMAKE_CXX_STANDARD 17)
@@ -47,6 +47,7 @@ add_definitions(-DAWS_CUSTOM_MEMORY_MANAGEMENT)
set(BUILD_SHARED_LIBS 1)
add_definitions(-DTIP_SECURITY_SERVICE="1")
add_definitions(-DPOCO_LOG_DEBUG="1")
add_compile_options(-Wall -Wextra)
if(ASAN)
@@ -77,6 +78,7 @@ add_executable( owsec
src/framework/orm.h
src/framework/StorageClass.h
src/framework/ow_constants.h
src/framework/MicroServiceErrorHandler.h
src/framework/WebSocketClientNotifications.h
src/seclibs/qrcode/qrcodegen.hpp src/seclibs/qrcode/qrcodegen.cpp
src/seclibs/cpptotp/bytes.cpp src/seclibs/cpptotp/bytes.h
@@ -124,7 +126,7 @@ add_executable( owsec
src/storage/orm_actionLinks.cpp src/storage/orm_actionLinks.h
src/storage/orm_avatar.cpp src/storage/orm_avatar.h
src/SpecialUserHelpers.h
src/RESTAPI/RESTAPI_db_helpers.h src/storage/orm_logins.cpp src/storage/orm_logins.h src/RESTAPI/RESTAPI_totp_handler.cpp src/RESTAPI/RESTAPI_totp_handler.h src/TotpCache.h src/RESTAPI/RESTAPI_subtotp_handler.cpp src/RESTAPI/RESTAPI_subtotp_handler.h src/RESTAPI/RESTAPI_signup_handler.cpp src/RESTAPI/RESTAPI_signup_handler.h)
src/RESTAPI/RESTAPI_db_helpers.h src/storage/orm_logins.cpp src/storage/orm_logins.h src/RESTAPI/RESTAPI_totp_handler.cpp src/RESTAPI/RESTAPI_totp_handler.h src/TotpCache.h src/RESTAPI/RESTAPI_subtotp_handler.cpp src/RESTAPI/RESTAPI_subtotp_handler.h src/RESTAPI/RESTAPI_signup_handler.cpp src/RESTAPI/RESTAPI_signup_handler.h src/MessagingTemplates.cpp src/MessagingTemplates.h)
if(NOT SMALL_BUILD)
target_link_libraries(owsec PUBLIC

View File

@@ -1,16 +1,24 @@
FROM alpine:3.15 AS build-base
ARG DEBIAN_VERSION=11.4-slim
ARG POCO_VERSION=poco-tip-v1
ARG FMTLIB_VERSION=9.0.0
ARG CPPKAFKA_VERSION=tip-v1
ARG JSON_VALIDATOR_VERSION=2.1.0
ARG AWS_SDK_VERSION=1.9.315
RUN apk add --update --no-cache \
FROM debian:$DEBIAN_VERSION AS build-base
RUN apt-get update && apt-get install --no-install-recommends -y \
make cmake g++ git \
unixodbc-dev postgresql-dev mariadb-dev \
librdkafka-dev boost-dev openssl-dev \
zlib-dev nlohmann-json \
curl-dev
libpq-dev libmariadb-dev libmariadbclient-dev-compat \
librdkafka-dev libboost-all-dev libssl-dev \
zlib1g-dev nlohmann-json3-dev ca-certificates libcurl4-openssl-dev
FROM build-base AS poco-build
ADD https://api.github.com/repos/stephb9959/poco/git/refs/heads/master version.json
RUN git clone https://github.com/stephb9959/poco /poco
ARG POCO_VERSION
ADD https://api.github.com/repos/AriliaWireless/poco/git/refs/tags/${POCO_VERSION} version.json
RUN git clone https://github.com/AriliaWireless/poco --branch ${POCO_VERSION} /poco
WORKDIR /poco
RUN mkdir cmake-build
@@ -21,8 +29,10 @@ RUN cmake --build . --target install
FROM build-base AS fmtlib-build
ADD https://api.github.com/repos/fmtlib/fmt/git/refs/heads/master version.json
RUN git clone https://github.com/fmtlib/fmt /fmtlib
ARG FMTLIB_VERSION
ADD https://api.github.com/repos/fmtlib/fmt/git/refs/tags/${FMTLIB_VERSION} version.json
RUN git clone https://github.com/fmtlib/fmt --branch ${FMTLIB_VERSION} /fmtlib
WORKDIR /fmtlib
RUN mkdir cmake-build
@@ -33,8 +43,10 @@ RUN make install
FROM build-base AS cppkafka-build
ADD https://api.github.com/repos/stephb9959/cppkafka/git/refs/heads/master version.json
RUN git clone https://github.com/stephb9959/cppkafka /cppkafka
ARG CPPKAFKA_VERSION
ADD https://api.github.com/repos/AriliaWireless/cppkafka/git/refs/tags/${CPPKAFKA_VERSION} version.json
RUN git clone https://github.com/AriliaWireless/cppkafka --branch ${CPPKAFKA_VERSION} /cppkafka
WORKDIR /cppkafka
RUN mkdir cmake-build
@@ -45,8 +57,10 @@ RUN cmake --build . --target install
FROM build-base AS json-schema-validator-build
ADD https://api.github.com/repos/pboettch/json-schema-validator/git/refs/heads/master version.json
RUN git clone https://github.com/pboettch/json-schema-validator /json-schema-validator
ARG JSON_VALIDATOR_VERSION
ADD https://api.github.com/repos/pboettch/json-schema-validator/git/refs/tags/${JSON_VALIDATOR_VERSION} version.json
RUN git clone https://github.com/pboettch/json-schema-validator --branch ${JSON_VALIDATOR_VERSION} /json-schema-validator
WORKDIR /json-schema-validator
RUN mkdir cmake-build
@@ -57,14 +71,19 @@ RUN make install
FROM build-base AS aws-sdk-cpp-build
ADD https://api.github.com/repos/aws/aws-sdk-cpp/git/refs/heads/main version.json
RUN git clone --recurse-submodules https://github.com/aws/aws-sdk-cpp /aws-sdk-cpp
ARG AWS_SDK_VERSION
ADD https://api.github.com/repos/aws/aws-sdk-cpp/git/refs/tags/${AWS_SDK_VERSION} version.json
RUN git clone --recurse-submodules https://github.com/aws/aws-sdk-cpp --branch ${AWS_SDK_VERSION} /aws-sdk-cpp
WORKDIR /aws-sdk-cpp
RUN mkdir cmake-build
WORKDIR cmake-build
RUN cmake .. -DBUILD_ONLY="sns;s3" \
-DCMAKE_BUILD_TYPE=Release \
-DUSE_OPENSSL=ON \
-DCPP_STANDARD=17 \
-DBUILD_SHARED_LIBS=ON \
-DCMAKE_CXX_FLAGS="-Wno-error=stringop-overflow -Wno-error=uninitialized" \
-DAUTORUN_UNIT_TESTS=OFF
RUN cmake --build . --config Release -j8
@@ -92,26 +111,24 @@ COPY --from=fmtlib-build /usr/local/lib /usr/local/lib
WORKDIR /owsec
RUN mkdir cmake-build
WORKDIR /owsec/cmake-build
RUN cmake .. \
-Dcrypto_LIBRARY=/usr/lib/libcrypto.so \
-DBUILD_SHARED_LIBS=ON
RUN cmake ..
RUN cmake --build . --config Release -j8
FROM alpine:3.15
FROM debian:$DEBIAN_VERSION
ENV OWSEC_USER=owsec \
OWSEC_ROOT=/owsec-data \
OWSEC_CONFIG=/owsec-data
RUN addgroup -S "$OWSEC_USER" && \
adduser -S -G "$OWSEC_USER" "$OWSEC_USER"
RUN useradd "$OWSEC_USER"
RUN mkdir /openwifi
RUN mkdir -p "$OWSEC_ROOT" "$OWSEC_CONFIG" && \
chown "$OWSEC_USER": "$OWSEC_ROOT" "$OWSEC_CONFIG"
RUN apk add --update --no-cache librdkafka su-exec gettext ca-certificates bash jq curl \
mariadb-connector-c libpq unixodbc postgresql-client
RUN apt-get update && apt-get install --no-install-recommends -y \
librdkafka++1 gosu gettext ca-certificates bash jq curl wget \
libmariadb-dev-compat libpq5 unixodbc postgresql-client
COPY readiness_check /readiness_check
COPY test_scripts/curl/cli /cli
@@ -122,7 +139,7 @@ COPY templates /dist/templates
COPY docker-entrypoint.sh /
COPY wait-for-postgres.sh /
RUN wget https://raw.githubusercontent.com/Telecominfraproject/wlan-cloud-ucentral-deploy/main/docker-compose/certs/restapi-ca.pem \
-O /usr/local/share/ca-certificates/restapi-ca-selfsigned.pem
-O /usr/local/share/ca-certificates/restapi-ca-selfsigned.crt
COPY --from=owsec-build /owsec/cmake-build/owsec /openwifi/owsec
COPY --from=cppkafka-build /cppkafka/cmake-build/src/lib/* /usr/local/lib
@@ -131,6 +148,8 @@ COPY --from=aws-sdk-cpp-build /aws-sdk-cpp/cmake-build/aws-cpp-sdk-core/libaws-c
COPY --from=aws-sdk-cpp-build /aws-sdk-cpp/cmake-build/aws-cpp-sdk-s3/libaws-cpp-sdk-s3.so /usr/local/lib
COPY --from=aws-sdk-cpp-build /aws-sdk-cpp/cmake-build/aws-cpp-sdk-sns/libaws-cpp-sdk-sns.so /usr/local/lib
RUN ldconfig
EXPOSE 16001 17001 16101
ENTRYPOINT ["/docker-entrypoint.sh"]

37
OPERATOR.md Normal file
View File

@@ -0,0 +1,37 @@
# Operator Support
In order to support multiple tenants and operators, you must prepare the security service to serve
customized e-mails and messages.
## Structure for `templates`
Any file in the root of the directory will be used as defaults. The following files must be present:
- email_invitation.html/txt : This email message will be sent to a newly added user.
- email_verification.html/txt : This email is sent when an email verification is required.
- password_reset.html/txt : This is sent when a pasword reset is requested.
- verification_code.html/txt : This is used during MFA when email based.
- signup_verification.html/txt : This email is send to a new subscriber who signed up for service.
- sub_email_verification.html/txt : This is sent to a subscriber requiring an email verification.
- sub_verification_code.html/txt : This is used during MFA when email based for a subscriber.
- logo.jpg : The default logo to use in any of these emails.
## Structure for `wwwassets`
Any file in the root of the directory will be used as defaults. The following files must be present:
- email_verification_error.html : Used when email verification has failed.
- email_verification_success.html : Used when emil verification has succeeded.
- invitation_error.html :
- invitation_success.html :
- password_policy.html :
- password_reset.html :
- password_reset_success.html :
- password_reset_error.html :
- signup_verification.html :
- signup_verification_error.html :
- signup_verification_success.html :
- favicon.ico : icon for the application
- 404_error.html : your customized 404 page
- the_logo : the logo to use.
## For tenants
When creating a tenant/operator, you must create a subdirectory inside each `wwwassets` and `templates` and replicate
all the files that appear at the root level. You need to use the short Operator name (also known as RegistrantId in the API). This means
no spaces, all lowercase characters and numbers. No special characters: 0-9 and a-z.

2
build
View File

@@ -1 +1 @@
57
22

View File

@@ -1,11 +1,11 @@
#!/bin/sh
#!/bin/bash
set -e
if [ "$SELFSIGNED_CERTS" = 'true' ]; then
update-ca-certificates
fi
if [[ "$TEMPLATE_CONFIG" = 'true' && ! -f "$OWSEC_CONFIG"/owsec.properties ]]; then
if [[ "$TEMPLATE_CONFIG" = 'true' ]]; then
RESTAPI_HOST_ROOTCA=${RESTAPI_HOST_ROOTCA:-"\$OWSEC_ROOT/certs/restapi-ca.pem"} \
RESTAPI_HOST_PORT=${RESTAPI_HOST_PORT:-"16001"} \
RESTAPI_HOST_CERT=${RESTAPI_HOST_CERT:-"\$OWSEC_ROOT/certs/restapi-cert.pem"} \
@@ -23,6 +23,7 @@ if [[ "$TEMPLATE_CONFIG" = 'true' && ! -f "$OWSEC_CONFIG"/owsec.properties ]]; t
SYSTEM_URI_PRIVATE=${SYSTEM_URI_PRIVATE:-"https://localhost:17001"} \
SYSTEM_URI_PUBLIC=${SYSTEM_URI_PUBLIC:-"https://localhost:16001"} \
SYSTEM_URI_UI=${SYSTEM_URI_UI:-"http://localhost"} \
SECURITY_RESTAPI_DISABLE=${SECURITY_RESTAPI_DISABLE:-"false"} \
SERVICE_KEY=${SERVICE_KEY:-"\$OWSEC_ROOT/certs/restapi-key.pem"} \
SERVICE_KEY_PASSWORD=${SERVICE_KEY_PASSWORD:-"mypassword"} \
SMSSENDER_ENABLED=${SMSSENDER_ENABLED:-"false"} \
@@ -84,7 +85,7 @@ if [ "$1" = '/openwifi/owsec' -a "$(id -u)" = '0' ]; then
if [ "$RUN_CHOWN" = 'true' ]; then
chown -R "$OWSEC_USER": "$OWSEC_ROOT" "$OWSEC_CONFIG"
fi
exec su-exec "$OWSEC_USER" "$@"
exec gosu "$OWSEC_USER" "$@"
fi
exec "$@"

2
helm/.gitignore vendored
View File

@@ -1 +1,3 @@
*.swp
Chart.lock
charts/

View File

@@ -5,14 +5,14 @@ name: owsec
version: 0.1.0
dependencies:
- name: postgresql
repository: https://charts.bitnami.com/bitnami
repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
version: 10.9.2
condition: postgresql.enabled
- name: mysql
repository: https://charts.bitnami.com/bitnami
repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
version: 8.8.3
condition: mysql.enabled
- name: mariadb
repository: https://charts.bitnami.com/bitnami
repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
version: 9.4.2
condition: mariadb.enabled

View File

@@ -70,8 +70,8 @@ The following table lists the configurable parameters of the chart and their def
| persistence.size | string | Defines PV size | `'10Gi'` |
| public_env_variables | hash | Defines list of environment variables to be passed to the Security | |
| configProperties | hash | Configuration properties that should be passed to the application in `owsec.properties`. May be passed by key in set (i.e. `configProperties."rtty\.token"`) | |
| certs | hash | Defines files (keys and certificates) that should be passed to the Security (PEM format is adviced to be used) (see `volumes.owsec` on where it is mounted) | |
| existingCertsSecret | string | Existing Kubernetes secret containing all required certificates and private keys for microservice operation. If set, certificates from `certs` key are ignored | `""` |
| certs | hash | Defines files (keys and certificates) that should be passed to the Gateway (PEM format is adviced to be used) (see `volumes.owsec` on where it is mounted). If `existingCertsSecret` is set, certificates passed this way will not be used. | |
Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example,

View File

@@ -1,4 +1,5 @@
{{- $root := . -}}
{{- $storageType := index .Values.configProperties "storage.type" -}}
---
apiVersion: apps/v1
kind: Deployment
@@ -46,6 +47,39 @@ spec:
- -timeout
- 600s
{{- if eq $storageType "postgresql" }}
- name: wait-postgres
image: "{{ .Values.images.owsec.repository }}:{{ .Values.images.owsec.tag }}"
imagePullPolicy: {{ .Values.images.owsec.pullPolicy }}
command:
- /wait-for-postgres.sh
- {{ index .Values.configProperties "storage.type.postgresql.host" }}
- echo
- "PostgreSQL is ready"
env:
- name: KUBERNETES_DEPLOYED
value: "{{ now }}"
{{- range $key, $value := .Values.public_env_variables }}
- name: {{ $key }}
value: {{ $value | quote }}
{{- end }}
{{- range $key, $value := .Values.secret_env_variables }}
- name: {{ $key }}
valueFrom:
secretKeyRef:
name: {{ include "owsec.fullname" $root }}-env
key: {{ $key }}
{{- end }}
volumeMounts:
{{- range .Values.volumes.owsec }}
- name: {{ .name }}
mountPath: {{ .mountPath }}
{{- if .subPath }}
subPath: {{ .subPath }}
{{- end }}
{{- end }}
{{- end }}
containers:
- name: owsec

View File

@@ -9,7 +9,7 @@ fullnameOverride: ""
images:
owsec:
repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owsec
tag: main
tag: v2.7.0-RC4
pullPolicy: Always
# regcred:
# registry: tip-tip-wlan-cloud-ucentral.jfrog.io
@@ -71,7 +71,7 @@ volumes:
mountPath: /owsec-data/certs
volumeDefinition: |
secret:
secretName: {{ include "owsec.fullname" . }}-certs
secretName: {{ if .Values.existingCertsSecret }}{{ .Values.existingCertsSecret }}{{ else }}{{ include "owsec.fullname" . }}-certs{{ end }}
# Change this if you want to use another volume type
- name: persist
mountPath: /owsec-data/persist
@@ -92,7 +92,7 @@ resources: {}
# memory: 128Mi
securityContext:
fsGroup: 101
fsGroup: 1000
nodeSelector: {}
@@ -228,6 +228,9 @@ configProperties:
storage.type.mysql.username: stephb
storage.type.mysql.password: snoopy99
# NOTE: List of required certificates may be found in "certs" key. Alternative way to pass required certificates is to create external secret with all required certificates and set secret name in "existingCertsSecret" key. Details may be found in https://github.com/Telecominfraproject/wlan-cloud-ucentral-deploy/tree/main/chart#tldr
existingCertsSecret: ""
certs:
# restapi-ca.pem: ""
# restapi-cert.pem: ""

View File

@@ -36,6 +36,7 @@ openwifi.system.data = $OWSEC_ROOT/data
openwifi.system.uri.private = https://localhost:17001
openwifi.system.uri.public = https://local.dpaas.arilia.com:16001
openwifi.system.uri.ui = https://ucentral-ui.arilia.com
openwifi.security.restapi.disable = false
openwifi.system.commandchannel = /tmp/app.ucentralsec
openwifi.service.key = $OWSEC_ROOT/certs/restapi-key.pem
openwifi.service.key.password = mypassword
@@ -132,4 +133,4 @@ storage.type.mysql.connectiontimeout = 60
########################################################################
logging.type = file
logging.path = $OWSEC_ROOT/logs
logging.level = debug
logging.level = debug

View File

@@ -36,6 +36,7 @@ openwifi.system.data = ${SYSTEM_DATA}
openwifi.system.uri.private = ${SYSTEM_URI_PRIVATE}
openwifi.system.uri.public = ${SYSTEM_URI_PUBLIC}
openwifi.system.uri.ui = ${SYSTEM_URI_UI}
openwifi.security.restapi.disable = ${SECURITY_RESTAPI_DISABLE}
openwifi.system.commandchannel = /tmp/app.ucentralsec
openwifi.service.key = ${SERVICE_KEY}
openwifi.service.key.password = ${SERVICE_KEY_PASSWORD}

View File

@@ -5,25 +5,30 @@
#include "ActionLinkManager.h"
#include "StorageService.h"
#include "RESTObjects/RESTAPI_SecurityObjects.h"
#include "MessagingTemplates.h"
namespace OpenWifi {
int ActionLinkManager::Start() {
poco_information(Logger(),"Starting...");
if(!Running_)
Thr_.start(*this);
return 0;
}
void ActionLinkManager::Stop() {
poco_information(Logger(),"Stopping...");
if(Running_) {
Running_ = false;
Thr_.wakeUp();
Thr_.join();
}
poco_information(Logger(),"Stopped...");
}
void ActionLinkManager::run() {
Running_ = true ;
Utils::SetThreadName("action-mgr");
while(Running_) {
Poco::Thread::trySleep(2000);
@@ -52,44 +57,59 @@ namespace OpenWifi {
i.action==OpenWifi::SecurityObjects::LinkActions::SUB_SIGNUP ) && !StorageService()->SubDB().GetUserById(i.userId,UInfo)) {
StorageService()->ActionLinksDB().CancelAction(i.id);
continue;
} else if((i.action==OpenWifi::SecurityObjects::LinkActions::EMAIL_INVITATION) &&
(OpenWifi::Now()-i.created)>(24*60*60)) {
StorageService()->ActionLinksDB().CancelAction(i.id);
continue;
}
switch(i.action) {
case OpenWifi::SecurityObjects::LinkActions::FORGOT_PASSWORD: {
if(AuthService::SendEmailToUser(i.id, UInfo.email, AuthService::FORGOT_PASSWORD)) {
Logger().information(fmt::format("Send password reset link to {}",UInfo.email));
if(AuthService::SendEmailToUser(i.id, UInfo.email, MessagingTemplates::FORGOT_PASSWORD)) {
poco_information(Logger(),fmt::format("Send password reset link to {}",UInfo.email));
}
StorageService()->ActionLinksDB().SentAction(i.id);
}
break;
case OpenWifi::SecurityObjects::LinkActions::VERIFY_EMAIL: {
if(AuthService::SendEmailToUser(i.id, UInfo.email, AuthService::EMAIL_VERIFICATION)) {
Logger().information(fmt::format("Send email verification link to {}",UInfo.email));
if(AuthService::SendEmailToUser(i.id, UInfo.email, MessagingTemplates::EMAIL_VERIFICATION)) {
poco_information(Logger(),fmt::format("Send email verification link to {}",UInfo.email));
}
StorageService()->ActionLinksDB().SentAction(i.id);
}
break;
case OpenWifi::SecurityObjects::LinkActions::EMAIL_INVITATION: {
if(AuthService::SendEmailToUser(i.id, UInfo.email, MessagingTemplates::EMAIL_INVITATION)) {
poco_information(Logger(),fmt::format("Send new subscriber email invitation link to {}",UInfo.email));
}
StorageService()->ActionLinksDB().SentAction(i.id);
}
break;
case OpenWifi::SecurityObjects::LinkActions::SUB_FORGOT_PASSWORD: {
if(AuthService::SendEmailToSubUser(i.id, UInfo.email, AuthService::FORGOT_PASSWORD)) {
Logger().information(fmt::format("Send subscriber password reset link to {}",UInfo.email));
auto Signup = Poco::StringTokenizer(UInfo.signingUp,":");
if(AuthService::SendEmailToSubUser(i.id, UInfo.email,MessagingTemplates::SUB_FORGOT_PASSWORD, Signup.count()==1 ? "" : Signup[0])) {
poco_information(Logger(),fmt::format("Send subscriber password reset link to {}",UInfo.email));
}
StorageService()->ActionLinksDB().SentAction(i.id);
}
break;
case OpenWifi::SecurityObjects::LinkActions::SUB_VERIFY_EMAIL: {
if(AuthService::SendEmailToSubUser(i.id, UInfo.email, AuthService::EMAIL_VERIFICATION)) {
Logger().information(fmt::format("Send subscriber email verification link to {}",UInfo.email));
auto Signup = Poco::StringTokenizer(UInfo.signingUp,":");
if(AuthService::SendEmailToSubUser(i.id, UInfo.email, MessagingTemplates::SUB_EMAIL_VERIFICATION, Signup.count()==1 ? "" : Signup[0])) {
poco_information(Logger(),fmt::format("Send subscriber email verification link to {}",UInfo.email));
}
StorageService()->ActionLinksDB().SentAction(i.id);
}
break;
case OpenWifi::SecurityObjects::LinkActions::SUB_SIGNUP: {
if(AuthService::SendEmailToSubUser(i.id, UInfo.email, AuthService::SIGNUP_VERIFICATION)) {
Logger().information(fmt::format("Send new subscriber email verification link to {}",UInfo.email));
auto Signup = Poco::StringTokenizer(UInfo.signingUp,":");
if(AuthService::SendEmailToSubUser(i.id, UInfo.email, MessagingTemplates::SIGNUP_VERIFICATION, Signup.count()==1 ? "" : Signup[0])) {
poco_information(Logger(),fmt::format("Send new subscriber email verification link to {}",UInfo.email));
}
StorageService()->ActionLinksDB().SentAction(i.id);
}

View File

@@ -12,14 +12,6 @@ namespace OpenWifi {
class ActionLinkManager : public SubSystemServer, Poco::Runnable {
public:
/* enum Actions {
FORGOT_PASSWORD,
VERIFY_EMAIL,
SUB_FORGOT_PASSWORD,
SUB_VERIFY_EMAIL,
SUB_SIGNUP
};
*/
static ActionLinkManager * instance() {
static auto instance_ = new ActionLinkManager;
return instance_;

View File

@@ -8,18 +8,21 @@
#include <ctime>
#include "framework/MicroService.h"
#include "framework/KafkaTopics.h"
#include "Poco/Net/OAuth20Credentials.h"
#include "Poco/JWT/Token.h"
#include "Poco/JWT/Signer.h"
#include "Poco/StringTokenizer.h"
#include "framework/MicroService.h"
#include "StorageService.h"
#include "AuthService.h"
#include "framework/KafkaTopics.h"
#include "SMTPMailerService.h"
#include "MFAServer.h"
#include "MessagingTemplates.h"
namespace OpenWifi {
@@ -33,7 +36,6 @@ namespace OpenWifi {
}
}
int AuthService::AccessTypeToInt(ACCESS_TYPE T) {
switch (T) {
case USERNAME: return 1;
@@ -46,24 +48,25 @@ namespace OpenWifi {
static const std::string DefaultPassword_8_u_l_n_1{"^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[\\{\\}\\(\\)~_\\+\\|\\\\\\[\\]\\;\\:\\<\\>\\.\\,\\/\\?\\\"\\'\\`\\=#?!@$%^&*-]).{8,}$"};
int AuthService::Start() {
Logger().notice("Starting...");
poco_information(Logger(),"Starting...");
TokenAging_ = (uint64_t) MicroService::instance().ConfigGetInt("authentication.token.ageing", 30 * 24 * 60 * 60);
RefreshTokenLifeSpan_ = (uint64_t) MicroService::instance().ConfigGetInt("authentication.refresh_token.lifespan", 90 * 24 * 60 * 600);
HowManyOldPassword_ = MicroService::instance().ConfigGetInt("authentication.oldpasswords", 5);
AccessPolicy_ = MicroService::instance().ConfigPath("openwifi.document.policy.access", "/wwwassets/access_policy.html");
PasswordPolicy_ = MicroService::instance().ConfigPath("openwifi.document.policy.password", "/wwwassets/password_policy.html");
AccessPolicy_ = MicroService::instance().ConfigGetString("openwifi.document.policy.access", "/wwwassets/access_policy.html");
PasswordPolicy_ = MicroService::instance().ConfigGetString("openwifi.document.policy.password", "/wwwassets/password_policy.html");
PasswordValidation_ = PasswordValidationStr_ = MicroService::instance().ConfigGetString("authentication.validation.expression",DefaultPassword_8_u_l_n_1);
SubPasswordValidation_ = SubPasswordValidationStr_ = MicroService::instance().ConfigGetString("subscriber.validation.expression",DefaultPassword_8_u_l_n_1);
SubAccessPolicy_ = MicroService::instance().ConfigPath("subscriber.policy.access", "/wwwassets/access_policy.html");
SubPasswordPolicy_ = MicroService::instance().ConfigPath("subscriber.policy.password", "/wwwassets/password_policy.html");
SubAccessPolicy_ = MicroService::instance().ConfigGetString("subscriber.policy.access", "/wwwassets/access_policy.html");
SubPasswordPolicy_ = MicroService::instance().ConfigGetString("subscriber.policy.password", "/wwwassets/password_policy.html");
return 0;
}
void AuthService::Stop() {
Logger().notice("Stopping...");
poco_information(Logger(),"Stopping...");
poco_information(Logger(),"Stopped...");
}
bool AuthService::RefreshUserToken(Poco::Net::HTTPServerRequest & Request, const std::string & RefreshToken, SecurityObjects::UserInfoAndPolicy & UI) {
@@ -142,18 +145,20 @@ namespace OpenWifi {
return false;
}
bool AuthService::IsAuthorized(Poco::Net::HTTPServerRequest & Request, std::string & SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired )
bool AuthService::IsAuthorized(Poco::Net::HTTPServerRequest & Request, std::string & SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, std::uint64_t TID, bool & Expired )
{
std::lock_guard Guard(Mutex_);
// std::lock_guard Guard(Mutex_);
std::string CallToken;
Expired = false;
try {
std::string CallToken;
Poco::Net::OAuth20Credentials Auth(Request);
if (Auth.getScheme() == "Bearer") {
CallToken = Auth.getBearerToken();
}
if(CallToken.empty()) {
poco_debug(Logger(), fmt::format("TokenValidation failed for TID={} Token={}", TID, CallToken));
return false;
}
@@ -161,35 +166,40 @@ namespace OpenWifi {
uint64_t RevocationDate=0;
std::string UserId;
if(StorageService()->UserTokenDB().GetToken(CallToken, WT, UserId, RevocationDate)) {
if(RevocationDate!=0)
if(RevocationDate!=0) {
poco_debug(Logger(), fmt::format("TokenValidation failed for TID={} Token={}", TID, CallToken));
return false;
}
auto now=OpenWifi::Now();
Expired = (WT.created_ + WT.expires_in_) < now;
if(StorageService()->UserDB().GetUserById(UserId,UInfo.userinfo)) {
UInfo.webtoken = WT;
SessionToken = CallToken;
poco_debug(Logger(), fmt::format("TokenValidation success for TID={} Token={}", TID, CallToken));
return true;
}
}
return false;
} catch(const Poco::Exception &E) {
Logger().log(E);
}
poco_debug(Logger(), fmt::format("TokenValidation failed for TID={} Token={}", TID, CallToken));
return false;
}
bool AuthService::IsSubAuthorized(Poco::Net::HTTPServerRequest & Request, std::string & SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired )
bool AuthService::IsSubAuthorized(Poco::Net::HTTPServerRequest & Request, std::string & SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, std::uint64_t TID, bool & Expired )
{
std::lock_guard Guard(Mutex_);
// std::lock_guard Guard(Mutex_);
std::string CallToken;
Expired = false;
try {
std::string CallToken;
Poco::Net::OAuth20Credentials Auth(Request);
if (Auth.getScheme() == "Bearer") {
CallToken = Auth.getBearerToken();
}
if(CallToken.empty()) {
poco_debug(Logger(), fmt::format("TokenValidation failed for TID={} Token={}", TID, CallToken));
return false;
}
@@ -197,20 +207,23 @@ namespace OpenWifi {
uint64_t RevocationDate=0;
std::string UserId;
if(StorageService()->SubTokenDB().GetToken(CallToken, WT, UserId, RevocationDate)) {
if(RevocationDate!=0)
if(RevocationDate!=0) {
poco_debug(Logger(), fmt::format("TokenValidation failed for TID={} Token={}", TID, CallToken));
return false;
}
auto now=OpenWifi::Now();
Expired = (WT.created_ + WT.expires_in_) < now;
if(StorageService()->SubDB().GetUserById(UserId,UInfo.userinfo)) {
UInfo.webtoken = WT;
SessionToken = CallToken;
poco_debug(Logger(), fmt::format("TokenValidation success for TID={} Token={}", TID, CallToken));
return true;
}
}
return false;
} catch(const Poco::Exception &E) {
Logger().log(E);
}
poco_debug(Logger(), fmt::format("TokenValidation failed for TID={} Token={}", TID, CallToken));
return false;
}
@@ -514,7 +527,6 @@ namespace OpenWifi {
return SUCCESS;
}
return INVALID_CREDENTIALS;
}
@@ -564,33 +576,66 @@ namespace OpenWifi {
return INVALID_CREDENTIALS;
}
bool AuthService::SendEmailToUser(const std::string &LinkId, std::string &Email, EMAIL_REASON Reason) {
bool AuthService::SendEmailChallengeCode(const SecurityObjects::UserInfoAndPolicy &UInfo, const std::string &Challenge) {
auto OperatorParts = Poco::StringTokenizer(UInfo.userinfo.signingUp,":");
if(UInfo.userinfo.signingUp.empty() || OperatorParts.count()!=2) {
MessageAttributes Attrs;
Attrs[RECIPIENT_EMAIL] = UInfo.userinfo.email;
Attrs[LOGO] = AuthService::GetLogoAssetURI();
Attrs[SUBJECT] = "Login validation code";
Attrs[CHALLENGE_CODE] = Challenge;
return SMTPMailerService()->SendMessage(UInfo.userinfo.email, MessagingTemplates::TemplateName(MessagingTemplates::VERIFICATION_CODE), Attrs);
} else {
MessageAttributes Attrs;
Attrs[RECIPIENT_EMAIL] = UInfo.userinfo.email;
Attrs[LOGO] = AuthService::GetLogoAssetURI();
Attrs[SUBJECT] = "Login validation code";
Attrs[CHALLENGE_CODE] = Challenge;
return SMTPMailerService()->SendMessage(UInfo.userinfo.email, MessagingTemplates::TemplateName(MessagingTemplates::SUB_VERIFICATION_CODE,OperatorParts[0]), Attrs);
}
}
bool AuthService::SendEmailToUser(const std::string &LinkId, std::string &Email, MessagingTemplates::EMAIL_REASON Reason) {
SecurityObjects::UserInfo UInfo;
if(StorageService()->UserDB().GetUserByEmail(Email,UInfo)) {
switch (Reason) {
case FORGOT_PASSWORD: {
case MessagingTemplates::FORGOT_PASSWORD: {
MessageAttributes Attrs;
Attrs[RECIPIENT_EMAIL] = UInfo.email;
Attrs[LOGO] = GetLogoAssetURI();
Attrs[SUBJECT] = "Password reset link";
Attrs[ACTION_LINK] = MicroService::instance().GetPublicAPIEndPoint() + "/actionLink?action=password_reset&id=" + LinkId ;
SMTPMailerService()->SendMessage(UInfo.email, "password_reset.txt", Attrs);
Attrs[ACTION_LINK_HTML] = "/api/v1/actionLink?action=password_reset&id=" + LinkId ;
SMTPMailerService()->SendMessage(UInfo.email, MessagingTemplates::TemplateName(MessagingTemplates::FORGOT_PASSWORD), Attrs);
}
break;
case EMAIL_VERIFICATION: {
case MessagingTemplates::EMAIL_VERIFICATION: {
MessageAttributes Attrs;
Attrs[RECIPIENT_EMAIL] = UInfo.email;
Attrs[LOGO] = GetLogoAssetURI();
Attrs[SUBJECT] = "e-mail Address Verification";
Attrs[ACTION_LINK] = MicroService::instance().GetPublicAPIEndPoint() + "/actionLink?action=email_verification&id=" + LinkId ;
SMTPMailerService()->SendMessage(UInfo.email, "email_verification.txt", Attrs);
Attrs[ACTION_LINK_HTML] = "/api/v1/actionLink?action=email_verification&id=" + LinkId ;
SMTPMailerService()->SendMessage(UInfo.email, MessagingTemplates::TemplateName(MessagingTemplates::EMAIL_VERIFICATION), Attrs);
UInfo.waitingForEmailCheck = true;
}
break;
case MessagingTemplates::EMAIL_INVITATION: {
MessageAttributes Attrs;
Attrs[RECIPIENT_EMAIL] = UInfo.email;
Attrs[LOGO] = GetLogoAssetURI();
Attrs[SUBJECT] = "e-mail Invitation";
Attrs[ACTION_LINK] = MicroService::instance().GetPublicAPIEndPoint() + "/actionLink?action=email_invitation&id=" + LinkId ;
Attrs[ACTION_LINK_HTML] = "/api/v1/actionLink?action=email_invitation&id=" + LinkId ;
SMTPMailerService()->SendMessage(UInfo.email, MessagingTemplates::TemplateName(MessagingTemplates::EMAIL_INVITATION), Attrs);
UInfo.waitingForEmailCheck = true;
}
break;
default:
break;
}
@@ -599,40 +644,43 @@ namespace OpenWifi {
return false;
}
bool AuthService::SendEmailToSubUser(const std::string &LinkId, std::string &Email, EMAIL_REASON Reason) {
bool AuthService::SendEmailToSubUser(const std::string &LinkId, std::string &Email, MessagingTemplates::EMAIL_REASON Reason, const std::string &OperatorName ) {
SecurityObjects::UserInfo UInfo;
if(StorageService()->SubDB().GetUserByEmail(Email,UInfo)) {
switch (Reason) {
case FORGOT_PASSWORD: {
case MessagingTemplates::SUB_FORGOT_PASSWORD: {
MessageAttributes Attrs;
Attrs[RECIPIENT_EMAIL] = UInfo.email;
Attrs[LOGO] = GetLogoAssetURI();
Attrs[SUBJECT] = "Password reset link";
Attrs[ACTION_LINK] = MicroService::instance().GetPublicAPIEndPoint() + "/actionLink?action=password_reset&id=" + LinkId ;
SMTPMailerService()->SendMessage(UInfo.email, "password_reset.txt", Attrs);
Attrs[ACTION_LINK] = MicroService::instance().GetPublicAPIEndPoint() + "/actionLink?action=sub_password_reset&id=" + LinkId ;
Attrs[ACTION_LINK_HTML] = "/api/v1/actionLink?action=sub_password_reset&id=" + LinkId ;
SMTPMailerService()->SendMessage(UInfo.email, MessagingTemplates::TemplateName(MessagingTemplates::SUB_FORGOT_PASSWORD, OperatorName), Attrs);
}
break;
case EMAIL_VERIFICATION: {
case MessagingTemplates::SUB_EMAIL_VERIFICATION: {
MessageAttributes Attrs;
Attrs[RECIPIENT_EMAIL] = UInfo.email;
Attrs[LOGO] = GetLogoAssetURI();
Attrs[SUBJECT] = "e-mail Address Verification";
Attrs[ACTION_LINK] = MicroService::instance().GetPublicAPIEndPoint() + "/actionLink?action=email_verification&id=" + LinkId ;
SMTPMailerService()->SendMessage(UInfo.email, "email_verification.txt", Attrs);
Attrs[ACTION_LINK] = MicroService::instance().GetPublicAPIEndPoint() + "/actionLink?action=sub_email_verification&id=" + LinkId ;
Attrs[ACTION_LINK_HTML] = "/api/v1/actionLink?action=sub_email_verification&id=" + LinkId ;
SMTPMailerService()->SendMessage(UInfo.email, MessagingTemplates::TemplateName(MessagingTemplates::SUB_EMAIL_VERIFICATION, OperatorName), Attrs);
UInfo.waitingForEmailCheck = true;
}
break;
case SIGNUP_VERIFICATION: {
case MessagingTemplates::SIGNUP_VERIFICATION: {
MessageAttributes Attrs;
Attrs[RECIPIENT_EMAIL] = UInfo.email;
Attrs[LOGO] = GetLogoAssetURI();
Attrs[SUBJECT] = "Signup e-mail Address Verification";
Attrs[ACTION_LINK] = MicroService::instance().GetPublicAPIEndPoint() + "/actionLink?action=signup_verification&id=" + LinkId ;
SMTPMailerService()->SendMessage(UInfo.email, "signup_verification.txt", Attrs);
Attrs[ACTION_LINK_HTML] = "/api/v1/actionLink?action=signup_verification&id=" + LinkId ;
SMTPMailerService()->SendMessage(UInfo.email, MessagingTemplates::TemplateName(MessagingTemplates::SIGNUP_VERIFICATION, OperatorName), Attrs);
UInfo.waitingForEmailCheck = true;
}
break;
@@ -693,7 +741,8 @@ namespace OpenWifi {
}
return false;
}
return IsValidSubToken(Token, WebToken, UserInfo, Expired);
// return IsValidSubToken(Token, WebToken, UserInfo, Expired);
return false;
}
bool AuthService::IsValidSubToken(const std::string &Token, SecurityObjects::WebToken &WebToken, SecurityObjects::UserInfo &UserInfo, bool & Expired) {

View File

@@ -11,6 +11,8 @@
#include <regex>
#include "framework/MicroService.h"
#include "Poco/JSON/Object.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/HTTPServerResponse.h"
@@ -20,8 +22,8 @@
#include "Poco/HMACEngine.h"
#include "Poco/ExpireLRUCache.h"
#include "framework/MicroService.h"
#include "RESTObjects/RESTAPI_SecurityObjects.h"
#include "MessagingTemplates.h"
namespace OpenWifi{
@@ -36,12 +38,6 @@ namespace OpenWifi{
CUSTOM
};
enum EMAIL_REASON {
FORGOT_PASSWORD,
EMAIL_VERIFICATION,
SIGNUP_VERIFICATION
};
static ACCESS_TYPE IntToAccessType(int C);
static int AccessTypeToInt(ACCESS_TYPE T);
@@ -53,14 +49,14 @@ namespace OpenWifi{
int Start() override;
void Stop() override;
[[nodiscard]] bool IsAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired);
[[nodiscard]] bool IsAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, std::uint64_t TID, bool & Expired);
[[nodiscard]] UNAUTHORIZED_REASON Authorize( std::string & UserName, const std::string & Password, const std::string & NewPassword, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired );
void CreateToken(const std::string & UserName, SecurityObjects::UserInfoAndPolicy &UInfo);
[[nodiscard]] bool SetPassword(const std::string &Password, SecurityObjects::UserInfo & UInfo);
[[nodiscard]] const std:: string & PasswordValidationExpression() const { return PasswordValidationStr_;};
void Logout(const std::string &token, bool EraseFromCache=true);
[[nodiscard]] bool IsSubAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired);
[[nodiscard]] bool IsSubAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, std::uint64_t TID, bool & Expired);
[[nodiscard]] UNAUTHORIZED_REASON AuthorizeSub( std::string & UserName, const std::string & Password, const std::string & NewPassword, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired );
void CreateSubToken(const std::string & UserName, SecurityObjects::UserInfoAndPolicy &UInfo);
[[nodiscard]] bool SetSubPassword(const std::string &Password, SecurityObjects::UserInfo & UInfo);
@@ -90,10 +86,12 @@ namespace OpenWifi{
[[nodiscard]] static bool VerifyEmail(SecurityObjects::UserInfo &UInfo);
[[nodiscard]] static bool VerifySubEmail(SecurityObjects::UserInfo &UInfo);
[[nodiscard]] static bool SendEmailToUser(const std::string &LinkId, std::string &Email, EMAIL_REASON Reason);
[[nodiscard]] static bool SendEmailToSubUser(const std::string &LinkId, std::string &Email, EMAIL_REASON Reason);
[[nodiscard]] static bool SendEmailToUser(const std::string &LinkId, std::string &Email, MessagingTemplates::EMAIL_REASON Reason);
[[nodiscard]] static bool SendEmailToSubUser(const std::string &LinkId, std::string &Email, MessagingTemplates::EMAIL_REASON Reason, const std::string &OperatorName);
[[nodiscard]] bool RequiresMFA(const SecurityObjects::UserInfoAndPolicy &UInfo);
[[nodiscard]] bool SendEmailChallengeCode(const SecurityObjects::UserInfoAndPolicy &UInfo, const std::string &code);
bool DeleteUserFromCache(const std::string &UserName);
bool DeleteSubUserFromCache(const std::string &UserName);
void RevokeToken(std::string & Token);
@@ -158,11 +156,11 @@ namespace OpenWifi{
inline auto AuthService() { return AuthService::instance(); }
[[nodiscard]] inline bool AuthServiceIsAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo , bool & Expired, bool Sub ) {
[[nodiscard]] inline bool AuthServiceIsAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo , std::uint64_t TID, bool & Expired, bool Sub ) {
if(Sub)
return AuthService()->IsSubAuthorized(Request, SessionToken, UInfo, Expired );
return AuthService()->IsSubAuthorized(Request, SessionToken, UInfo, TID, Expired );
else
return AuthService()->IsAuthorized(Request, SessionToken, UInfo, Expired );
return AuthService()->IsAuthorized(Request, SessionToken, UInfo, TID, Expired );
}
} // end of namespace

View File

@@ -10,6 +10,7 @@
// Arilia Wireless Inc.
//
#include "Poco/Util/Application.h"
#include "Poco/Util/Option.h"
#include "Poco/Environment.h"

View File

@@ -10,6 +10,8 @@
#include <vector>
#include <set>
#include "framework/MicroService.h"
#include "Poco/Util/Application.h"
#include "Poco/Util/ServerApplication.h"
#include "Poco/Util/Option.h"
@@ -20,7 +22,6 @@
#include "Poco/Crypto/CipherFactory.h"
#include "Poco/Crypto/Cipher.h"
#include "framework/MicroService.h"
namespace OpenWifi {

View File

@@ -2,10 +2,11 @@
// Created by stephane bourque on 2021-10-11.
//
#include "framework/MicroService.h"
#include "MFAServer.h"
#include "SMSSender.h"
#include "SMTPMailerService.h"
#include "framework/MicroService.h"
#include "AuthService.h"
#include "TotpCache.h"
@@ -44,12 +45,7 @@ namespace OpenWifi {
std::string Message = "This is your login code: " + Challenge + " Please enter this in your login screen.";
return SMSSender()->Send(UInfo.userinfo.userTypeProprietaryInfo.mobiles[0].number, Message);
} else if(Method==MFAMETHODS::EMAIL && SMTPMailerService()->Enabled() && !UInfo.userinfo.email.empty()) {
MessageAttributes Attrs;
Attrs[RECIPIENT_EMAIL] = UInfo.userinfo.email;
Attrs[LOGO] = AuthService::GetLogoAssetURI();
Attrs[SUBJECT] = "Login validation code";
Attrs[CHALLENGE_CODE] = Challenge;
return SMTPMailerService()->SendMessage(UInfo.userinfo.email, "verification_code.txt", Attrs);
return AuthService()->SendEmailChallengeCode(UInfo,Challenge);
} else if(Method==MFAMETHODS::AUTHENTICATOR && !UInfo.userinfo.userTypeProprietaryInfo.authenticatorSecret.empty()) {
return true;
}

View File

@@ -0,0 +1,8 @@
//
// Created by stephane bourque on 2022-07-25.
//
#include "MessagingTemplates.h"
namespace OpenWifi {
} // OpenWifi

75
src/MessagingTemplates.h Normal file
View File

@@ -0,0 +1,75 @@
//
// Created by stephane bourque on 2022-07-25.
//
#pragma once
#include <string>
#include <vector>
namespace OpenWifi {
class MessagingTemplates {
public:
static MessagingTemplates & instance() {
static auto instance = new MessagingTemplates;
return *instance;
}
enum EMAIL_REASON {
FORGOT_PASSWORD = 0,
EMAIL_VERIFICATION,
SIGNUP_VERIFICATION,
EMAIL_INVITATION,
VERIFICATION_CODE,
SUB_FORGOT_PASSWORD,
SUB_EMAIL_VERIFICATION,
SUB_VERIFICATION_CODE
};
static std::string AddOperator(const std::string & filename, const std::string &OperatorName) {
if(OperatorName.empty())
return "/" + filename;
return "/" + OperatorName + "/" + filename;
}
static std::string TemplateName( EMAIL_REASON r , const std::string &OperatorName="") {
switch (r) {
case FORGOT_PASSWORD: return AddOperator(EmailTemplateNames[FORGOT_PASSWORD],OperatorName);
case EMAIL_VERIFICATION: return AddOperator(EmailTemplateNames[EMAIL_VERIFICATION],OperatorName);
case SIGNUP_VERIFICATION: return AddOperator(EmailTemplateNames[SIGNUP_VERIFICATION],OperatorName);
case EMAIL_INVITATION: return AddOperator(EmailTemplateNames[EMAIL_INVITATION],OperatorName);
case VERIFICATION_CODE: return AddOperator(EmailTemplateNames[VERIFICATION_CODE],OperatorName);
case SUB_FORGOT_PASSWORD: return AddOperator(EmailTemplateNames[SUB_FORGOT_PASSWORD],OperatorName);
case SUB_EMAIL_VERIFICATION: return AddOperator(EmailTemplateNames[SUB_EMAIL_VERIFICATION],OperatorName);
case SUB_VERIFICATION_CODE: return AddOperator(EmailTemplateNames[SUB_VERIFICATION_CODE],OperatorName);
default:
return "";
}
}
static std::string Logo(const std::string &OperatorName = "" ) {
return AddOperator("logo.jpg", OperatorName);
}
static std::string SubLogo(const std::string &OperatorName = "" ) {
return AddOperator("sub_logo.jpg", OperatorName);
}
private:
inline const static std::vector<std::string> EmailTemplateNames = {
"password_reset",
"email_verification",
"signup_verification",
"email_invitation",
"verification_code",
"sub_password_reset",
"sub_email_verification",
"sub_verification_code"
};
};
inline MessagingTemplates & MessagingTemplates() { return MessagingTemplates::instance(); }
} // OpenWifi

View File

@@ -23,8 +23,12 @@ namespace OpenWifi {
if(Action=="password_reset")
return RequestResetPassword(Link);
else if(Action=="sub_password_reset")
return RequestSubResetPassword(Link);
else if(Action=="email_verification")
return DoEmailVerification(Link);
else if(Action=="sub_email_verification")
return DoSubEmailVerification(Link);
else if(Action=="signup_verification")
return DoNewSubVerification(Link);
else
@@ -36,8 +40,12 @@ namespace OpenWifi {
if(Action=="password_reset")
return CompleteResetPassword();
else if(Action=="sub_password_reset")
return CompleteResetPassword();
else if(Action=="signup_completion")
return CompleteSubVerification();
else if(Action=="email_invitation")
return CompleteEmailInvitation();
else
return DoReturnA404();
}
@@ -199,10 +207,11 @@ namespace OpenWifi {
// Send the update to the provisioning service
Poco::JSON::Object Body;
Body.set("signupUUID", UInfo.signingUp);
auto RawSignup = Poco::StringTokenizer(UInfo.signingUp,":");
Body.set("signupUUID", RawSignup.count()==1 ? UInfo.signingUp : RawSignup[1]);
OpenAPIRequestPut ProvRequest(uSERVICE_PROVISIONING,"/api/v1/signup",
{
{"signupUUID", UInfo.signingUp} ,
{"signupUUID", RawSignup.count()==1 ? UInfo.signingUp : RawSignup[1]} ,
{"operation", "emailVerified"}
},
Body,30000);
@@ -238,7 +247,8 @@ namespace OpenWifi {
return SendHTMLFileBack(FormFile, FormVars);
}
Logger_.information(fmt::format("EMAIL-VERIFICATION(%s): For ID={}", Request->clientAddress().toString(), UInfo.email));
Logger_.information(fmt::format("EMAIL-VERIFICATION(%s): For ID={}", Request->clientAddress().toString(),
UInfo.email));
UInfo.waitingForEmailCheck = false;
UInfo.validated = true;
UInfo.lastEmailCheck = OpenWifi::Now();
@@ -262,4 +272,16 @@ namespace OpenWifi {
SendHTMLFileBack(FormFile, FormVars);
}
void RESTAPI_action_links::CompleteEmailInvitation() {
/// TODO:
}
void RESTAPI_action_links::RequestSubResetPassword([[maybe_unused]] SecurityObjects::ActionLink &Link) {
}
void RESTAPI_action_links::DoSubEmailVerification([[maybe_unused]] SecurityObjects::ActionLink &Link) {
}
}

View File

@@ -22,11 +22,14 @@ namespace OpenWifi {
true, RateLimit{.Interval=1000,.MaxCalls=10}) {}
static auto PathName() { return std::list<std::string>{"/api/v1/actionLink"}; };
void RequestResetPassword(SecurityObjects::ActionLink &Link);
void RequestSubResetPassword(SecurityObjects::ActionLink &Link);
void CompleteResetPassword();
void CompleteSubVerification();
void DoEmailVerification(SecurityObjects::ActionLink &Link);
void DoSubEmailVerification(SecurityObjects::ActionLink &Link);
void DoReturnA404();
void DoNewSubVerification(SecurityObjects::ActionLink &Link);
void CompleteEmailInvitation();
void DoGet() final;
void DoPost() final;

View File

@@ -29,7 +29,8 @@
namespace OpenWifi {
Poco::Net::HTTPRequestHandler * RESTAPI_ExtRouter(const std::string &Path, RESTAPIHandler::BindingMap &Bindings,
Poco::Logger & L, RESTAPI_GenericServer & S, uint64_t TransactionId) {
Poco::Logger & L, RESTAPI_GenericServer & S,
uint64_t TransactionId) {
return RESTAPI_Router<
RESTAPI_oauth2_handler,
RESTAPI_user_handler,

View File

@@ -13,8 +13,9 @@ namespace OpenWifi {
auto UserName = GetParameter("email");
auto signupUUID = GetParameter("signupUUID");
auto owner = GetParameter("owner");
if(UserName.empty() || signupUUID.empty() || owner.empty()) {
Logger().error("Signup requires: email, signupUUID, and owner.");
auto operatorName = GetParameter("operatorName");
if(UserName.empty() || signupUUID.empty() || owner.empty() || operatorName.empty()) {
Logger().error("Signup requires: email, signupUUID, operatorName, and owner.");
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
}
@@ -37,7 +38,7 @@ namespace OpenWifi {
}
SecurityObjects::UserInfo NewSub;
NewSub.signingUp = signupUUID;
NewSub.signingUp = operatorName + ":" + signupUUID;
NewSub.waitingForEmailCheck = true;
NewSub.name = UserName;
NewSub.modified = OpenWifi::Now();

View File

@@ -12,6 +12,10 @@ namespace OpenWifi {
void OpenWifi::RESTAPI_sms_handler::DoPost() {
const auto &Obj = ParsedBody_;
if(!SMSSender()->Enabled()) {
return BadRequest(RESTAPI::Errors::SMSMFANotEnabled);
}
std::string Arg;
if(HasParameter("validateNumber",Arg) && Arg=="true" && Obj->has("to")) {
auto Number = Obj->get("to").toString();

View File

@@ -76,12 +76,21 @@ namespace OpenWifi {
return BadRequest(RESTAPI::Errors::SMSMissingPhoneNumber);
}
if(!SMSSender()->Enabled()) {
return BadRequest(RESTAPI::Errors::SMSMFANotEnabled);
}
if (SMSSender()->StartValidation(MFC.sms, UserInfo_.userinfo.email)) {
return OK();
} else {
return InternalError(RESTAPI::Errors::SMSTryLater);
}
} else if (GetBoolParameter("completeValidation", false)) {
if(!SMSSender()->Enabled()) {
return BadRequest(RESTAPI::Errors::SMSMFANotEnabled);
}
auto ChallengeCode = GetParameter("challengeCode", "");
if (ChallengeCode.empty()) {
return BadRequest(RESTAPI::Errors::SMSMissingChallenge);

View File

@@ -11,7 +11,6 @@ namespace OpenWifi {
auto Reset = GetBoolParameter("reset",false);
std::string QRCode;
if(TotpCache()->StartValidation(UserInfo_.userinfo,false,QRCode,Reset)) {
return SendFileContent(QRCode, "image/svg+xml","qrcode.svg");
}

View File

@@ -538,8 +538,8 @@ namespace OpenWifi::AnalyticsObjects {
void WifiClientHistory::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"timestamp",timestamp);
field_to_json(Obj,"stationId",stationId);
field_to_json(Obj,"bssId",bssId);
field_to_json(Obj,"station_id",station_id);
field_to_json(Obj,"bssid",bssid);
field_to_json(Obj,"ssid",ssid);
field_to_json(Obj,"rssi",rssi);
field_to_json(Obj,"rx_bitrate",rx_bitrate);
@@ -573,13 +573,14 @@ namespace OpenWifi::AnalyticsObjects {
field_to_json(Obj,"connected",connected);
field_to_json(Obj,"inactive",inactive);
field_to_json(Obj,"tx_retries",tx_retries);
field_to_json(Obj,"venue_id",venue_id);
}
bool WifiClientHistory::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj,"timestamp",timestamp);
field_from_json(Obj,"stationId",stationId);
field_from_json(Obj,"bssId",bssId);
field_from_json(Obj,"station_id",station_id);
field_from_json(Obj,"bssid",bssid);
field_from_json(Obj,"ssid",ssid);
field_from_json(Obj,"rssi",rssi);
field_from_json(Obj,"rx_bitrate",rx_bitrate);
@@ -613,6 +614,7 @@ namespace OpenWifi::AnalyticsObjects {
field_from_json(Obj,"connected",connected);
field_from_json(Obj,"inactive",inactive);
field_from_json(Obj,"tx_retries",tx_retries);
field_from_json(Obj,"venue_id",venue_id);
return true;
} catch(...) {

View File

@@ -376,8 +376,8 @@ namespace OpenWifi {
struct WifiClientHistory {
uint64_t timestamp=OpenWifi::Now();
std::string stationId;
std::string bssId;
std::string station_id;
std::string bssid;
std::string ssid;
int64_t rssi=0;
uint32_t rx_bitrate=0;
@@ -411,6 +411,7 @@ namespace OpenWifi {
uint64_t connected=0;
uint64_t inactive=0;
uint64_t tx_retries=0;
std::string venue_id;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);

View File

@@ -3,176 +3,206 @@
//
#include "RESTAPI_CertObjects.h"
#include "framework/MicroService.h"
using OpenWifi::RESTAPI_utils::field_to_json;
using OpenWifi::RESTAPI_utils::field_from_json;
namespace OpenWifi {
namespace CertObjects {
void CertificateEntry::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"id", id);
field_to_json(Obj,"entity", entity);
field_to_json(Obj,"creator", creator);
field_to_json(Obj,"type", type);
field_to_json(Obj,"status", status);
field_to_json(Obj,"certificate", certificate);
field_to_json(Obj,"key", key);
field_to_json(Obj,"devid", devid);
field_to_json(Obj,"cas", cas);
field_to_json(Obj,"manufacturer", manufacturer);
field_to_json(Obj,"model", model);
field_to_json(Obj,"redirector", redirector);
field_to_json(Obj,"commonName", commonName);
field_to_json(Obj,"certificateId", certificateId);
field_to_json(Obj,"batch", batch);
field_to_json(Obj,"created", created);
field_to_json(Obj,"modified", modified);
field_to_json(Obj,"revoked", revoked);
field_to_json(Obj,"revokeCount", revokeCount);
}
namespace OpenWifi::CertObjects {
void CertificateEntry::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"id", id);
field_to_json(Obj,"entity", entity);
field_to_json(Obj,"creator", creator);
field_to_json(Obj,"type", type);
field_to_json(Obj,"status", status);
field_to_json(Obj,"certificate", certificate);
field_to_json(Obj,"key", key);
field_to_json(Obj,"devid", devid);
field_to_json(Obj,"cas", cas);
field_to_json(Obj,"manufacturer", manufacturer);
field_to_json(Obj,"model", model);
field_to_json(Obj,"redirector", redirector);
field_to_json(Obj,"commonName", commonName);
field_to_json(Obj,"certificateId", certificateId);
field_to_json(Obj,"batch", batch);
field_to_json(Obj,"created", created);
field_to_json(Obj,"modified", modified);
field_to_json(Obj,"revoked", revoked);
field_to_json(Obj,"revokeCount", revokeCount);
field_to_json(Obj,"synched", synched);
}
bool CertificateEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj,"id", id);
field_from_json(Obj,"entity", entity);
field_from_json(Obj,"creator", creator);
field_from_json(Obj,"type", type);
field_from_json(Obj,"status", status);
field_from_json(Obj,"certificate", certificate);
field_from_json(Obj,"key", key);
field_from_json(Obj,"devid", devid);
field_from_json(Obj,"cas", cas);
field_from_json(Obj,"manufacturer", manufacturer);
field_from_json(Obj,"model", model);
field_from_json(Obj,"redirector", redirector);
field_from_json(Obj,"commonName", commonName);
field_from_json(Obj,"certificateId", certificateId);
field_from_json(Obj,"batch", batch);
field_from_json(Obj,"created", created);
field_from_json(Obj,"modified", modified);
field_from_json(Obj,"revoked", revoked);
field_from_json(Obj,"revokeCount", revokeCount);
return true;
} catch (...) {
}
return false;
bool CertificateEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj,"id", id);
field_from_json(Obj,"entity", entity);
field_from_json(Obj,"creator", creator);
field_from_json(Obj,"type", type);
field_from_json(Obj,"status", status);
field_from_json(Obj,"certificate", certificate);
field_from_json(Obj,"key", key);
field_from_json(Obj,"devid", devid);
field_from_json(Obj,"cas", cas);
field_from_json(Obj,"manufacturer", manufacturer);
field_from_json(Obj,"model", model);
field_from_json(Obj,"redirector", redirector);
field_from_json(Obj,"commonName", commonName);
field_from_json(Obj,"certificateId", certificateId);
field_from_json(Obj,"batch", batch);
field_from_json(Obj,"created", created);
field_from_json(Obj,"modified", modified);
field_from_json(Obj,"revoked", revoked);
field_from_json(Obj,"revokeCount", revokeCount);
field_from_json(Obj,"synched", synched);
return true;
} catch (...) {
}
return false;
}
void EntityEntry::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"id", id);
field_to_json(Obj,"creator", creator);
field_to_json(Obj,"name", name);
field_to_json(Obj,"description", description);
field_to_json(Obj,"defaultRedirector", defaultRedirector);
field_to_json(Obj,"apiKey", apiKey);
field_to_json(Obj,"serverEnrollmentProfile", serverEnrollmentProfile);
field_to_json(Obj,"clientEnrollmentProfile", clientEnrollmentProfile);
field_to_json(Obj,"organization", organization);
field_to_json(Obj,"created", created);
field_to_json(Obj,"modified", modified);
field_to_json(Obj,"suspended", suspended);
field_to_json(Obj,"deleted", deleted);
field_to_json(Obj,"notes", notes);
}
void EntityEntry::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"id", id);
field_to_json(Obj,"creator", creator);
field_to_json(Obj,"name", name);
field_to_json(Obj,"description", description);
field_to_json(Obj,"defaultRedirector", defaultRedirector);
field_to_json(Obj,"apiKey", apiKey);
field_to_json(Obj,"serverEnrollmentProfile", serverEnrollmentProfile);
field_to_json(Obj,"clientEnrollmentProfile", clientEnrollmentProfile);
field_to_json(Obj,"organization", organization);
field_to_json(Obj,"created", created);
field_to_json(Obj,"modified", modified);
field_to_json(Obj,"suspended", suspended);
field_to_json(Obj,"deleted", deleted);
field_to_json(Obj,"notes", notes);
}
bool EntityEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj,"id", id);
field_from_json(Obj,"creator", creator);
field_from_json(Obj,"name", name);
field_from_json(Obj,"description", description);
field_from_json(Obj,"defaultRedirector", defaultRedirector);
field_from_json(Obj,"apiKey", apiKey);
field_from_json(Obj,"serverEnrollmentProfile", serverEnrollmentProfile);
field_from_json(Obj,"clientEnrollmentProfile", clientEnrollmentProfile);
field_from_json(Obj,"organization", organization);
field_from_json(Obj,"created", created);
field_from_json(Obj,"modified", modified);
field_from_json(Obj,"suspended", suspended);
field_from_json(Obj,"deleted", deleted);
field_from_json(Obj,"notes", notes);
return true;
} catch (...) {
}
return false;
bool EntityEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj,"id", id);
field_from_json(Obj,"creator", creator);
field_from_json(Obj,"name", name);
field_from_json(Obj,"description", description);
field_from_json(Obj,"defaultRedirector", defaultRedirector);
field_from_json(Obj,"apiKey", apiKey);
field_from_json(Obj,"serverEnrollmentProfile", serverEnrollmentProfile);
field_from_json(Obj,"clientEnrollmentProfile", clientEnrollmentProfile);
field_from_json(Obj,"organization", organization);
field_from_json(Obj,"created", created);
field_from_json(Obj,"modified", modified);
field_from_json(Obj,"suspended", suspended);
field_from_json(Obj,"deleted", deleted);
field_from_json(Obj,"notes", notes);
return true;
} catch (...) {
}
return false;
}
void BatchEntry::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"id", id);
field_to_json(Obj,"entity", entity);
field_to_json(Obj,"creator", creator);
field_to_json(Obj,"name", name);
field_to_json(Obj,"description", description);
field_to_json(Obj,"manufacturer", manufacturer);
field_to_json(Obj,"model", model);
field_to_json(Obj,"redirector", redirector);
field_to_json(Obj,"commonNames", commonNames);
field_to_json(Obj,"jobHistory", jobHistory);
field_to_json(Obj,"notes", notes);
field_to_json(Obj,"submitted", submitted);
field_to_json(Obj,"started", started);
field_to_json(Obj,"completed", completed);
field_to_json(Obj,"modified", modified);
}
void BatchEntry::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"id", id);
field_to_json(Obj,"entity", entity);
field_to_json(Obj,"creator", creator);
field_to_json(Obj,"name", name);
field_to_json(Obj,"description", description);
field_to_json(Obj,"manufacturer", manufacturer);
field_to_json(Obj,"model", model);
field_to_json(Obj,"redirector", redirector);
field_to_json(Obj,"commonNames", commonNames);
field_to_json(Obj,"jobHistory", jobHistory);
field_to_json(Obj,"notes", notes);
field_to_json(Obj,"submitted", submitted);
field_to_json(Obj,"started", started);
field_to_json(Obj,"completed", completed);
field_to_json(Obj,"modified", modified);
}
bool BatchEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj,"id", id);
field_from_json(Obj,"entity", entity);
field_from_json(Obj,"creator", creator);
field_from_json(Obj,"name", name);
field_from_json(Obj,"description", description);
field_from_json(Obj,"manufacturer", manufacturer);
field_from_json(Obj,"model", model);
field_from_json(Obj,"redirector", redirector);
field_from_json(Obj,"commonNames", commonNames);
field_from_json(Obj,"jobHistory", jobHistory);
field_from_json(Obj,"notes", notes);
field_from_json(Obj,"submitted", submitted);
field_from_json(Obj,"started", started);
field_from_json(Obj,"completed", completed);
field_from_json(Obj,"modified", modified);
return true;
} catch (...) {
}
return false;
bool BatchEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj,"id", id);
field_from_json(Obj,"entity", entity);
field_from_json(Obj,"creator", creator);
field_from_json(Obj,"name", name);
field_from_json(Obj,"description", description);
field_from_json(Obj,"manufacturer", manufacturer);
field_from_json(Obj,"model", model);
field_from_json(Obj,"redirector", redirector);
field_from_json(Obj,"commonNames", commonNames);
field_from_json(Obj,"jobHistory", jobHistory);
field_from_json(Obj,"notes", notes);
field_from_json(Obj,"submitted", submitted);
field_from_json(Obj,"started", started);
field_from_json(Obj,"completed", completed);
field_from_json(Obj,"modified", modified);
return true;
} catch (...) {
}
return false;
}
void JobEntry::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"id", id);
field_to_json(Obj,"entity", entity);
field_to_json(Obj,"creator", creator);
field_to_json(Obj,"batch", batch);
field_to_json(Obj,"commonNames", commonNames);
field_to_json(Obj,"completedNames", completedNames);
field_to_json(Obj,"errorNames", errorNames);
field_to_json(Obj,"status", status);
field_to_json(Obj,"command", command);
field_to_json(Obj,"parameters", parameters);
field_to_json(Obj,"submitted", submitted);
field_to_json(Obj,"started", started);
field_to_json(Obj,"completed", completed);
}
void JobEntry::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"id", id);
field_to_json(Obj,"entity", entity);
field_to_json(Obj,"creator", creator);
field_to_json(Obj,"batch", batch);
field_to_json(Obj,"commonNames", commonNames);
field_to_json(Obj,"completedNames", completedNames);
field_to_json(Obj,"errorNames", errorNames);
field_to_json(Obj,"status", status);
field_to_json(Obj,"command", command);
field_to_json(Obj,"parameters", parameters);
field_to_json(Obj,"submitted", submitted);
field_to_json(Obj,"started", started);
field_to_json(Obj,"completed", completed);
}
bool JobEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj,"id", id);
field_from_json(Obj,"entity", entity);
field_from_json(Obj,"creator", creator);
field_from_json(Obj,"batch", batch);
field_from_json(Obj,"commonNames", commonNames);
field_from_json(Obj,"completedNames", completedNames);
field_from_json(Obj,"errorNames", errorNames);
field_from_json(Obj,"status", status);
field_from_json(Obj,"command", command);
field_from_json(Obj,"parameters", parameters);
field_from_json(Obj,"submitted", submitted);
field_from_json(Obj,"started", started);
field_from_json(Obj,"completed", completed);
return true;
} catch (...) {
}
return false;
bool JobEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj,"id", id);
field_from_json(Obj,"entity", entity);
field_from_json(Obj,"creator", creator);
field_from_json(Obj,"batch", batch);
field_from_json(Obj,"commonNames", commonNames);
field_from_json(Obj,"completedNames", completedNames);
field_from_json(Obj,"errorNames", errorNames);
field_from_json(Obj,"status", status);
field_from_json(Obj,"command", command);
field_from_json(Obj,"parameters", parameters);
field_from_json(Obj,"submitted", submitted);
field_from_json(Obj,"started", started);
field_from_json(Obj,"completed", completed);
return true;
} catch (...) {
}
return false;
}
void DashBoardYearlyStats::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "year", year);
field_to_json(Obj, "activeCerts", activeCerts);
field_to_json(Obj, "revokedCerts", revokedCerts);
}
void Dashboard::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"snapshot", snapshot);
field_to_json(Obj,"numberOfIssuedCerts", numberOfIssuedCerts);
field_to_json(Obj,"numberOfRevokedCerts", numberOfRevokedCerts);
field_to_json(Obj,"activeCertsPerOrganization", activeCertsPerOrganization);
field_to_json(Obj,"revokedCertsPerOrganization", revokedCertsPerOrganization);
field_to_json(Obj,"numberOfRedirectors", numberOfRedirectors);
field_to_json(Obj,"deviceTypes", deviceTypes);
field_to_json(Obj,"monthlyNumberOfCerts", monthlyNumberOfCerts);
field_to_json(Obj,"monthlyNumberOfCertsPerOrgPerYear", monthlyNumberOfCertsPerOrgPerYear);
}
void Dashboard::reset() {
snapshot=0;
numberOfRevokedCerts = numberOfIssuedCerts = 0;
activeCertsPerOrganization.clear();
revokedCertsPerOrganization.clear();
numberOfRedirectors.clear();
deviceTypes.clear();
monthlyNumberOfCerts.clear();
monthlyNumberOfCertsPerOrgPerYear.clear();
}
}

View File

@@ -5,97 +5,118 @@
#pragma once
#include <string>
#include "framework/MicroService.h"
#include "framework/OpenWifiTypes.h"
#include "RESTObjects/RESTAPI_SecurityObjects.h"
namespace OpenWifi {
namespace OpenWifi::CertObjects {
namespace CertObjects {
struct CertificateEntry {
OpenWifi::Types::UUID_t id;
OpenWifi::Types::UUID_t entity;
OpenWifi::Types::UUID_t creator;
std::string type;
std::string status;
std::string certificate;
std::string key;
std::string devid;
std::string cas;
std::string manufacturer;
std::string model;
std::string redirector;
std::string commonName;
std::string certificateId;
OpenWifi::Types::UUID_t batch;
uint64_t created = 0;
uint64_t modified = 0;
uint64_t revoked = 0;
uint64_t revokeCount = 0;
uint64_t synched = 0;
struct CertificateEntry {
OpenWifi::Types::UUID_t id;
OpenWifi::Types::UUID_t entity;
OpenWifi::Types::UUID_t creator;
std::string type;
std::string status;
std::string certificate;
std::string key;
std::string devid;
std::string cas;
std::string manufacturer;
std::string model;
std::string redirector;
std::string commonName;
std::string certificateId;
OpenWifi::Types::UUID_t batch;
uint64_t created = 0;
uint64_t modified = 0;
uint64_t revoked = 0;
uint64_t revokeCount = 0;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct EntityEntry {
OpenWifi::Types::UUID_t id;
OpenWifi::Types::UUID_t creator;
std::string name;
std::string description;
std::string defaultRedirector;
std::string apiKey;
std::string serverEnrollmentProfile;
std::string clientEnrollmentProfile;
std::string organization;
SecurityObjects::NoteInfoVec notes;
bool suspended=false;
bool deleted=false;
uint64_t created = 0 ;
uint64_t modified = 0 ;
struct EntityEntry {
OpenWifi::Types::UUID_t id;
OpenWifi::Types::UUID_t creator;
std::string name;
std::string description;
std::string defaultRedirector;
std::string apiKey;
std::string serverEnrollmentProfile;
std::string clientEnrollmentProfile;
std::string organization;
SecurityObjects::NoteInfoVec notes;
bool suspended=false;
bool deleted=false;
uint64_t created = 0 ;
uint64_t modified = 0 ;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct BatchEntry {
OpenWifi::Types::UUID_t id;
OpenWifi::Types::UUID_t entity;
OpenWifi::Types::UUID_t creator;
std::string name;
std::string description;
std::string manufacturer;
std::string model;
std::string redirector;
std::vector<std::string> commonNames;
std::vector<std::string> jobHistory;
SecurityObjects::NoteInfoVec notes;
uint64_t submitted = 0 ;
uint64_t started = 0 ;
uint64_t completed = 0 ;
uint64_t modified = 0 ;
struct BatchEntry {
OpenWifi::Types::UUID_t id;
OpenWifi::Types::UUID_t entity;
OpenWifi::Types::UUID_t creator;
std::string name;
std::string description;
std::string manufacturer;
std::string model;
std::string redirector;
std::vector<std::string> commonNames;
std::vector<std::string> jobHistory;
SecurityObjects::NoteInfoVec notes;
uint64_t submitted = 0 ;
uint64_t started = 0 ;
uint64_t completed = 0 ;
uint64_t modified = 0 ;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct JobEntry {
OpenWifi::Types::UUID_t id;
OpenWifi::Types::UUID_t entity;
OpenWifi::Types::UUID_t creator;
OpenWifi::Types::UUID_t batch;
std::string command;
OpenWifi::Types::StringVec commonNames;
OpenWifi::Types::StringVec completedNames;
OpenWifi::Types::StringVec errorNames;
Types::StringPairVec parameters;
std::string status;
uint64_t submitted=0;
uint64_t started=0;
uint64_t completed=0;
struct JobEntry {
OpenWifi::Types::UUID_t id;
OpenWifi::Types::UUID_t entity;
OpenWifi::Types::UUID_t creator;
OpenWifi::Types::UUID_t batch;
std::string command;
OpenWifi::Types::StringVec commonNames;
OpenWifi::Types::StringVec completedNames;
OpenWifi::Types::StringVec errorNames;
Types::StringPairVec parameters;
std::string status;
uint64_t submitted=0;
uint64_t started=0;
uint64_t completed=0;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct DashBoardYearlyStats {
uint64_t year=0;
OpenWifi::Types::Counted3DMapSII activeCerts;
OpenWifi::Types::Counted3DMapSII revokedCerts;
void to_json(Poco::JSON::Object &Obj) const;
};
struct Dashboard {
uint64_t snapshot=0;
uint64_t numberOfIssuedCerts=0;
uint64_t numberOfRevokedCerts=0;
OpenWifi::Types::CountedMap activeCertsPerOrganization;
OpenWifi::Types::CountedMap revokedCertsPerOrganization;
OpenWifi::Types::CountedMap numberOfRedirectors;
OpenWifi::Types::CountedMap deviceTypes;
OpenWifi::Types::CountedMap monthlyNumberOfCerts;
std::vector<DashBoardYearlyStats> monthlyNumberOfCertsPerOrgPerYear;
void to_json(Poco::JSON::Object &Obj) const;
void reset();
};
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
}
}

View File

@@ -203,6 +203,10 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj,"kafkaClients", kafkaClients);
field_to_json(Obj,"kafkaPackets", kafkaPackets);
field_to_json(Obj,"locale", locale);
field_to_json(Obj,"started", started);
field_to_json(Obj,"sessionId", sessionId);
field_to_json(Obj,"connectionCompletionTime", connectionCompletionTime);
field_to_json(Obj,"totalConnectionTime", OpenWifi::Now() - started);
switch(VerifiedCertificate) {
case NO_CERTIFICATE:
@@ -218,6 +222,21 @@ namespace OpenWifi::GWObjects {
}
}
void DeviceConnectionStatistics::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"averageConnectionTime", averageConnectionTime);
field_to_json(Obj,"connectedDevices", connectedDevices );
}
bool DeviceConnectionStatistics::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj,"averageConnectionTime", averageConnectionTime);
field_from_json(Obj,"connectedDevices", connectedDevices );
return true;
} catch (const Poco::Exception &E) {
}
return false;
}
void RttySessionDetails::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"serialNumber", SerialNumber);
field_to_json(Obj,"server", Server);
@@ -293,7 +312,6 @@ namespace OpenWifi::GWObjects {
} catch (const Poco::Exception &E) {
}
return false;
}
void RadiusProxyPoolList::to_json(Poco::JSON::Object &Obj) const {
@@ -314,6 +332,8 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj,"description",description);
field_to_json(Obj,"authConfig",authConfig);
field_to_json(Obj,"acctConfig",acctConfig);
field_to_json(Obj,"coaConfig",coaConfig);
field_to_json(Obj,"useByDefault",useByDefault);
}
bool RadiusProxyPool::from_json(const Poco::JSON::Object::Ptr &Obj) {
@@ -322,6 +342,8 @@ namespace OpenWifi::GWObjects {
field_from_json(Obj,"description",description);
field_from_json(Obj,"authConfig",authConfig);
field_from_json(Obj,"acctConfig",acctConfig);
field_from_json(Obj,"coaConfig",coaConfig);
field_from_json(Obj,"useByDefault",useByDefault);
return true;
} catch (const Poco::Exception &E) {
}
@@ -329,7 +351,7 @@ namespace OpenWifi::GWObjects {
}
void RadiusProxyServerConfig::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"policy",strategy);
field_to_json(Obj,"strategy",strategy);
field_to_json(Obj,"monitor",monitor);
field_to_json(Obj,"monitorMethod",monitorMethod);
field_to_json(Obj,"methodParameters",methodParameters);
@@ -338,7 +360,7 @@ namespace OpenWifi::GWObjects {
bool RadiusProxyServerConfig::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj,"policy",strategy);
field_from_json(Obj,"strategy",strategy);
field_from_json(Obj,"monitor",monitor);
field_from_json(Obj,"monitorMethod",monitorMethod);
field_from_json(Obj,"methodParameters",methodParameters);
@@ -354,6 +376,16 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj,"ip",ip);
field_to_json(Obj,"port",port);
field_to_json(Obj,"weight",weight);
field_to_json(Obj,"secret",secret);
field_to_json(Obj,"certificate",certificate);
field_to_json(Obj,"radsec",radsec);
field_to_json(Obj,"radsecPort",radsecPort);
field_to_json(Obj,"radsecSecret",radsecSecret);
field_to_json(Obj,"radsecCacerts",radsecCacerts);
field_to_json(Obj,"radsecCert",radsecCert);
field_to_json(Obj,"radsecKey",radsecKey);
field_to_json(Obj,"radsecRealms",radsecRealms);
field_to_json(Obj,"ignore",ignore);
}
bool RadiusProxyServerEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
@@ -362,6 +394,16 @@ namespace OpenWifi::GWObjects {
field_from_json(Obj,"ip",ip);
field_from_json(Obj,"port",port);
field_from_json(Obj,"weight",weight);
field_from_json(Obj,"secret",secret);
field_from_json(Obj,"certificate",certificate);
field_from_json(Obj,"radsec",radsec);
field_from_json(Obj,"radsecSecret",radsecSecret);
field_from_json(Obj,"radsecPort",radsecPort);
field_from_json(Obj,"radsecCacerts",radsecCacerts);
field_from_json(Obj,"radsecCert",radsecCert);
field_from_json(Obj,"radsecKey",radsecKey);
field_from_json(Obj,"radsecRealms",radsecRealms);
field_from_json(Obj,"ignore",ignore);
return true;
} catch (const Poco::Exception &E) {
}

View File

@@ -38,6 +38,10 @@ namespace OpenWifi::GWObjects {
uint64_t kafkaPackets=0;
uint64_t websocketPackets=0;
std::string locale;
uint64_t started=0;
uint64_t sessionId=0;
double connectionCompletionTime=0.0;
void to_json(Poco::JSON::Object &Obj) const;
};
@@ -71,6 +75,13 @@ namespace OpenWifi::GWObjects {
void Print() const;
};
struct DeviceConnectionStatistics {
std::uint64_t connectedDevices = 0;
std::uint64_t averageConnectionTime = 0;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct Statistics {
std::string SerialNumber;
uint64_t UUID = 0 ;
@@ -216,6 +227,16 @@ namespace OpenWifi::GWObjects {
std::string ip;
uint16_t port=0;
uint64_t weight=0;
std::string secret;
std::string certificate;
bool radsec=false;
uint16_t radsecPort=2083;
std::string radsecSecret;
std::string radsecKey;
std::string radsecCert;
std::vector<std::string> radsecCacerts;
std::vector<std::string> radsecRealms;
bool ignore=false;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
@@ -237,6 +258,8 @@ namespace OpenWifi::GWObjects {
std::string description;
RadiusProxyServerConfig authConfig;
RadiusProxyServerConfig acctConfig;
RadiusProxyServerConfig coaConfig;
bool useByDefault=false;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);

View File

@@ -0,0 +1,110 @@
//
// Created by stephane bourque on 2021-08-31.
//
#include "framework/MicroService.h"
using OpenWifi::RESTAPI_utils::field_to_json;
using OpenWifi::RESTAPI_utils::field_from_json;
using OpenWifi::RESTAPI_utils::EmbedDocument;
#include "RESTAPI_OWLSobjects.h"
// SIM -> 0x53/0x073, 0x49/0x69, 0x4d/0x6d
namespace OpenWifi::OWLSObjects {
void SimulationDetails::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"id", id);
field_to_json(Obj,"name", name);
field_to_json(Obj,"gateway", gateway);
field_to_json(Obj,"certificate", certificate);
field_to_json(Obj,"key", key);
field_to_json(Obj,"macPrefix", macPrefix);
field_to_json(Obj,"deviceType", deviceType);
field_to_json(Obj,"devices", devices);
field_to_json(Obj,"healthCheckInterval", healthCheckInterval);
field_to_json(Obj,"stateInterval", stateInterval);
field_to_json(Obj,"minAssociations", minAssociations);
field_to_json(Obj,"maxAssociations", maxAssociations);
field_to_json(Obj,"minClients", minClients);
field_to_json(Obj,"maxClients", maxClients);
field_to_json(Obj,"simulationLength", simulationLength);
field_to_json(Obj,"threads", threads);
field_to_json(Obj,"clientInterval", clientInterval);
field_to_json(Obj,"keepAlive", keepAlive);
field_to_json(Obj,"reconnectInterval", reconnectInterval);
field_to_json(Obj,"concurrentDevices", concurrentDevices);
}
bool SimulationDetails::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj,"id", id);
field_from_json(Obj,"name", name);
field_from_json(Obj,"gateway", gateway);
field_from_json(Obj,"certificate", certificate);
field_from_json(Obj,"key", key);
field_from_json(Obj,"macPrefix", macPrefix);
field_from_json(Obj,"deviceType", deviceType);
field_from_json(Obj,"devices", devices);
field_from_json(Obj,"healthCheckInterval", healthCheckInterval);
field_from_json(Obj,"stateInterval", stateInterval);
field_from_json(Obj,"minAssociations", minAssociations);
field_from_json(Obj,"maxAssociations", maxAssociations);
field_from_json(Obj,"minClients", minClients);
field_from_json(Obj,"maxClients", maxClients);
field_from_json(Obj,"simulationLength", simulationLength);
field_from_json(Obj,"threads", threads);
field_from_json(Obj,"clientInterval", clientInterval);
field_from_json(Obj,"keepAlive", keepAlive);
field_from_json(Obj,"reconnectInterval", reconnectInterval);
field_from_json(Obj,"concurrentDevices", concurrentDevices);
return true;
} catch(...) {
}
return false;
}
void SimulationDetailsList::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"list", list);
}
bool SimulationDetailsList::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj,"list", list);
return true;
} catch(...) {
}
return false;
}
void SimulationStatus::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"id", id);
field_to_json(Obj,"simulationId", simulationId);
field_to_json(Obj,"state", state);
field_to_json(Obj,"tx", tx);
field_to_json(Obj,"rx", rx);
field_to_json(Obj,"msgsTx", msgsTx);
field_to_json(Obj,"msgsRx", msgsRx);
field_to_json(Obj,"liveDevices", liveDevices);
field_to_json(Obj,"timeToFullDevices", timeToFullDevices);
field_to_json(Obj,"startTime", startTime);
field_to_json(Obj,"endTime", endTime);
field_to_json(Obj,"errorDevices", errorDevices);
field_to_json(Obj,"owner", owner);
}
void Dashboard::to_json([[maybe_unused]] Poco::JSON::Object &Obj) const {
}
bool Dashboard::from_json([[maybe_unused]] const Poco::JSON::Object::Ptr &Obj) {
return true;
}
void Dashboard::reset() {
}
}

View File

@@ -0,0 +1,77 @@
//
// Created by stephane bourque on 2021-08-31.
//
#ifndef UCENTRALSIM_RESTAPI_OWLSOBJECTS_H
#define UCENTRALSIM_RESTAPI_OWLSOBJECTS_H
#include <vector>
#include "Poco/JSON/Object.h"
namespace OpenWifi::OWLSObjects {
struct SimulationDetails {
std::string id;
std::string name;
std::string gateway;
std::string certificate;
std::string key;
std::string macPrefix;
std::string deviceType;
uint64_t devices = 5;
uint64_t healthCheckInterval = 60;
uint64_t stateInterval = 60 ;
uint64_t minAssociations = 1;
uint64_t maxAssociations = 3;
uint64_t minClients = 1 ;
uint64_t maxClients = 3;
uint64_t simulationLength = 60 * 60;
uint64_t threads = 16;
uint64_t clientInterval = 1;
uint64_t keepAlive = 300;
uint64_t reconnectInterval = 30 ;
uint64_t concurrentDevices = 5;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct SimulationDetailsList {
std::vector<SimulationDetails> list;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct SimulationStatus {
std::string id;
std::string simulationId;
std::string state;
uint64_t tx;
uint64_t rx;
uint64_t msgsTx;
uint64_t msgsRx;
uint64_t liveDevices;
uint64_t timeToFullDevices;
uint64_t startTime;
uint64_t endTime;
uint64_t errorDevices;
std::string owner;
void to_json(Poco::JSON::Object &Obj) const;
};
struct Dashboard {
int O;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
void reset();
};
}
#endif //UCENTRALSIM_RESTAPI_OWLSOBJECTS_H

View File

@@ -9,6 +9,7 @@
#pragma once
#include <string>
#include <type_traits>
#include "framework/OpenWifiTypes.h"
#include "Poco/JSON/Object.h"
#include "Poco/Data/LOB.h"
@@ -27,8 +28,13 @@ namespace OpenWifi {
bool Delete_ = true;
bool PortalLogin_ = true;
AclTemplate() noexcept = default;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj); };
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
static_assert( std::is_nothrow_move_constructible_v<AclTemplate> );
struct WebToken {
std::string access_token_;
@@ -245,7 +251,8 @@ namespace OpenWifi {
VERIFY_EMAIL,
SUB_FORGOT_PASSWORD,
SUB_VERIFY_EMAIL,
SUB_SIGNUP
SUB_SIGNUP,
EMAIL_INVITATION
};
struct ActionLink {

View File

@@ -2,16 +2,14 @@
// Created by stephane bourque on 2021-10-09.
//
#include <aws/sns/SNSClient.h>
#include <aws/sns/model/PublishRequest.h>
#include <aws/sns/model/PublishResult.h>
#include <aws/sns/model/GetSMSAttributesRequest.h>
#include "framework/MicroService.h"
#include "MFAServer.h"
#include "SMS_provider_aws.h"
#include "SMS_provider_twilio.h"
#include "SMSSender.h"
#include "framework/MicroService.h"
namespace OpenWifi {
@@ -45,6 +43,8 @@ namespace OpenWifi {
bool SMSSender::StartValidation(const std::string &Number, const std::string &UserName) {
std::lock_guard G(Mutex_);
if(!Enabled_)
return false;
CleanCache();
uint64_t Now=OpenWifi::Now();
auto Challenge = MFAServer::MakeChallenge();
@@ -56,6 +56,9 @@ namespace OpenWifi {
bool SMSSender::IsNumberValid(const std::string &Number, const std::string &UserName) {
std::lock_guard G(Mutex_);
if(!Enabled_)
return false;
for(const auto &i:Cache_) {
if(i.Number==Number && i.UserName==UserName)
return i.Validated;
@@ -66,6 +69,9 @@ namespace OpenWifi {
bool SMSSender::CompleteValidation(const std::string &Number, const std::string &Code, const std::string &UserName) {
std::lock_guard G(Mutex_);
if(!Enabled_)
return false;
for(auto &i:Cache_) {
if(i.Code==Code && i.Number==Number && i.UserName==UserName) {
i.Validated=true;
@@ -77,7 +83,7 @@ namespace OpenWifi {
bool SMSSender::Send(const std::string &PhoneNumber, const std::string &Message) {
if(!Enabled_) {
Logger().information("SMS has not been enabled. Messages cannot be sent.");
poco_information(Logger(),"SMS has not been enabled. Messages cannot be sent.");
return false;
}
return ProviderImpl_->Send(PhoneNumber,Message);

View File

@@ -17,7 +17,7 @@ namespace OpenWifi {
Region_ = MicroService::instance().ConfigGetString("smssender.aws.region","");
if(SecretKey_.empty() || AccessKey_.empty() || Region_.empty()) {
Logger().debug("SMSSender is disabled. Please provide key, secret, and region.");
poco_debug(Logger(),"SMSSender is disabled. Please provide key, secret, and region.");
return false;
}
Running_=true;
@@ -51,16 +51,16 @@ namespace OpenWifi {
auto psms_out = sns.Publish(psms_req);
if (psms_out.IsSuccess()) {
Logger().debug(fmt::format("SMS sent to {}",PhoneNumber));
poco_debug(Logger(),fmt::format("SMS sent to {}",PhoneNumber));
return true;
}
std::string ErrMsg{psms_out.GetError().GetMessage()};
Logger().debug(fmt::format("SMS NOT sent to {}: {}",PhoneNumber, ErrMsg));
poco_debug(Logger(),fmt::format("SMS NOT sent to {}: {}",PhoneNumber, ErrMsg));
return false;
} catch (...) {
}
Logger().debug(fmt::format("SMS NOT sent to {}: failure in SMS service",PhoneNumber));
poco_debug(Logger(),fmt::format("SMS NOT sent to {}: failure in SMS service",PhoneNumber));
return false;
}

View File

@@ -4,12 +4,13 @@
#include "SMS_provider_twilio.h"
#include "framework/MicroService.h"
#include "Poco/Net/HTTPBasicCredentials.h"
#include "Poco/URI.h"
#include "Poco/Net/HTMLForm.h"
#include "Poco/Net/HTTPSClientSession.h"
#include "Poco/Net/HTTPResponse.h"
#include "framework/MicroService.h"
namespace OpenWifi {
bool SMS_provider_twilio::Initialize() {
@@ -18,7 +19,7 @@ namespace OpenWifi {
PhoneNumber_ = MicroService::instance().ConfigGetString("smssender.twilio.phonenumber","");
if(Sid_.empty() || Token_.empty() || PhoneNumber_.empty()) {
Logger().debug("SMSSender is disabled. Please provide SID, TOKEN, and PHONE NUMBER.");
poco_debug(Logger(),"SMSSender is disabled. Please provide SID, TOKEN, and PHONE NUMBER.");
return false;
}
Running_=true;
@@ -64,12 +65,12 @@ namespace OpenWifi {
std::istream& rs = session.receiveResponse(res);
if(res.getStatus()==Poco::Net::HTTPResponse::HTTP_OK) {
Logger().information(fmt::format("Message sent to {}", PhoneNumber));
poco_information(Logger(),fmt::format("Message sent to {}", PhoneNumber));
return true;
} else {
std::ostringstream os;
Poco::StreamCopier::copyStream(rs,os);
Logger().information(fmt::format("Message was not to {}: Error:{}", PhoneNumber, os.str()));
poco_information(Logger(),fmt::format("Message was not to {}: Error:{}", PhoneNumber, os.str()));
return false;
}
}

View File

@@ -2,7 +2,8 @@
// Created by stephane bourque on 2021-06-17.
//
#include <iostream>
#include <fstream>
#include "framework/MicroService.h"
#include "Poco/Net/MailMessage.h"
#include "Poco/Net/MailRecipient.h"
@@ -12,9 +13,9 @@
#include "Poco/Exception.h"
#include "Poco/Net/SSLManager.h"
#include "Poco/Net/Context.h"
#include "Poco/Net/NetException.h"
#include "SMTPMailerService.h"
#include "framework/MicroService.h"
#include "AuthService.h"
namespace OpenWifi {
@@ -31,7 +32,9 @@ namespace OpenWifi {
TemplateDir_ = MicroService::instance().ConfigPath("mailer.templates", MicroService::instance().DataDir());
MailRetry_ = MicroService::instance().ConfigGetInt("mailer.retry",2*60);
MailAbandon_ = MicroService::instance().ConfigGetInt("mailer.abandon",2*60*60);
UseHTML_ = MicroService::instance().ConfigGetBool("mailer.html",false);
Enabled_ = (!MailHost_.empty() && !SenderLoginPassword_.empty() && !SenderLoginUserName_.empty());
EmailLogo_ = TemplateDir_ + "/" + MicroService::instance().ConfigGetString("mailer.logo","logo.jpg");
}
}
@@ -49,7 +52,7 @@ namespace OpenWifi {
void SMTPMailerService::reinitialize([[maybe_unused]] Poco::Util::Application &self) {
MicroService::instance().LoadConfigurationFile();
Logger().information("Reinitializing.");
poco_information(Logger(),"Reinitializing.");
LoadMyConfig();
}
@@ -58,14 +61,14 @@ namespace OpenWifi {
PendingMessages_.push_back(MessageEvent{.Posted= OpenWifi::Now(),
.LastTry=0,
.Sent=0,
.File=Poco::File(TemplateDir_ + "/" +Name),
.TemplateName=Name,
.Attrs=Attrs});
return true;
}
void SMTPMailerService::run() {
Running_ = true;
Utils::SetThreadName("smtp-mailer");
while(Running_) {
Poco::Thread::trySleep(10000);
@@ -83,15 +86,23 @@ namespace OpenWifi {
auto Recipient = i->Attrs.find(RECIPIENT_EMAIL)->second;
uint64_t now = OpenWifi::Now();
if((i->LastTry==0 || (now-i->LastTry)>MailRetry_)) {
if (SendIt(*i)) {
Logger().information(fmt::format("Attempting to deliver for mail '{}'.", Recipient));
i = Messages_.erase(i);
} else {
i->LastTry = now;
++i;
switch(SendIt(*i)) {
case MessageSendStatus::msg_sent: {
poco_information(Logger(),fmt::format("Attempting to deliver for mail '{}'.", Recipient));
i = Messages_.erase(i);
} break;
case MessageSendStatus::msg_not_sent_but_resend: {
poco_information(Logger(),fmt::format("Mail for '{}' was not. We will retry later.", Recipient));
i->LastTry = now;
++i;
} break;
case MessageSendStatus::msg_not_sent_but_do_not_resend: {
poco_information(Logger(),fmt::format("Mail for '{}' will not be sent. Check email address", Recipient));
i = Messages_.erase(i);
} break;
}
} else if ((now-i->Posted)>MailAbandon_) {
Logger().information(fmt::format("Mail for '{}' has timed out and will not be sent.", Recipient));
poco_information(Logger(),fmt::format("Mail for '{}' has timed out and will not be sent.", Recipient));
i = Messages_.erase(i);
} else {
++i;
@@ -106,14 +117,12 @@ namespace OpenWifi {
}
}
bool SMTPMailerService::SendIt(const MessageEvent &Msg) {
MessageSendStatus SMTPMailerService::SendIt(const MessageEvent &Msg) {
std::string Recipient;
try
{
Poco::Net::MailMessage Message;
Recipient = Msg.Attrs.find(RECIPIENT_EMAIL)->second;
auto H1 = Msg.Attrs.find(SENDER);
std::string TheSender;
if(H1!=Msg.Attrs.end()) {
@@ -121,34 +130,40 @@ namespace OpenWifi {
} else {
TheSender = Sender_ ;
}
Message.setSender( TheSender );
Logger().information(fmt::format("Sending message to:{} from {}",Recipient,TheSender));
Message.addRecipient(Poco::Net::MailRecipient(Poco::Net::MailRecipient::PRIMARY_RECIPIENT, Recipient));
Message.setSubject(Msg.Attrs.find(SUBJECT)->second);
auto Message = std::make_unique<Poco::Net::MailMessage>();
Recipient = Msg.Attrs.find(RECIPIENT_EMAIL)->second;
Message->setSender( TheSender );
Message->addRecipient(Poco::Net::MailRecipient(Poco::Net::MailRecipient::PRIMARY_RECIPIENT, Recipient));
Message->setSubject(Msg.Attrs.find(SUBJECT)->second);
poco_information(Logger(),fmt::format("Sending message to:{} from {}",Recipient,TheSender));
if(Msg.Attrs.find(TEXT) != Msg.Attrs.end()) {
std::string Content = Msg.Attrs.find(TEXT)->second;
Message.addContent(new Poco::Net::StringPartSource(Content));
Message->addContent(new Poco::Net::StringPartSource(Content));
} else {
std::string Content = Utils::LoadFile(Msg.File);
// std::cout << "Mailing " << Content << std::endl;
Types::StringPairVec Variables;
FillVariables(Msg.Attrs, Variables);
Utils::ReplaceVariables(Content, Variables);
// std::cout << "Mailing " << Content << std::endl;
Message.addContent(new Poco::Net::StringPartSource(Content));
for(const auto &format:{"html","txt"}) {
std::string Content = Utils::LoadFile(TemplateDir_ + Msg.TemplateName + "." + format );
Types::StringPairVec Variables;
FillVariables(Msg.Attrs, Variables);
Utils::ReplaceVariables(Content, Variables);
Message->addContent(
new Poco::Net::StringPartSource(Content, (strcmp(format,"html") == 0 ? "text/html" : "text/plain") ));
}
}
auto Logo = Msg.Attrs.find(LOGO);
if(Logo!=Msg.Attrs.end()) {
try {
Poco::File LogoFile(AuthService::GetLogoAssetFileName());
Poco::File LogoFile(EmailLogo_);
std::ifstream IF(LogoFile.path());
std::ostringstream OS;
Poco::StreamCopier::copyStream(IF, OS);
Message.addAttachment("logo", new Poco::Net::StringPartSource(OS.str(), "image/png"));
Message->addAttachment("logo", new Poco::Net::StringPartSource(OS.str(), "image/png"));
} catch (...) {
Logger().warning(fmt::format("Cannot add '{}' logo in email",AuthService::GetLogoAssetFileName()));
poco_warning(Logger(),fmt::format("Cannot add '{}' logo in email",AuthService::GetLogoAssetFileName()));
}
}
@@ -169,18 +184,23 @@ namespace OpenWifi {
SenderLoginUserName_,
SenderLoginPassword_
);
session.sendMessage(Message);
session.sendMessage(*Message);
session.close();
return true;
return MessageSendStatus::msg_sent;
}
catch (const Poco::Net::SMTPException &S) {
Logger().log(S);
return MessageSendStatus::msg_not_sent_but_do_not_resend;
}
catch (const Poco::Exception& E)
{
Logger().log(E);
return MessageSendStatus::msg_not_sent_but_resend;
}
catch (const std::exception &E) {
Logger().warning(fmt::format("Cannot send message to:{}, error: {}",Recipient, E.what()));
poco_warning(Logger(),fmt::format("Cannot send message to:{}, error: {}",Recipient, E.what()));
return MessageSendStatus::msg_not_sent_but_do_not_resend;
}
return false;
}
}

View File

@@ -27,7 +27,8 @@ namespace OpenWifi {
LOGO,
TEXT,
CHALLENGE_CODE,
SENDER
SENDER,
ACTION_LINK_HTML
};
static const std::map<MESSAGE_ATTRIBUTES,const std::string>
@@ -44,7 +45,8 @@ namespace OpenWifi {
{ LOGO, "LOGO"},
{ TEXT, "TEXT"},
{ CHALLENGE_CODE, "CHALLENGE_CODE"},
{ SENDER, "SENDER"}
{ SENDER, "SENDER"},
{ ACTION_LINK_HTML, "ACTION_LINK_HTML"},
};
inline const std::string & MessageAttributeToVar(MESSAGE_ATTRIBUTES Attr) {
@@ -56,6 +58,12 @@ namespace OpenWifi {
}
typedef std::map<MESSAGE_ATTRIBUTES, std::string> MessageAttributes;
enum class MessageSendStatus {
msg_sent,
msg_not_sent_but_resend,
msg_not_sent_but_do_not_resend
};
class SMTPMailerService : public SubSystemServer, Poco::Runnable {
public:
static SMTPMailerService *instance() {
@@ -67,7 +75,7 @@ namespace OpenWifi {
uint64_t Posted=0;
uint64_t LastTry=0;
uint64_t Sent=0;
Poco::File File;
std::string TemplateName;
MessageAttributes Attrs;
};
@@ -76,7 +84,7 @@ namespace OpenWifi {
void Stop() override;
bool SendMessage(const std::string &Recipient, const std::string &Name, const MessageAttributes &Attrs);
bool SendIt(const MessageEvent &Msg);
MessageSendStatus SendIt(const MessageEvent &Msg);
void LoadMyConfig();
void reinitialize(Poco::Util::Application &self) override;
bool Enabled() const { return Enabled_; }
@@ -96,6 +104,8 @@ namespace OpenWifi {
Poco::Thread SenderThr_;
std::atomic_bool Running_=false;
bool Enabled_=false;
bool UseHTML_=false;
std::string EmailLogo_{"logo.jpg"};
SMTPMailerService() noexcept:
SubSystemServer("SMTPMailer", "MAILER-SVR", "smtpmailer")

View File

@@ -13,6 +13,7 @@ namespace OpenWifi {
int StorageService::Start() {
std::lock_guard Guard(Mutex_);
poco_information(Logger(),"Starting...");
StorageClass::Start();
@@ -51,18 +52,20 @@ namespace OpenWifi {
Archivercallback_ = std::make_unique<Poco::TimerCallback<Archiver>>(Archiver_,&Archiver::onTimer);
Timer_.setStartInterval( 5 * 60 * 1000); // first run in 5 minutes
Timer_.setPeriodicInterval(1 * 60 * 60 * 1000); // 1 hours
Timer_.start(*Archivercallback_);
Timer_.start(*Archivercallback_, MicroService::instance().TimerPool());
return 0;
}
void StorageService::Stop() {
Logger().notice("Stopping.");
poco_information(Logger(),"Stopping...");
Timer_.stop();
StorageClass::Stop();
poco_information(Logger(),"Stopped...");
}
void Archiver::onTimer([[maybe_unused]] Poco::Timer &timer) {
Utils::SetThreadName("strg-arch");
Poco::Logger &logger = Poco::Logger::get("STORAGE-ARCHIVER");
logger.information("Squiggy the DB: removing old tokens.");
StorageService()->SubTokenDB().CleanExpiredTokens();

View File

@@ -6,6 +6,7 @@
#define OWSEC_TOTPCACHE_H
#include "framework/MicroService.h"
#include "seclibs/cpptotp/bytes.h"
#include "seclibs/qrcode/qrcodegen.hpp"
#include "seclibs/cpptotp/otp.h"
@@ -41,7 +42,6 @@ namespace OpenWifi {
}
std::string GenerateQRCode(const std::string &Secret, const std::string &email) {
std::string uri{
"otpauth://totp/" + Issuer_ + ":" +
email + "?secret=" + Secret + "&issuer=" + Issuer_
@@ -55,10 +55,10 @@ namespace OpenWifi {
static bool ValidateCode( const std::string &Secret, const std::string &Code, std::string & Expecting) {
uint64_t Now = OpenWifi::Now();
uint32_t p = CppTotp::totp(CppTotp::Bytes::ByteString{ (const u_char *)Secret.c_str()}, Now, 0, 30, 6);
char buffer[16];
char buffer[16]{0};
sprintf(buffer,"%06u",p);
Expecting = buffer;
return Code == buffer;
Expecting = std::string(buffer);
return Code == Expecting;
}
int Start() override {
@@ -92,26 +92,13 @@ namespace OpenWifi {
auto Secret = GenerateSecret(20, Base32Secret);
QRCode = GenerateQRCode(Base32Secret, User.email);
/*
struct Entry {
bool Subscriber=false;
uint64_t Start = 0;
uint64_t Done = 0 ;
uint64_t Verifications = 0 ;
std::string Secret;
std::string QRCode;
std::string LastCode;
};
*/
Entry E{ .Subscriber = Subscriber,
.Start = OpenWifi::Now(),
.Done = 0,
.Verifications = 0,
.Secret = Secret,
.QRCode = QRCode,
.LastCode = 0
.LastCode = ""
};
Cache_[User.id] = E;
return true;

View File

@@ -13,9 +13,10 @@
namespace OpenWifi {
static const std::string GitUCentralJSONSchemaFile{"https://raw.githubusercontent.com/blogic/ucentral-schema/main/ucentral.schema.json"};
static const std::string GitUCentralJSONSchemaFile{
"https://raw.githubusercontent.com/blogic/ucentral-schema/main/ucentral.schema.json"};
static json DefaultUCentralSchema = R"(
static json DefaultUCentralSchema = R"(
{
"$id": "https://openwrt.org/ucentral.schema.json",
@@ -43,7 +44,7 @@ namespace OpenWifi {
"switch": {
"$ref": "#/$defs/switch"
},
"radios": {
"radiosgrep": {
"type": "array",
"items": {
"$ref": "#/$defs/radio"
@@ -518,7 +519,7 @@ namespace OpenWifi {
"maximum": 4050
},
"proto": {
"decription": "The L2 vlan tag that shall be added (1q,1ad) ",
"decription": "The L2 vlan tag that shall be added (1q,1ad ) ",
"type": "string",
"enum": [
"802.1ad",
@@ -669,6 +670,47 @@ namespace OpenWifi {
}
}
},
"interface.ipv4.port-forward": {
"type": "object",
"properties": {
"protocol": {
"type": "string",
"enum": [
"tcp",
"udp",
"any"
],
"default": "any"
},
"external-port": {
"type": [
"integer",
"string"
],
"minimum": 0,
"maximum": 65535,
"format": "uc-portrange"
},
"internal-address": {
"type": "string",
"format": "ipv4",
"example": "0.0.0.120"
},
"internal-port": {
"type": [
"integer",
"string"
],
"minimum": 0,
"maximum": 65535,
"format": "uc-portrange"
}
},
"required": [
"external-port",
"internal-address"
]
},
"interface.ipv4": {
"type": "object",
"properties": {
@@ -722,6 +764,12 @@ namespace OpenWifi {
"items": {
"$ref": "#/$defs/interface.ipv4.dhcp-lease"
}
},
"port-forward": {
"type": "array",
"items": {
"$ref": "#/$defs/interface.ipv4.port-forward"
}
}
}
},
@@ -751,6 +799,96 @@ namespace OpenWifi {
}
}
},
"interface.ipv6.port-forward": {
"type": "object",
"properties": {
"protocol": {
"type": "string",
"enum": [
"tcp",
"udp",
"any"
],
"default": "any"
},
"external-port": {
"type": [
"integer",
"string"
],
"minimum": 0,
"maximum": 65535,
"format": "uc-portrange"
},
"internal-address": {
"type": "string",
"format": "ipv6",
"example": "::1234:abcd"
},
"internal-port": {
"type": [
"integer",
"string"
],
"minimum": 0,
"maximum": 65535,
"format": "uc-portrange"
}
},
"required": [
"external-port",
"internal-address"
]
},
"interface.ipv6.traffic-allow": {
"type": "object",
"properties": {
"protocol": {
"type": "string",
"default": "any"
},
"source-address": {
"type": "string",
"format": "uc-cidr6",
"example": "2001:db8:1234:abcd::/64",
"default": "::/0"
},
"source-ports": {
"type": "array",
"minItems": 1,
"items": {
"type": [
"integer",
"string"
],
"minimum": 0,
"maximum": 65535,
"format": "uc-portrange"
}
},
"destination-address": {
"type": "string",
"format": "ipv6",
"example": "::1000"
},
"destination-ports": {
"type": "array",
"minItems": 1,
"items": {
"type": [
"integer",
"string"
],
"minimum": 0,
"maximum": 65535,
"format": "uc-portrange"
}
}
},
"required": [
"destination-address"
]
},
"interface.ipv6": {
"type": "object",
"properties": {
@@ -782,6 +920,18 @@ namespace OpenWifi {
},
"dhcpv6": {
"$ref": "#/$defs/interface.ipv6.dhcpv6"
},
"port-forward": {
"type": "array",
"items": {
"$ref": "#/$defs/interface.ipv6.port-forward"
}
},
"traffic-allow": {
"type": "array",
"items": {
"$ref": "#/$defs/interface.ipv6.traffic-allow"
}
}
}
},
@@ -866,7 +1016,7 @@ namespace OpenWifi {
},
"gateway-fqdn": {
"type": "string",
"format": "fqdn",
"format": "uc-fqdn",
"default": "ucentral.splash"
},
"max-clients": {
@@ -901,6 +1051,7 @@ namespace OpenWifi {
"psk",
"psk2",
"psk-mixed",
"psk2-radius",
"wpa",
"wpa2",
"wpa-mixed",
@@ -961,6 +1112,10 @@ namespace OpenWifi {
"type": "boolean",
"default": false
},
"reduced-neighbor-reporting": {
"type": "boolean",
"default": false
},
"lci": {
"type": "string"
},
@@ -1527,6 +1682,11 @@ namespace OpenWifi {
"decription": "This option allows embedding custom vendor specific IEs inside the beacons of a BSS in AP mode.",
"type": "string"
},
"fils-discovery-interval": {
"type": "integer",
"default": 20,
"maximum": 10000
},
"encryption": {
"$ref": "#/$defs/interface.ssid.encryption"
},
@@ -2087,6 +2247,10 @@ namespace OpenWifi {
"auto-channel": {
"type": "boolean",
"default": false
},
"ipv6": {
"type": "boolean",
"default": false
}
}
},
@@ -2193,7 +2357,7 @@ namespace OpenWifi {
"properties": {
"fqdn": {
"type": "string",
"format": "fqdn"
"format": "uc-fqdn"
},
"suffix-matching": {
"type": "boolean",
@@ -2444,8 +2608,7 @@ namespace OpenWifi {
}
}
}
)"_json;
)"_json;
class custom_error_handler : public nlohmann::json_schema::basic_error_handler
{
@@ -2460,9 +2623,18 @@ namespace OpenWifi {
void ConfigurationValidator::Init() {
if(Initialized_)
return;
std::string GitSchema;
if(MicroService::instance().ConfigGetBool("ucentral.datamodel.internal",true)) {
RootSchema_ = DefaultUCentralSchema;
Logger().information("Using uCentral validation from built-in default.");
Initialized_ = Working_ = true;
return;
}
try {
if(Utils::wgets(GitUCentralJSONSchemaFile, GitSchema)) {
auto GitURI = MicroService::instance().ConfigGetString("ucentral.datamodel.uri",GitUCentralJSONSchemaFile);
if(Utils::wgets(GitURI, GitSchema)) {
RootSchema_ = json::parse(GitSchema);
Logger().information("Using uCentral validation schema from GIT.");
} else {
@@ -2528,6 +2700,17 @@ namespace OpenWifi {
return IsCIDRv4(value) || IsCIDRv6(value);
}
static inline bool IsPortRangeIsValid(const std::string &r) {
const auto ports = Poco::StringTokenizer("-",r,Poco::StringTokenizer::TOK_TRIM);
for(const auto &port:ports) {
uint32_t port_num = std::stoul(port);
if(port_num==0 || port_num>65535)
return false;
}
return true;
}
void ConfigurationValidator::my_format_checker(const std::string &format, const std::string &value)
{
static const std::regex host_regex{"^(?=.{1,254}$)((?=[a-z0-9-]{1,63}\\.)(xn--+)?[a-z0-9]+(-[a-z0-9]+)*\\.)+[a-z]{2,63}$"};
@@ -2578,6 +2761,14 @@ namespace OpenWifi {
} catch (...) {
}
throw std::invalid_argument(value + " is not a valid URI: should be something like https://hello.world.com.");
} else if(format == "uc-portrange") {
try {
if(IsPortRangeIsValid(value))
return;
throw std::invalid_argument(value + " is not a valid port range: should an integer between 1-65535 or a port range like post-port.");
} catch (...) {
}
throw std::invalid_argument(value + " is not a valid port range: should an integer between 1-65535 or a port range like post-port.");
} else if(format == "ip") {
if (IsIP(value))
return;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,169 @@
//
// Created by stephane bourque on 2022-09-29.
//
#pragma once
#include "fmt/format.h"
#include "Poco/Util/Application.h"
#include "Poco/ErrorHandler.h"
#include "Poco/Net/NetException.h"
#include "Poco/Net/SSLException.h"
#include "Poco/JSON/Template.h"
#include "Poco/Thread.h"
namespace OpenWifi {
class MicroServiceErrorHandler : public Poco::ErrorHandler {
public:
explicit MicroServiceErrorHandler(Poco::Util::Application &App) : App_(App) {
}
inline void exception(const Poco::Exception & Base) override {
try {
if(Poco::Thread::current()!= nullptr) {
t_name = Poco::Thread::current()->getName();
t_id = Poco::Thread::current()->id();
} else {
t_name = "startup_code";
t_id = 0;
}
App_.logger().log(Base);
Base.rethrow();
} catch (const Poco::Net::InvalidCertificateException &E) {
poco_error(App_.logger(), fmt::format("Poco::Net::InvalidCertificateException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::Net::InvalidSocketException &E) {
poco_error(App_.logger(), fmt::format("Poco::Net::InvalidSocketException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::Net::WebSocketException &E) {
poco_error(App_.logger(), fmt::format("Poco::Net::WebSocketException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::Net::ConnectionResetException &E) {
poco_error(App_.logger(), fmt::format("Poco::Net::ConnectionResetException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::Net::CertificateValidationException &E) {
poco_error(App_.logger(), fmt::format("Poco::Net::CertificateValidationException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::Net::SSLConnectionUnexpectedlyClosedException &E) {
poco_error(App_.logger(), fmt::format("Poco::Net::SSLConnectionUnexpectedlyClosedException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::Net::SSLContextException &E) {
poco_error(App_.logger(), fmt::format("Poco::Net::SSLContextException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::Net::SSLException &E) {
poco_error(App_.logger(), fmt::format("Poco::Net::SSLException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::Net::InvalidAddressException &E) {
poco_error(App_.logger(), fmt::format("Poco::Net::InvalidAddressException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::Net::NetException &E) {
poco_error(App_.logger(), fmt::format("Poco::Net::NetException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::IOException &E) {
poco_error(App_.logger(), fmt::format("Poco::IOException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::RuntimeException &E) {
poco_error(App_.logger(), fmt::format("Poco::RuntimeException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::JSON::JSONTemplateException &E) {
poco_error(App_.logger(), fmt::format("Poco::JSON::JSONTemplateException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::JSON::JSONException &E) {
poco_error(App_.logger(), fmt::format("Poco::JSON::JSONException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::ApplicationException &E) {
poco_error(App_.logger(), fmt::format("Poco::ApplicationException thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (const Poco::Exception &E) {
poco_error(App_.logger(), fmt::format("Poco::Exception thr_name={} thr_id={} code={} text={} msg={} what={}",
t_name, t_id, E.code(),
E.displayText(),
E.message(),
E.what()));
} catch (...) {
poco_error(App_.logger(), fmt::format("Poco:Generic thr_name={}",t_name, t_id));
}
}
inline void exception(const std::exception & E) override {
if(Poco::Thread::current()!= nullptr) {
t_name = Poco::Thread::current()->getName();
t_id = Poco::Thread::current()->id();
} else {
t_name = "startup_code";
t_id = 0;
}
poco_warning(App_.logger(), fmt::format("std::exception in {}: {} thr_id={}",
t_name,E.what(),
t_id));
}
inline void exception() override {
if(Poco::Thread::current()!= nullptr) {
t_name = Poco::Thread::current()->getName();
t_id = Poco::Thread::current()->id();
} else {
t_name = "startup_code";
t_id = 0;
}
poco_warning(App_.logger(), fmt::format("generic exception in {} thr_id={}",
t_name, t_id));
}
private:
Poco::Util::Application &App_;
std::string t_name;
int t_id=0;
};
}

View File

@@ -33,7 +33,6 @@ namespace OpenWifi {
int Start() override {
std::lock_guard Guard(Mutex_);
Logger().setLevel(Poco::Message::PRIO_INFORMATION);
Logger().notice("Starting.");
std::string DBType = MicroService::instance().ConfigGetString("storage.type");

View File

@@ -146,6 +146,10 @@ namespace OpenWifi {
WebSocketClientServer()->SendUserNotification(User,N);
}
/////
/////
/////
struct WebSocketNotificationRebootList {
std::string title,
details,
@@ -189,5 +193,58 @@ namespace OpenWifi {
WebSocketClientServer()->SendUserNotification(User,N);
}
/////
/////
/////
struct WebSocketNotificationUpgradeList {
std::string title,
details,
jobId;
std::vector<std::string> success,
skipped,
no_firmware,
not_connected;
uint64_t timeStamp=OpenWifi::Now();
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
typedef WebSocketNotification<WebSocketNotificationUpgradeList> WebSocketClientNotificationVenueUpgradeList_t;
inline void WebSocketNotificationUpgradeList::to_json(Poco::JSON::Object &Obj) const {
RESTAPI_utils::field_to_json(Obj,"title",title);
RESTAPI_utils::field_to_json(Obj,"jobId",jobId);
RESTAPI_utils::field_to_json(Obj,"success",success);
RESTAPI_utils::field_to_json(Obj,"notConnected",not_connected);
RESTAPI_utils::field_to_json(Obj,"noFirmware",no_firmware);
RESTAPI_utils::field_to_json(Obj,"skipped",skipped);
RESTAPI_utils::field_to_json(Obj,"timeStamp",timeStamp);
RESTAPI_utils::field_to_json(Obj,"details",details);
}
inline bool WebSocketNotificationUpgradeList::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
RESTAPI_utils::field_from_json(Obj,"title",title);
RESTAPI_utils::field_from_json(Obj,"jobId",jobId);
RESTAPI_utils::field_from_json(Obj,"success",success);
RESTAPI_utils::field_from_json(Obj,"notConnected",not_connected);
RESTAPI_utils::field_from_json(Obj,"noFirmware",no_firmware);
RESTAPI_utils::field_from_json(Obj,"skipped",skipped);
RESTAPI_utils::field_from_json(Obj,"timeStamp",timeStamp);
RESTAPI_utils::field_from_json(Obj,"details",details);
return true;
} catch(...) {
}
return false;
}
inline void WebSocketClientNotificationVenueUpgradeCompletionToUser( const std::string & User, WebSocketClientNotificationVenueUpgradeList_t &N) {
N.type = "venue_upgrader";
WebSocketClientServer()->SendUserNotification(User,N);
}
} // namespace OpenWifi

View File

@@ -133,6 +133,37 @@ namespace ORM {
return R;
}
inline std::string WHERE_AND_(std::string Result) {
return Result;
}
template <typename T, typename... Args> std::string WHERE_AND_(std::string Result, const char *fieldName, const T &Value, Args... args) {
if constexpr(std::is_same_v<T,std::string>)
{
if(!Value.empty()) {
if(!Result.empty())
Result += " and ";
Result += fieldName;
Result += '=';
Result += "'";
Result += Escape(Value);
Result += "'";
}
} else {
if(!Result.empty())
Result += " and ";
Result += fieldName ;
Result += '=';
Result += std::to_string(Value);
}
return WHERE_AND_(Result,args...);
}
template <typename... Args> std::string WHERE_AND(Args... args) {
std::string Result;
return WHERE_AND_(Result, args...);
}
enum SqlComparison { EQ = 0, NEQ, LT, LTE, GT, GTE };
enum SqlBinaryOp { AND = 0 , OR };

View File

@@ -5,6 +5,7 @@
#pragma once
#include <string>
#include <cstring>
#include "Poco/String.h"
#if defined(__GNUC__)
@@ -195,6 +196,8 @@ namespace OpenWifi::RESTAPI::Errors {
static const struct msg InvalidRadiusServerEntry{1142,"RADIUS Server IP address invalid or port missing."};
static const struct msg InvalidRadiusServerWeigth{1143,"RADIUS Server IP weight cannot be 0."};
static const struct msg MaximumRTTYSessionsReached{1144,"Too many RTTY sessions currently active"};
static const struct msg DeviceIsAlreadyBusy{1145,"Device is already executing a command. Please try later."};
}
@@ -427,7 +430,9 @@ namespace OpenWifi::uCentralProtocol {
static const char *RADIUSDATA = "data";
static const char *RADIUSACCT = "acct";
static const char *RADIUSAUTH = "auth";
static const char *RADIUSCOA = "coa";
static const char *RADIUSDST = "dst";
static const char *IES = "ies";
}
namespace OpenWifi::uCentralProtocol::Events {
@@ -442,6 +447,7 @@ namespace OpenWifi::uCentralProtocol::Events {
static const char *RECOVERY = "recovery";
static const char *TELEMETRY = "telemetry";
static const char *DEVICEUPDATE = "deviceupdate";
static const char *VENUE_BROADCAST = "venue_broadcast";
enum EVENT_MSG {
ET_UNKNOWN,
@@ -454,28 +460,34 @@ namespace OpenWifi::uCentralProtocol::Events {
ET_CFGPENDING,
ET_RECOVERY,
ET_DEVICEUPDATE,
ET_TELEMETRY
ET_TELEMETRY,
ET_VENUEBROADCAST
};
inline static EVENT_MSG EventFromString(const std::string & Method) {
static std::vector<std::pair<const char *,EVENT_MSG>> Values{
{ CFGPENDING , ET_CFGPENDING },
{ CONNECT, ET_CONNECT },
{ CRASHLOG, ET_CRASHLOG },
{ DEVICEUPDATE, ET_DEVICEUPDATE },
{ HEALTHCHECK, ET_HEALTHCHECK },
{ LOG, ET_LOG },
{ PING, ET_PING },
{ RECOVERY, ET_RECOVERY },
{ STATE, ET_STATE },
{ TELEMETRY, ET_TELEMETRY }
};
std::string L = Poco::toLower(Method);
auto hint = std::find_if(cbegin(Values),cend(Values),[&](const std::pair<const char *,EVENT_MSG> &v) ->bool { return strcmp(v.first,L.c_str())==0; });
if(hint == cend(Values))
return ET_UNKNOWN;
return hint->second;
inline EVENT_MSG EventFromString(const std::string & Method) {
if(strcmp(STATE,Method.c_str())==0)
return ET_STATE;
else if(strcmp(HEALTHCHECK,Method.c_str())==0)
return ET_HEALTHCHECK;
else if(strcmp(CONNECT,Method.c_str())==0)
return ET_CONNECT;
else if(strcmp(CFGPENDING,Method.c_str())==0)
return ET_CFGPENDING;
else if(strcmp(CRASHLOG,Method.c_str())==0)
return ET_CRASHLOG;
else if(strcmp(DEVICEUPDATE,Method.c_str())==0)
return ET_DEVICEUPDATE;
else if(strcmp(LOG,Method.c_str())==0)
return ET_LOG;
else if(strcmp(PING,Method.c_str())==0)
return ET_PING;
else if(strcmp(RECOVERY,Method.c_str())==0)
return ET_RECOVERY;
else if(strcmp(TELEMETRY,Method.c_str())==0)
return ET_TELEMETRY;
else if(strcmp(VENUE_BROADCAST,Method.c_str())==0)
return ET_VENUEBROADCAST;
return ET_UNKNOWN;
};
}

View File

@@ -29,7 +29,7 @@ namespace OpenWifi {
}
static std::string MakeSessionId(const std::string & token) {
return MicroService::instance().CreateHash(token);
return Utils::ComputeHash(token);
}
void LoginDB::AddLogin( const std::string & userId, const std::string & email, const std::string &token) {

View File

@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>eMail Invitation</title>
</head>
<body>
</body>
</html>

View File

@@ -0,0 +1,7 @@
Dear ${RECIPIENT_EMAIL},
You have been invited to join the OpenWifi system. Please click below and follow the instructions
${ACTION_LINK}
Thank you!

View File

@@ -2,7 +2,10 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<title>eMail Verification</title>
</head>
<body>

View File

@@ -2,7 +2,16 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<title>Password Reset</title>
<form action="${ACTION_LINK_HTML}">
<label for="fname">First name: </label>
<input type="text" id="fname" name="fname"><br><br>
<label for="lname">Last name: </label>
<input type="text" id="lname" name="lname"><br><br>
<input type="submit" value="Submit">
</form>
</head>
<body>

441
templates/sample.html Normal file
View File

@@ -0,0 +1,441 @@
<!doctype html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta name="viewport" content="width=device-width">
<title>Project Groups now available to join - Telecom Infra Project</title>
<style>
/* -------------------------------------
GLOBAL RESETS
------------------------------------- */
/*All the styling goes here*/
img {
border: none;
-ms-interpolation-mode: bicubic;
max-width: 100%;
}
body {
color: #414141;
background-color: #f6f6f6;
font-family: sans-serif;
-webkit-font-smoothing: antialiased;
font-size: 14px;
line-height: 1.4;
margin: 0;
padding: 0;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
}
table {
border-collapse: separate;
mso-table-lspace: 0pt;
mso-table-rspace: 0pt;
width: 100%;
text-align: center;
}
table td {
font-family: sans-serif;
font-size: 14px;
color: #414141;
vertical-align: top;
}
/* -------------------------------------
BODY & CONTAINER
------------------------------------- */
.body {
background-color: white;
width: 100%;
}
/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something
*/
.container {
display: block;
margin: 0 auto !important;
/* makes it centered */
max-width: 580px;
padding: 10px;
width: 580px;
}
/* This should also be a block element, so that it will fill 100% of the container */
.content {
box-sizing: border-box;
display: block;
margin: 0 auto;
max-width: 580px;
padding: 10px;
}
/* -------------------------------------
HEADER, FOOTER, MAIN
------------------------------------- */
.main {
background: #ffffff;
border-radius: 0px;
width: 600px;
max-width: 100%;
border: 1px solid #d4d4d4;
padding-left: 45px;
padding-right: 45px;
}
.wrapper {
box-sizing: border-box;
padding: 40px 20px;
}
.content-block {
padding-bottom: 10px;
padding-top: 10px;
}
.footer {
clear: both;
margin-top: 10px;
text-align: center;
width: 100%;
}
.footer td,
.footer p,
.footer span,
.footer a {
color: #999999;
font-size: 12px;
text-align: center;
}
/* -------------------------------------
TYPOGRAPHY
------------------------------------- */
h1,
h2,
h3,
h4 {
color: #414141;
font-family: sans-serif;
font-weight: 400;
line-height: 1.4;
margin: 0;
margin-bottom: 30px;
}
h2 {
font-weight: 600;
}
h1 {
font-size: 35px;
font-weight: 300;
text-align: center;
text-transform: capitalize;
}
p,
ul,
ol {
font-family: sans-serif;
font-size: 14px;
font-weight: normal;
margin: 0;
color: #414141;
margin-bottom: 15px;
}
p li,
ul li,
ol li {
list-style-position: inside;
margin-left: 5px;
color: #414141;
}
a {
color: #29818c !important;
text-decoration: none;
border-bottom: 1px solid #d2d2d2;
}
.footer a {
color: #999999 !important;
}
/* -------------------------------------
BUTTONS
------------------------------------- */
.btn {
box-sizing: border-box;
width: 100%;
}
tbody {
text-align: left;
}
.btn > tbody > tr > td {
padding-bottom: 15px;
}
.btn table {
width: auto;
}
.btn table td {
background-color: #ffffff;
border-radius: 20px;
text-align: center;
}
.btn a {
background-color: #ffffff;
border: solid 1px #489e94;
border-radius: 5px;
box-sizing: border-box;
color: #29818c;
cursor: pointer;
display: inline-block;
font-size: 14px;
font-weight: bold;
margin: 0;
padding: 12px 120px;
text-decoration: none;
font-weight:600;
text-transform: uppercase;
}
.btn-primary table td {
/* background-color: #29818c;*/
}
.btn-primary a {
transition: background-color 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,
box-shadow 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,
border 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
margin: auto;
background-color: #29818c;
border-color: #29818c;
color: #ffffff !important;
}
/* -------------------------------------
OTHER STYLES THAT MIGHT BE USEFUL
------------------------------------- */
.last {
margin-bottom: 0;
}
.first {
margin-top: 0;
}
.align-center {
text-align: center;
}
.align-right {
text-align: right;
}
.align-left {
text-align: left;
}
.clear {
clear: both;
}
.mt0 {
margin-top: 0;
}
.mb0 {
margin-bottom: 0;
}
.preheader {
color: transparent;
display: none;
height: 0;
max-height: 0;
max-width: 0;
opacity: 0;
overflow: hidden;
mso-hide: all;
visibility: hidden;
width: 0;
}
.powered-by a {
text-decoration: none;
}
hr {
border: 0;
border-bottom: 1px solid #d4d4d4;
margin: 20px 0;
}
.grayFont {
color: #999999;
}
.bold {
font-weight: 600;
}
/* -------------------------------------
RESPONSIVE AND MOBILE FRIENDLY STYLES
------------------------------------- */
@media only screen and (max-width: 620px) {
table[class="body"] h1 {
font-size: 28px !important;
margin-bottom: 10px !important;
}
table[class="body"] p,
table[class="body"] ul,
table[class="body"] ol,
table[class="body"] td,
table[class="body"] span,
table[class="body"] a {
font-size: 16px !important;
}
table[class="body"] .wrapper,
table[class="body"] .article {
padding: 10px !important;
}
table[class="body"] .content {
padding: 0 !important;
}
table[class="body"] .container {
padding: 0 !important;
width: 100% !important;
}
table[class="body"] .main {
border-left-width: 0 !important;
border-radius: 0 !important;
border-right-width: 0 !important;
}
table[class="body"] .btn table {
width: 100% !important;
}
table[class="body"] .btn a {
width: 100% !important;
}
table[class="body"] .img-responsive {
height: auto !important;
max-width: 100% !important;
width: auto !important;
}
}
/* -------------------------------------
PRESERVE THESE STYLES IN THE HEAD
------------------------------------- */
@media all {
.ExternalClass {
width: 100%;
}
.ExternalClass,
.ExternalClass p,
.ExternalClass span,
.ExternalClass font,
.ExternalClass td,
.ExternalClass div {
line-height: 100%;
}
.apple-link a {
color: inherit !important;
font-family: inherit !important;
font-size: inherit !important;
font-weight: inherit !important;
line-height: inherit !important;
text-decoration: none !important;
}
.btn-primary table td:hover {
/* background-color: rgb(50, 110, 103) !important; */
}
.btn-primary a:hover {
background-color: rgb(50, 110, 103) !important;
border-color: rgb(50, 110, 103) !important;
}
}
</style>
</head>
<body class="">
<span class="preheader"></span>
<table d="" role="presentation" border="0" cellpadding="0" cellspacing="0" class="body">
<tr>
<td>&nbsp;</td>
<td class="container">
<div class="content">
<!-- START CENTERED WHITE CONTAINER -->
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="min-width:100%">
<tbody>
<tr>
<td valign="top" style="padding:0px">
<table align="left" width="100%" border="0" cellpadding="0" cellspacing="0" style="min-width:100%">
<tbody>
<tr>
<td valign="top" style="padding-right:0px;padding-left:0px;padding-top:0;padding-bottom:0;text-align:center">
<img align="center" alt="Telecom Infra Project" src="https://gallery.mailchimp.com/d068b19c9ce4cd81f132f1844/images/f4ac7418-c41c-4aee-890b-efe01f3302cb.png"
width="600" style="max-width:100%;padding-bottom:0;display:inline!important;vertical-align:bottom">
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<table role="presentation" class="main">
<!-- START MAIN CONTENT AREA -->
<tr>
<td class="wrapper">
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr>
<td>
<h2>Project Groups now available to join - Telecom Infra Project</h2>
<p>Dear Jaspreet Sachdev,</p>
<p>
Facebook is now a member of the following TIP Project Group,
which means they are available for you to join:
</p>
<p>
<ul style="text-align: left;margin: auto;display: inline-block;">
<li><a href="https://urldefense.com/" target="_blank">Wi-Fi</a></li>
</ul>
</p>
<p>
If you would like to participate in any of these groups, you may join
by logging in to your TIP Membership Account and navigating to My Project
Groups.
</p>
</td>
</tr>
<tr>
<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="btn btn-primary">
<tbody>
<tr>
<td>
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td>
<a href="https://urldefense.com/v3/" target="_blank">Account Login</a>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</tr>
<tr>
<td>
<p>Questions? <a href="https://urldefense.com/v3/" target="_blank">Contact TIP Support</a> or email support@telecominfraproject.com.</p>
</td>
</tr>
<tr>
<td>
<p>Sincerely,</p>
<p>Telecom Infra Project</p>
</td>
</tr>
</table>
</td>
</tr>
<!-- END MAIN CONTENT AREA -->
</table>
=09
<!-- END CENTERED WHITE CONTAINER -->
<div class="footer">
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="min-width:100;margin-top:30px;">
<tbody>
<tr>
<td valign="top" style="padding:0px">
<table align="left" width="100%" border="0" cellpadding="0" cellspacing="0" style="min-width:100%">
<tbody>
<tr>
<tr>
<p style="text-align:center">
Copyright =C2=A9 2021 Telecom Infra Project, All rights reserved.
</p>
<a href="https://urldefense.com/v3/" target="_blank">www.telecominfraproject.com</a>
</tr>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</td>
<td>&nbsp;</td>
</tr>
</table>
<img src="https://mandrillapp.com/track/open.php?u=31039844&amp;id=6424f96bfb88484685c7229756fee3fb" height="1" width="1"></body>
</html>

View File

View File

View File

View File

View File

View File

View File

View File

@@ -1 +0,0 @@
null

View File

@@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
# wait-for-postgres.sh
set -e
@@ -20,7 +20,7 @@ if [ "$1" = '/openwifi/owsec' -a "$(id -u)" = '0' ]; then
if [ "$RUN_CHOWN" = 'true' ]; then
chown -R "$OWSEC_USER": "$OWSEC_ROOT" "$OWSEC_CONFIG"
fi
exec su-exec "$OWSEC_USER" "$@"
exec gosu "$OWSEC_USER" "$@"
fi
exec "$@"

View File

@@ -96,7 +96,7 @@
<div class="logo-grid">
<div></div>
<div><img src="/wwwassets/the_logo.png" alt="OpenWifi"></div>
<div><img src="/wwwassets/logo.png" alt="OpenWifi"></div>
<div></div>
</div>

View File

@@ -103,7 +103,7 @@
<div class="logo-grid">
<div></div>
<div><img src="/wwwassets/the_logo.png" alt="OpenWifi"></div>
<div><img src="/wwwassets/logo.png" alt="OpenWifi"></div>
<div></div>
</div>

View File

@@ -103,7 +103,7 @@
<div class="logo-grid">
<div></div>
<div><img src="/wwwassets/the_logo.png" alt="OpenWifi"></div>
<div><img src="/wwwassets/logo.png" alt="OpenWifi"></div>
<div></div>
</div>

View File

View File

BIN
wwwassets/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

@@ -101,7 +101,7 @@
<div class="logo-grid">
<div></div>
<div><img src="/wwwassets/the_logo.png" alt="OpenWifi"></div>
<div><img src="/wwwassets/logo.png" alt="OpenWifi"></div>
<div></div>
</div>

View File

@@ -122,7 +122,7 @@
<div class="logo-grid">
<div></div>
<div><img src="/wwwassets/the_logo.png" alt="OpenWifi"></div>
<div><img src="/wwwassets/logo.png" alt="OpenWifi"></div>
<div></div>
</div>

View File

@@ -101,7 +101,7 @@
<div class="logo-grid">
<div></div>
<div><img src="/wwwassets/the_logo.png" alt="OpenWifi"></div>
<div><img src="/wwwassets/logo.png" alt="OpenWifi"></div>
<div></div>
</div>

View File

@@ -70,7 +70,7 @@
<body>
<div class="logo-grid">
<div></div>
<div><img src="/wwwassets/the_logo.png" alt="OpenWifi"></div>
<div><img src="/wwwassets/logo.png" alt="OpenWifi"></div>
<div></div>
</div>

View File

@@ -122,7 +122,7 @@
<div class="logo-grid">
<div></div>
<div><img src="/wwwassets/the_logo.png" alt="OpenWifi"></div>
<div><img src="/wwwassets/sub_logo.png" alt="OpenWifi"></div>
<div></div>
</div>

View File

@@ -101,7 +101,7 @@
<div class="logo-grid">
<div></div>
<div><img src="/wwwassets/the_logo.png" alt="OpenWifi"></div>
<div><img src="/wwwassets/sub_logo.png" alt="OpenWifi"></div>
<div></div>
</div>

View File

@@ -69,7 +69,7 @@
<body>
<div class="logo-grid">
<div></div>
<div><img src="/wwwassets/the_logo.png" alt="OpenWifi"></div>
<div><img src="/wwwassets/sub_logo.png" alt="OpenWifi"></div>
<div></div>
</div>

View File

View File

View File

BIN
wwwassets/sub_favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB

BIN
wwwassets/sub_logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

View File

View File