Compare commits

...

77 Commits

Author SHA1 Message Date
Dmitry Dunaev
889d98a162 [WIFI-10236] Fix: image building
Signed-off-by: Dmitry Dunaev <dmitry@opsfleet.com>
2022-07-26 15:12:59 +03:00
TIP Automation User
a46401bf87 Chg: update image tag in helm values to v2.5.2 2022-07-26 10:29:52 +00:00
Dmitry Dunaev
f0be8ffdc5 [WIFI-1998] Add: gracefull ingress deprecation
Signed-off-by: Dmitry Dunaev <dmitry@opsfleet.com>
2022-07-21 17:46:15 +03:00
Dmitry Dunaev
941680c0fd Merge pull request #35 from Telecominfraproject/fix/wifi-9174--dep-charts-2.5
[WIFI-9174] Fix: switch from deprecated bitnami charts to mirrored ones
2022-06-03 19:16:39 +03:00
Dmitry Dunaev
f2b64939a3 [WIFI-9174] Fix: switch from deprecated bitnami charts to mirrored ones
Signed-off-by: Dmitry Dunaev <dmitry@opsfleet.com>
2022-06-03 19:16:09 +03:00
TIP Automation User
bf7375c8f1 Chg: update image tag in helm values to v2.5.0 2022-03-30 13:48:21 +00:00
TIP Automation User
e516e60179 Chg: update image tag in helm values to v2.5.0-RC1 2022-02-11 16:02:43 +00:00
stephb9959
7036d960e5 Merge remote-tracking branch 'origin/main' 2022-02-08 22:12:48 -08:00
stephb9959
eb8a858e05 Update framework. 2022-02-08 22:12:40 -08:00
Johann Hoffmann
4527248545 Re-structure Dockerfile and use docker-image-build composite action (#26)
Signed-off-by: Johann Hoffmann <johann.hoffmann@mailbox.org>
2022-02-08 15:15:57 +01:00
stephb9959
783b7bd32e Update framework. 2022-02-04 11:45:22 -08:00
stephb9959
76c34c5b7e Update framework. 2022-02-04 09:56:22 -08:00
stephb9959
316e51a0e2 Update framework. 2022-02-02 11:02:47 -08:00
stephb9959
f2f8edd905 Merge remote-tracking branch 'origin/main' 2022-01-31 14:25:42 -08:00
stephb9959
68389ec1e8 Update framework. 2022-01-31 14:25:34 -08:00
Dmitry Dunaev
615408acff Merge pull request #25 from Telecominfraproject/feature/wifi-6837--chart-improvements
[WIFI-6837] Chg: modify readiness to make some envs optional, switch default helm service type to ClusterIP
2022-01-28 16:04:56 +03:00
Dmitry Dunaev
0a4bd59c56 [WIFI-6837] Chg: modify readiness to make some envs optional, switch default helm service type to ClusterIP
Signed-off-by: Dmitry Dunaev <dmitry@opsfleet.com>
2022-01-28 13:54:22 +03:00
stephb9959
479e3cc96c Update framework. 2022-01-27 10:00:18 -08:00
stephb9959
0e6ce5d6d9 Update framework. 2022-01-26 23:18:52 -08:00
stephb9959
507e8dadb5 Adding kafka logging in framework. 2022-01-23 22:52:48 -08:00
stephb9959
3e72a41686 Adding kafka logging in framework. 2022-01-23 10:25:28 -08:00
stephb9959
50050fe16d Merge remote-tracking branch 'origin/main' 2022-01-20 22:55:40 -08:00
stephb9959
3344f5bb13 Adding kafka logging in framework. 2022-01-20 22:55:33 -08:00
Johann Hoffmann
b4ab5192d3 [WIFI-5775] Run SDK tests on a PR level (#19)
* Trigger testing with Docker Compose deployment

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

* Switch to trigger-workflow-and-wait community Github action

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

* Switch to latest version

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

* Use trigger-workflow-and-wait composite action

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

* Pass versions as one JSON string

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

* Remove ref since PR was merged

Signed-off-by: Johann Hoffmann <johann.hoffmann@mailbox.org>
2022-01-17 17:37:11 +01:00
Johann Hoffmann
707014d698 Adapt logging configuration to newest changes
Signed-off-by: Johann Hoffmann <johann.hoffmann@mailbox.org>
2022-01-17 11:53:17 +01:00
Dmitry Dunaev
e34874f68b Merge pull request #23 from Telecominfraproject/feature/wifi-6393--add-wait-kafka-initcontainer
[WIFI-6393] Add: initContainer to wait for Kafka to be ready
2022-01-13 12:18:09 +03:00
Dmitry Dunaev
2244e9fcab [WIFI-6393] Add: initContainer to wait for Kafka to be ready
Signed-off-by: Dmitry Dunaev <dmitry@opsfleet.com>
2022-01-13 12:15:05 +03:00
stephb9959
4f4fe39edc Config & framework update 2022-01-11 23:18:18 -08:00
stephb9959
7f143c6eaf Config & framework update 2022-01-10 22:45:07 -08:00
stephb9959
f2b6339470 Config & framework update 2022-01-10 14:15:31 -08:00
stephb9959
79622fd5ca Config & framework update 2022-01-10 12:27:57 -08:00
stephb9959
090c019175 Config & framework update 2022-01-10 09:07:06 -08:00
stephb9959
c32a7bd91f Config & framework update 2022-01-09 22:39:26 -08:00
stephb9959
00fb2bab4f ORM update 2022-01-09 10:04:36 -08:00
stephb9959
b4862aa11c ORM update 2022-01-08 22:17:48 -08:00
stephb9959
f476d4711b ORM update 2022-01-06 09:31:32 -08:00
stephb9959
ad436b0a7c Fixing typo in userinfo 2022-01-05 22:21:42 -08:00
stephb9959
5f0bf8b37f Moving to proper timers. 2022-01-04 15:42:33 -08:00
stephb9959
69d42a1074 Merge remote-tracking branch 'origin/main' 2022-01-04 15:14:14 -08:00
stephb9959
69f4ac6035 Moving to proper timers. 2022-01-04 15:13:59 -08:00
Dmitry Dunaev
27aa44ac30 Merge pull request #22 from Telecominfraproject/feature/wifi-6183--cli-review
[WIFI-6183] Chg: cli review and usage enhancement
2022-01-04 14:46:39 +03:00
Dmitry Dunaev
edc855063a [WIFI-6183] Chg: cli review and usage enhancement
Signed-off-by: Dmitry Dunaev <dmitry@opsfleet.com>
2022-01-04 14:08:31 +03:00
Johann Hoffmann
be520211bf Add curl cli script to Docker image
Signed-off-by: Johann Hoffmann <johann.hoffmann@mailbox.org>
2022-01-04 11:31:41 +01:00
stephb9959
506150cbee Merge remote-tracking branch 'origin/main' 2021-12-29 07:52:34 -08:00
stephb9959
64f941e9ac Moving to ORM. 2021-12-29 07:52:25 -08:00
Dmitry Dunaev
d30e1715fe Merge pull request #21 from Telecominfraproject/feature/wifi-4977--introduce-revisionHistoryLimit
[WIFI-4977] Add: helm add revisionHistoryLimit support
2021-12-23 16:27:00 +03:00
Dmitry Dunaev
be01b70d4c [WIFI-4977] Add: helm add revisionHistoryLimit support
Signed-off-by: Dmitry Dunaev <dmitry@opsfleet.com>
2021-12-23 16:05:49 +03:00
stephb9959
6f6d539a14 Framework update 2021-12-22 22:14:25 -08:00
stephb9959
6d1285cb77 Merge remote-tracking branch 'origin/main' 2021-12-22 22:02:40 -08:00
stephb9959
e170f23300 Framework update 2021-12-22 22:02:32 -08:00
Johann Hoffmann
d02a19d649 [WIFI-6170] Add OpenWifi Docker Compose deployment with PostgreSQL (#20)
* Add wait-for-postgres.sh wrapper script

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

* Copy wait-for-postgres.sh into Docker image

Signed-off-by: Johann Hoffmann <johann.hoffmann@mailbox.org>
2021-12-16 17:22:20 +01:00
stephb9959
6546c14b3e Framework update 2021-12-11 23:30:55 -08:00
stephb9959
4a80848fd9 Framework update 2021-12-10 13:21:38 -08:00
stephb9959
935139067f Framework update 2021-12-07 20:41:13 -08:00
stephb9959
e3cceeab32 .git dir fix 2021-12-07 09:31:15 -08:00
stephb9959
d061e126bc Merge remote-tracking branch 'origin/main' 2021-12-07 08:53:21 -08:00
stephb9959
7612196acc Build number fix 2021-12-07 08:53:10 -08:00
Dmitry Dunaev
7c098c7925 Add: .git dir to build image to expose git hash for version
Signed-off-by: Dmitry Dunaev <dmitry@opsfleet.com>
2021-12-07 15:47:04 +03:00
stephb9959
814e9bf781 Merge remote-tracking branch 'origin/main' 2021-12-06 07:57:12 -08:00
stephb9959
44bb657c48 Adding git hash 2021-12-06 07:57:03 -08:00
Dmitry Dunaev
fab5e85f03 [WIFI-5840] Chg: failureThreshold for readiness_check up to 3
Signed-off-by: Dmitry Dunaev <dmitry@opsfleet.com>
2021-12-06 15:19:13 +03:00
stephb9959
3a7dae3855 Framework update 2021-12-05 10:55:05 -08:00
stephb9959
f9b14c7723 Framework update 2021-12-05 10:41:56 -08:00
stephb9959
53e2caa3cb Framework update 2021-12-05 10:19:17 -08:00
stephb9959
fcb67912b0 Merge remote-tracking branch 'origin/main'
# Conflicts:
#	build
2021-12-05 10:08:51 -08:00
stephb9959
76376ec7c0 Framework update 2021-12-05 10:08:23 -08:00
stephb9959
31e3b5e606 Fixing Postgresql bool 2021-12-04 22:14:03 -08:00
stephb9959
266570f7d0 Framework update 2021-11-30 20:44:21 -08:00
stephb9959
8414e0386a Framework update 2021-11-30 10:26:24 -08:00
stephb9959
993405851a Merge remote-tracking branch 'origin/main' 2021-11-21 23:36:37 -08:00
stephb9959
7e0da73c54 Adding the ability to remove a device from the history and the data table. 2021-11-21 23:36:27 -08:00
Dmitry Dunaev
cd93e29a99 [WIFI-4860] Chg: apply enforce-jira-issue-key only to PRs to release branches 2021-11-19 16:24:15 +03:00
Dmitry Dunaev
049cb888c1 Merge pull request #18 from Telecominfraproject/feature/wifi-4860--add-ensure-jira-issue-key-workflow
[WIFI-4860] Add: enforce-jira-issue-key workflow
2021-11-19 15:50:05 +03:00
Dmitry Dunaev
0495bf88e8 [WIFI-4860] Add: enforce-jira-issue-key workflow
Signed-off-by: Dmitry Dunaev <dmitry@opsfleet.com>
2021-11-19 13:19:13 +03:00
stephb9959
95d8ef42ae Fixing DB offset/limit computation. 2021-11-17 15:52:29 -08:00
stephb9959
d057bacd9c Framework update 2021-11-17 07:54:37 -08:00
stephb9959
b87ee360e5 Framework update 2021-11-16 22:10:35 -08:00
87 changed files with 4106 additions and 2408 deletions

View File

@@ -25,41 +25,46 @@ jobs:
DOCKER_REGISTRY_URL: tip-tip-wlan-cloud-ucentral.jfrog.io DOCKER_REGISTRY_URL: tip-tip-wlan-cloud-ucentral.jfrog.io
DOCKER_REGISTRY_USERNAME: ucentral DOCKER_REGISTRY_USERNAME: ucentral
steps: steps:
- uses: actions/checkout@v2 - name: Checkout actions repo
uses: actions/checkout@v2
- name: Build Docker image
run: docker build -t wlan-cloud-owfms:${{ github.sha }} .
- name: Tag Docker image
run: |
TAGS="${{ github.sha }}"
if [[ ${GITHUB_REF} == "refs/heads/"* ]]
then
CURRENT_TAG=$(echo ${GITHUB_REF#refs/heads/} | tr '/' '-')
TAGS="$TAGS $CURRENT_TAG"
else
if [[ ${GITHUB_REF} == "refs/tags/"* ]]
then
CURRENT_TAG=$(echo ${GITHUB_REF#refs/tags/} | tr '/' '-')
TAGS="$TAGS $CURRENT_TAG"
else # PR build
CURRENT_TAG=$(echo ${GITHUB_HEAD_REF#refs/heads/} | tr '/' '-')
TAGS="$TAGS $CURRENT_TAG"
fi
fi
echo "Result tags: $TAGS"
for tag in $TAGS; do
docker tag wlan-cloud-owfms:${{ github.sha }} ${{ env.DOCKER_REGISTRY_URL }}/owfms:$tag
done
- name: Log into Docker registry
if: startsWith(github.ref, 'refs/tags/') || startsWith(github.ref, 'refs/pull/') || github.ref == 'refs/heads/main'
uses: docker/login-action@v1
with: with:
registry: ${{ env.DOCKER_REGISTRY_URL }} repository: Telecominfraproject/.github
username: ${{ env.DOCKER_REGISTRY_USERNAME }} path: github
password: ${{ secrets.DOCKER_REGISTRY_PASSWORD }}
- name: Push Docker images - name: Build and push Docker image
if: startsWith(github.ref, 'refs/tags/') || startsWith(github.ref, 'refs/pull/') || github.ref == 'refs/heads/main' uses: ./github/composite-actions/docker-image-build
with:
image_name: owfms
registry: tip-tip-wlan-cloud-ucentral.jfrog.io
registry_user: ucentral
registry_password: ${{ secrets.DOCKER_REGISTRY_PASSWORD }}
trigger-testing:
if: startsWith(github.ref, 'refs/pull/')
runs-on: ubuntu-latest
needs: docker
steps:
- name: Get base branch name and set as output
id: get_base_branch
run: | run: |
docker images | grep ${{ env.DOCKER_REGISTRY_URL }}/owfms | awk -F ' ' '{print $1":"$2}' | xargs -I {} docker push {} echo ::set-output name=branch::$(echo ${GITHUB_BASE_REF##*/})
echo ::set-output name=owgw_branch::$(echo ${GITHUB_BASE_REF##*/} | sed 's/main/master/g')
- name: Checkout actions repo
uses: actions/checkout@v2
with:
repository: Telecominfraproject/.github
path: github
- name: Trigger testing of OpenWifi Docker Compose deployment and wait for result
uses: ./github/composite-actions/trigger-workflow-and-wait
env:
BASE_BRANCH: ${{ steps.get_base_branch.outputs.branch }}
OWGW_BASE_BRANCH: ${{ steps.get_base_branch.outputs.owgw_branch }}
with:
owner: Telecominfraproject
repo: wlan-testing
workflow: ow_docker-compose.yml
token: ${{ secrets.WLAN_TESTING_PAT }}
ref: master
inputs: '{"owgw_version": "${{ env.OWGW_BASE_BRANCH }}", "owgwui_version": "${{ env.BASE_BRANCH }}", "owsec_version": "${{ env.BASE_BRANCH }}", "owfms_version": "${{ github.sha }}", "owprov_version": "main", "owprovui_version": "main"}'

View File

@@ -0,0 +1,24 @@
name: Ensure Jira issue is linked
on:
pull_request:
types: [opened, edited, reopened, synchronize]
branches:
- 'release/*'
jobs:
check_for_issue_key:
runs-on: ubuntu-latest
steps:
- name: Checkout actions repo
uses: actions/checkout@v2
with:
repository: Telecominfraproject/.github
path: github
- name: Run JIRA check
uses: ./github/composite-actions/enforce-jira-issue-key
with:
jira_base_url: ${{ secrets.TIP_JIRA_URL }}
jira_user_email: ${{ secrets.TIP_JIRA_USER_EMAIL }}
jira_api_token: ${{ secrets.TIP_JIRA_API_TOKEN }}

3
.gitignore vendored
View File

@@ -20,5 +20,4 @@ _deps
*.zip *.zip
result.json result.json
pidfile pidfile
test_scripts/curl/result.json

View File

@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.13) cmake_minimum_required(VERSION 3.13)
project(owfms VERSION 2.4.0) project(owfms VERSION 2.5.0)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
@@ -15,18 +15,32 @@ if(UNIX AND NOT APPLE)
endif() endif()
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/build) if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/build)
file(READ build BUILD_NUM) file(READ ${CMAKE_CURRENT_SOURCE_DIR}/build BUILD_NUM)
if(BUILD_INCREMENT) if(BUILD_INCREMENT)
MATH(EXPR BUILD_NUM "${BUILD_NUM}+1") MATH(EXPR BUILD_NUM "${BUILD_NUM}+1")
file(WRITE build ${BUILD_NUM}) file(WRITE ${CMAKE_CURRENT_SOURCE_DIR}/build ${BUILD_NUM})
endif() endif()
else() else()
set(BUILD_NUM 1) set(BUILD_NUM 1)
file(WRITE build ${BUILD_NUM}) file(WRITE ${CMAKE_CURRENT_SOURCE_DIR}/build ${BUILD_NUM})
endif() endif()
find_package(Git QUIET)
if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git")
execute_process(COMMAND ${GIT_EXECUTABLE} describe --always --tags
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
RESULT_VARIABLE GIT_RESULT
OUTPUT_VARIABLE GIT_HASH)
if(NOT GIT_RESULT EQUAL "0")
message(FATAL_ERROR "git describe --always --tags failed with ${GIT_RESULT}")
endif()
string(REGEX REPLACE "\n$" "" GIT_HASH "${GIT_HASH}")
endif()
add_definitions(-DAWS_CUSTOM_MEMORY_MANAGEMENT)
set(BUILD_SHARED_LIBS 1) set(BUILD_SHARED_LIBS 1)
add_definitions(-DAPP_VERSION="${CMAKE_PROJECT_VERSION}" -DBUILD_NUMBER="${BUILD_NUM}" -DAWS_CUSTOM_MEMORY_MANAGEMENT) add_definitions(-DAWS_CUSTOM_MEMORY_MANAGEMENT)
set(Boost_USE_STATIC_LIBS OFF) set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_MULTITHREADED ON) set(Boost_USE_MULTITHREADED ON)
@@ -48,8 +62,11 @@ endif()
include_directories(/usr/local/include /usr/local/opt/openssl/include src include/kafka /usr/local/opt/mysql-client/include) include_directories(/usr/local/include /usr/local/opt/openssl/include src include/kafka /usr/local/opt/mysql-client/include)
configure_file(src/ow_version.h.in ${PROJECT_SOURCE_DIR}/src/ow_version.h @ONLY)
add_executable( owfms add_executable( owfms
build build
src/ow_version.h.in
src/framework/CountryCodes.h src/framework/CountryCodes.h
src/framework/KafkaTopics.h src/framework/KafkaTopics.h
src/framework/MicroService.h src/framework/MicroService.h
@@ -70,12 +87,7 @@ add_executable( owfms
src/RESTAPI/RESTAPI_connectedDevicesHandler.cpp src/RESTAPI/RESTAPI_connectedDevicesHandler.h src/RESTAPI/RESTAPI_connectedDevicesHandler.cpp src/RESTAPI/RESTAPI_connectedDevicesHandler.h
src/RESTAPI/RESTAPI_deviceReportHandler.cpp src/RESTAPI/RESTAPI_deviceReportHandler.h src/RESTAPI/RESTAPI_deviceReportHandler.cpp src/RESTAPI/RESTAPI_deviceReportHandler.h
src/RESTAPI/RESTAPI_connectedDeviceHandler.cpp src/RESTAPI/RESTAPI_connectedDeviceHandler.h src/RESTAPI/RESTAPI_connectedDeviceHandler.cpp src/RESTAPI/RESTAPI_connectedDeviceHandler.h
src/storage/storage_tables.cpp src/RESTAPI/RESTAPI_Routers.cpp
src/storage/storage_firmwares.cpp
src/storage/storage_firmwares.h src/storage/storage_history.cpp
src/storage/storage_history.h src/storage/storage_deviceTypes.cpp
src/storage/storage_deviceInfo.cpp src/storage/storage_deviceInfo.h
src/APIServers.cpp
src/Dashboard.cpp src/Dashboard.h src/Dashboard.cpp src/Dashboard.h
src/Daemon.cpp src/Daemon.h src/Daemon.cpp src/Daemon.h
src/StorageService.cpp src/StorageService.h src/StorageService.cpp src/StorageService.h
@@ -87,7 +99,10 @@ add_executable( owfms
src/FirmwareCache.cpp src/FirmwareCache.h src/FirmwareCache.cpp src/FirmwareCache.h
src/SDK/Prov_SDK.cpp src/SDK/Prov_SDK.h src/SDK/Prov_SDK.cpp src/SDK/Prov_SDK.h
src/AutoUpdater.cpp src/AutoUpdater.h src/SDK/GW_SDK.cpp src/SDK/GW_SDK.h src/AutoUpdater.cpp src/AutoUpdater.h src/SDK/GW_SDK.cpp src/SDK/GW_SDK.h
) src/NewCommandHandler.cpp src/NewCommandHandler.h
src/storage/orm_history.cpp src/storage/orm_history.h
src/storage/orm_firmwares.cpp src/storage/orm_firmwares.h
src/storage/orm_deviceInfo.cpp src/storage/orm_deviceInfo.h)
target_link_libraries(owfms PUBLIC target_link_libraries(owfms PUBLIC
${Poco_LIBRARIES} ${MySQL_LIBRARIES} ${Poco_LIBRARIES} ${MySQL_LIBRARIES}

View File

@@ -1,36 +1,16 @@
FROM alpine AS builder FROM alpine:3.15 AS build-base
RUN apk add --update --no-cache \ RUN apk add --update --no-cache \
openssl openssh \ make cmake g++ git \
ncurses-libs \
bash util-linux coreutils curl libcurl \
make cmake gcc g++ libstdc++ libgcc git zlib-dev \
openssl-dev boost-dev curl-dev util-linux-dev \
unixodbc-dev postgresql-dev mariadb-dev \ unixodbc-dev postgresql-dev mariadb-dev \
librdkafka-dev librdkafka-dev boost-dev openssl-dev \
zlib-dev nlohmann-json \
curl-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 RUN git clone https://github.com/stephb9959/poco /poco
RUN git clone https://github.com/stephb9959/cppkafka /cppkafka
RUN git clone https://github.com/nlohmann/json /json
RUN git clone https://github.com/pboettch/json-schema-validator /json-schema-validator
RUN git clone --recurse-submodules https://github.com/aws/aws-sdk-cpp /aws-sdk-cpp
WORKDIR /aws-sdk-cpp
RUN mkdir cmake-build
WORKDIR cmake-build
RUN cmake .. -DBUILD_ONLY="s3" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_FLAGS="-Wno-error=stringop-overflow -Wno-error=uninitialized" \
-DAUTORUN_UNIT_TESTS=OFF
RUN cmake --build . --config Release -j8
RUN cmake --build . --target install
WORKDIR /cppkafka
RUN mkdir cmake-build
WORKDIR cmake-build
RUN cmake ..
RUN cmake --build . --config Release -j8
RUN cmake --build . --target install
WORKDIR /poco WORKDIR /poco
RUN mkdir cmake-build RUN mkdir cmake-build
@@ -39,12 +19,22 @@ RUN cmake ..
RUN cmake --build . --config Release -j8 RUN cmake --build . --config Release -j8
RUN cmake --build . --target install RUN cmake --build . --target install
WORKDIR /json 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
WORKDIR /cppkafka
RUN mkdir cmake-build RUN mkdir cmake-build
WORKDIR cmake-build WORKDIR cmake-build
RUN cmake .. RUN cmake ..
RUN make RUN cmake --build . --config Release -j8
RUN make install 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
WORKDIR /json-schema-validator WORKDIR /json-schema-validator
RUN mkdir cmake-build RUN mkdir cmake-build
@@ -53,17 +43,46 @@ RUN cmake ..
RUN make RUN make
RUN make install 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
WORKDIR /aws-sdk-cpp
RUN mkdir cmake-build
WORKDIR cmake-build
RUN cmake .. -DBUILD_ONLY="sns;s3" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_FLAGS="-Wno-error=stringop-overflow -Wno-error=uninitialized" \
-DAUTORUN_UNIT_TESTS=OFF
RUN cmake --build . --config Release -j8
RUN cmake --build . --target install
FROM build-base AS owfms-build
ADD CMakeLists.txt build /owfms/ ADD CMakeLists.txt build /owfms/
ADD cmake /owfms/cmake ADD cmake /owfms/cmake
ADD src /owfms/src ADD src /owfms/src
ADD .git /owfms/.git
COPY --from=poco-build /usr/local/include /usr/local/include
COPY --from=poco-build /usr/local/lib /usr/local/lib
COPY --from=cppkafka-build /usr/local/include /usr/local/include
COPY --from=cppkafka-build /usr/local/lib /usr/local/lib
COPY --from=json-schema-validator-build /usr/local/include /usr/local/include
COPY --from=json-schema-validator-build /usr/local/lib /usr/local/lib
COPY --from=aws-sdk-cpp-build /usr/local/include /usr/local/include
COPY --from=aws-sdk-cpp-build /usr/local/lib /usr/local/lib
WORKDIR /owfms WORKDIR /owfms
RUN mkdir cmake-build RUN mkdir cmake-build
WORKDIR /owfms/cmake-build WORKDIR /owfms/cmake-build
RUN cmake .. RUN cmake .. \
-Dcrypto_LIBRARY=/usr/lib/libcrypto.so \
-DBUILD_SHARED_LIBS=ON
RUN cmake --build . --config Release -j8 RUN cmake --build . --config Release -j8
FROM alpine FROM alpine:3.15
ENV OWFMS_USER=owfms \ ENV OWFMS_USER=owfms \
OWFMS_ROOT=/owfms-data \ OWFMS_ROOT=/owfms-data \
@@ -75,20 +94,25 @@ RUN addgroup -S "$OWFMS_USER" && \
RUN mkdir /openwifi RUN mkdir /openwifi
RUN mkdir -p "$OWFMS_ROOT" "$OWFMS_CONFIG" && \ RUN mkdir -p "$OWFMS_ROOT" "$OWFMS_CONFIG" && \
chown "$OWFMS_USER": "$OWFMS_ROOT" "$OWFMS_CONFIG" chown "$OWFMS_USER": "$OWFMS_ROOT" "$OWFMS_CONFIG"
RUN apk add --update --no-cache librdkafka curl-dev mariadb-connector-c libpq unixodbc su-exec gettext ca-certificates bash jq curl
COPY --from=builder /owfms/cmake-build/owfms /openwifi/owfms RUN apk add --update --no-cache librdkafka su-exec gettext ca-certificates bash jq curl \
COPY --from=builder /cppkafka/cmake-build/src/lib/* /lib/ mariadb-connector-c libpq unixodbc postgresql-client
COPY --from=builder /poco/cmake-build/lib/* /lib/
COPY --from=builder /aws-sdk-cpp/cmake-build/aws-cpp-sdk-core/libaws-cpp-sdk-core.so /lib/ COPY readiness_check /readiness_check
COPY --from=builder /aws-sdk-cpp/cmake-build/aws-cpp-sdk-s3/libaws-cpp-sdk-s3.so /lib/ COPY test_scripts/curl/cli /cli
COPY owfms.properties.tmpl / COPY owfms.properties.tmpl /
COPY docker-entrypoint.sh / 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 \ 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.pem
COPY readiness_check /readiness_check COPY --from=owfms-build /owfms/cmake-build/owfms /openwifi/owfms
COPY --from=cppkafka-build /cppkafka/cmake-build/src/lib/* /usr/local/lib
COPY --from=poco-build /poco/cmake-build/lib/* /usr/local/lib
COPY --from=aws-sdk-cpp-build /aws-sdk-cpp/cmake-build/aws-cpp-sdk-core/libaws-cpp-sdk-core.so /usr/local/lib
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
EXPOSE 16004 17004 16104 EXPOSE 16004 17004 16104

2
build
View File

@@ -1 +1 @@
24 36

View File

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

View File

@@ -30,3 +30,13 @@ Create chart name and version as used by the chart label.
{{- define "owfms.chart" -}} {{- define "owfms.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}} {{- end -}}
{{- define "owfms.ingress.apiVersion" -}}
{{- if .Capabilities.APIVersions.Has "networking.k8s.io/v1" -}}
{{- print "networking.k8s.io/v1" -}}
{{- else if .Capabilities.APIVersions.Has "networking.k8s.io/v1beta1" -}}
{{- print "networking.k8s.io/v1beta1" -}}
{{- else -}}
{{- print "extensions/v1beta1" -}}
{{- end -}}
{{- end -}}

View File

@@ -13,6 +13,7 @@ spec:
replicas: {{ .Values.replicaCount }} replicas: {{ .Values.replicaCount }}
strategy: strategy:
type: {{ .Values.strategyType }} type: {{ .Values.strategyType }}
revisionHistoryLimit: {{ .Values.revisionHistoryLimit }}
selector: selector:
matchLabels: matchLabels:
app.kubernetes.io/name: {{ include "owfms.name" . }} app.kubernetes.io/name: {{ include "owfms.name" . }}
@@ -35,6 +36,16 @@ spec:
{{- end }} {{- end }}
spec: spec:
initContainers:
- name: wait-kafka
image: "{{ .Values.images.dockerize.repository }}:{{ .Values.images.dockerize.tag }}"
imagePullPolicy: {{ .Values.images.dockerize.pullPolicy }}
args:
- -wait
- tcp://{{ index .Values.configProperties "openwifi.kafka.brokerlist" }}
- -timeout
- 600s
containers: containers:
- name: owfms - name: owfms

View File

@@ -2,7 +2,7 @@
{{- range $ingress, $ingressValue := .Values.ingresses }} {{- range $ingress, $ingressValue := .Values.ingresses }}
{{- if $ingressValue.enabled }} {{- if $ingressValue.enabled }}
--- ---
apiVersion: extensions/v1beta1 apiVersion: {{ include "owfms.ingress.apiVersion" $root }}
kind: Ingress kind: Ingress
metadata: metadata:
name: {{ include "owfms.fullname" $root }}-{{ $ingress }} name: {{ include "owfms.fullname" $root }}-{{ $ingress }}
@@ -36,11 +36,25 @@ spec:
paths: paths:
{{- range $ingressValue.paths }} {{- range $ingressValue.paths }}
- path: {{ .path }} - path: {{ .path }}
{{- if $root.Capabilities.APIVersions.Has "networking.k8s.io/v1" }}
pathType: {{ .pathType | default "ImplementationSpecific" }}
{{- end }}
backend: backend:
{{- if $root.Capabilities.APIVersions.Has "networking.k8s.io/v1" }}
service:
name: {{ include "owfms.fullname" $root }}-{{ .serviceName }}
port:
{{- if kindIs "string" .servicePort }}
name: {{ .servicePort }}
{{- else }}
number: {{ .servicePort }}
{{- end }}
{{- else }}
serviceName: {{ include "owfms.fullname" $root }}-{{ .serviceName }} serviceName: {{ include "owfms.fullname" $root }}-{{ .serviceName }}
servicePort: {{ .servicePort }} servicePort: {{ .servicePort }}
{{- end }} {{- end }}
{{- end }} {{- end }}
{{- end }}
{{- end }} {{- end }}

View File

@@ -1,6 +1,7 @@
# System # System
replicaCount: 1 replicaCount: 1
strategyType: Recreate strategyType: Recreate
revisionHistoryLimit: 2
nameOverride: "" nameOverride: ""
fullnameOverride: "" fullnameOverride: ""
@@ -8,16 +9,20 @@ fullnameOverride: ""
images: images:
owfms: owfms:
repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owfms repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owfms
tag: main tag: v2.5.2
pullPolicy: Always pullPolicy: Always
# regcred: # regcred:
# registry: tip-tip-wlan-cloud-ucentral.jfrog.io # registry: tip-tip-wlan-cloud-ucentral.jfrog.io
# username: username # username: username
# password: password # password: password
dockerize:
repository: tip-tip-wlan-cloud-ucentral.jfrog.io/dockerize
tag: 0.16.0
pullPolicy: IfNotPresent
services: services:
owfms: owfms:
type: LoadBalancer type: ClusterIP
ports: ports:
restapi: restapi:
servicePort: 16004 servicePort: 16004
@@ -38,8 +43,6 @@ checks:
exec: exec:
command: command:
- /readiness_check - /readiness_check
failureThreshold: 1
ingresses: ingresses:
restapi: restapi:
@@ -51,6 +54,7 @@ ingresses:
- restapi.chart-example.local - restapi.chart-example.local
paths: paths:
- path: / - path: /
pathType: ImplementationSpecific
serviceName: owfms serviceName: owfms
servicePort: restapi servicePort: restapi
@@ -180,22 +184,9 @@ configProperties:
openwifi.system.uri.ui: https://localhost openwifi.system.uri.ui: https://localhost
openwifi.system.commandchannel: /tmp/app_owfms openwifi.system.commandchannel: /tmp/app_owfms
# Logging # Logging
logging.formatters.f1.class: PatternFormatter logging.type: console
logging.formatters.f1.pattern: "%Y-%m-%d %H:%M:%S %s: [%p] %t" logging.path: $OWFMS_ROOT/logs
logging.formatters.f1.times: UTC logging.level: debug
logging.channels.c1.class: ConsoleChannel
logging.channels.c1.formatter: f1
logging.channels.c2.class: FileChannel
logging.channels.c2.path: /tmp/log_owfms
logging.channels.c2.formatter.class: PatternFormatter
logging.channels.c2.formatter.pattern: "%Y-%m-%d %H:%M:%S %s: [%p] %t"
logging.channels.c2.rotation: "20 M"
logging.channels.c2.archive: timestamp
logging.channels.c2.purgeCount: 20
logging.channels.c3.class: ConsoleChannel
logging.channels.c3.pattern: "%s: [%p] %t"
logging.loggers.root.channel: c1
logging.loggers.root.level: debug
# -> Secret part # -> Secret part
# REST API # REST API

View File

@@ -2,7 +2,7 @@ openapi: 3.0.1
info: info:
title: uCentral Firmware Service API title: uCentral Firmware Service API
description: A process to manage new uCentral firmware distribution. description: A process to manage new uCentral firmware distribution.
version: 2.0.0 version: 2.5.0
license: license:
name: BSD3 name: BSD3
url: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE url: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
@@ -60,6 +60,11 @@ components:
- 6 # INTERNAL_ERROR, - 6 # INTERNAL_ERROR,
- 7 # ACCESS_DENIED, - 7 # ACCESS_DENIED,
- 8 # INVALID_TOKEN - 8 # INVALID_TOKEN
- 9 # EXPIRED_TOKEN
- 10 # RATE_LIMIT_EXCEEDED
- 11 # BAD_MFA_TRANSACTION
- 12 # MFA_FAILURE
- 13 # SECURITY_SERVICE_UNREACHABLE
ErrorDetails: ErrorDetails:
type: string type: string
ErrorDescription: ErrorDescription:

View File

@@ -35,6 +35,7 @@ openwifi.system.uri.private = https://localhost:17004
openwifi.system.uri.public = https://ucentral.dpaas.arilia.com:16004 openwifi.system.uri.public = https://ucentral.dpaas.arilia.com:16004
openwifi.system.commandchannel = /tmp/app.owfms openwifi.system.commandchannel = /tmp/app.owfms
openwifi.system.uri.ui = ucentral-ui.arilia.com openwifi.system.uri.ui = ucentral-ui.arilia.com
firmwaredb.refresh = 1800 firmwaredb.refresh = 1800
firmwaredb.maxage = 90 firmwaredb.maxage = 90
@@ -108,37 +109,9 @@ storage.type.mysql.connectiontimeout = 60
# Logging: please leave as is for now. # Logging: please leave as is for now.
# #
######################################################################## ########################################################################
logging.formatters.f1.class = PatternFormatter logging.type = file
logging.formatters.f1.pattern = %s: [%p] %t logging.path = $OWFMS_ROOT/logs
logging.formatters.f1.times = UTC logging.level = debug
logging.channels.c1.class = ConsoleChannel
logging.channels.c1.formatter = f1
# This is where the logs will be written. This path MUST exist
logging.channels.c2.class = FileChannel
logging.channels.c2.path = $OWFMS_ROOT/logs/log
logging.channels.c2.formatter.class = PatternFormatter
logging.channels.c2.formatter.pattern = %Y-%m-%d %H:%M:%S %s: [%p] %t
logging.channels.c2.rotation = 20 M
logging.channels.c2.archive = timestamp
logging.channels.c2.purgeCount = 20
logging.channels.c3.class = ConsoleChannel
logging.channels.c3.pattern = %s: [%p] %t
# External Channel
logging.loggers.root.channel = c2
logging.loggers.root.level = debug
# Inline Channel with PatternFormatter
# logging.loggers.l1.name = logger1
# logging.loggers.l1.channel.class = ConsoleChannel
# logging.loggers.l1.channel.pattern = %s: [%p] %t
# logging.loggers.l1.level = information
# SplitterChannel
# logging.channels.splitter.class = SplitterChannel
# logging.channels.splitter.channels = l1,l2
# logging.loggers.l2.name = logger2
# logging.loggers.l2.channel = splitter

View File

@@ -104,37 +104,6 @@ storage.type.mysql.connectiontimeout = 60
# Logging: please leave as is for now. # Logging: please leave as is for now.
# #
######################################################################## ########################################################################
logging.formatters.f1.class = PatternFormatter logging.type = console
logging.formatters.f1.pattern = %Y-%m-%d %H:%M:%S %s: [%p] %t logging.path = $OWFMS_ROOT/logs
logging.formatters.f1.times = UTC logging.level = debug
logging.channels.c1.class = ConsoleChannel
logging.channels.c1.formatter = f1
# This is where the logs will be written. This path MUST exist
logging.channels.c2.class = FileChannel
logging.channels.c2.path = $OWFMS_ROOT/logs/log
logging.channels.c2.formatter.class = PatternFormatter
logging.channels.c2.formatter.pattern = %Y-%m-%d %H:%M:%S %s: [%p] %t
logging.channels.c2.rotation = 20 M
logging.channels.c2.archive = timestamp
logging.channels.c2.purgeCount = 20
logging.channels.c3.class = ConsoleChannel
logging.channels.c3.pattern = %s: [%p] %t
# External Channel
logging.loggers.root.channel = c1
logging.loggers.root.level = debug
# Inline Channel with PatternFormatter
# logging.loggers.l1.name = logger1
# logging.loggers.l1.channel.class = ConsoleChannel
# logging.loggers.l1.channel.pattern = %s: [%p] %t
# logging.loggers.l1.level = information
# SplitterChannel
# logging.channels.splitter.class = SplitterChannel
# logging.channels.splitter.channels = l1,l2
# logging.loggers.l2.name = logger2
# logging.loggers.l2.channel = splitter

View File

@@ -13,6 +13,8 @@ then
exit 1 exit 1
fi fi
if [[ "${READINESS_METHOD}" == "systeminfo" ]]
then
if [[ "${OWSEC}" == "" ]] if [[ "${OWSEC}" == "" ]]
then then
echo "You must set the variable OWSEC in order to use this script. Something like" echo "You must set the variable OWSEC in order to use this script. Something like"
@@ -34,8 +36,6 @@ then
exit 1 exit 1
fi fi
if [[ "${READINESS_METHOD}" == "systeminfo" ]]
then
# Get OAuth token from OWSEC and cache it or use cached one # Get OAuth token from OWSEC and cache it or use cached one
payload="{ \"userId\" : \"$OWSEC_USERNAME\" , \"password\" : \"$OWSEC_PASSWORD\" }" payload="{ \"userId\" : \"$OWSEC_USERNAME\" , \"password\" : \"$OWSEC_PASSWORD\" }"
if [[ -f "/tmp/token" ]] if [[ -f "/tmp/token" ]]

View File

@@ -11,19 +11,22 @@
namespace OpenWifi { namespace OpenWifi {
int AutoUpdater::Start() { int AutoUpdater::Start() {
Running_ = true;
AutoUpdaterFrequency_ = MicroService::instance().ConfigGetInt("autoupdater.frequency",600);
AutoUpdaterEnabled_ = MicroService::instance().ConfigGetBool("autoupdater.enabled", false); AutoUpdaterEnabled_ = MicroService::instance().ConfigGetBool("autoupdater.enabled", false);
if(AutoUpdaterEnabled_) if(AutoUpdaterEnabled_) {
Thr_.start(*this); Running_ = false;
AutoUpdaterFrequency_ = MicroService::instance().ConfigGetInt("autoupdater.frequency",600);
AutoUpdaterCallBack_ = std::make_unique<Poco::TimerCallback<AutoUpdater>>(*this, &AutoUpdater::onTimer);
Timer_.setStartInterval(5 * 60 * 1000); // first run in 5 minutes
Timer_.setPeriodicInterval(AutoUpdaterFrequency_ * 1000);
Timer_.start(*AutoUpdaterCallBack_);
}
return 0; return 0;
} }
void AutoUpdater::Stop() { void AutoUpdater::Stop() {
Running_ = false; Running_ = false;
if(AutoUpdaterEnabled_) { if(AutoUpdaterEnabled_) {
Thr_.wakeUp(); Timer_.stop();
Thr_.join();
} }
} }
@@ -34,31 +37,28 @@ namespace OpenWifi {
Queue_.emplace_back(std::make_pair(std::move(serialNumber),std::move(DeviceType))); Queue_.emplace_back(std::make_pair(std::move(serialNumber),std::move(DeviceType)));
} }
void AutoUpdater::run() { void AutoUpdater::onTimer(Poco::Timer & timer) {
while(Running_) { Running_ = true;
Poco::Thread::trySleep(2000);
if(!Running_)
break;
std::unique_lock L(Mutex_); std::unique_lock L(Mutex_);
while(!Queue_.empty() && Running_) { while(!Queue_.empty() && Running_) {
auto Entry = Queue_.front(); auto Entry = Queue_.front();
Queue_.pop_front(); Queue_.pop_front();
try { try {
Logger_.debug(Poco::format("Preparing to upgrade %s",Entry.first)); Logger().debug(Poco::format("Preparing to upgrade %s",Entry.first));
auto CacheEntry = Cache_.find(Entry.first); auto CacheEntry = Cache_.find(Entry.first);
uint64_t Now = std::time(nullptr); uint64_t Now = std::time(nullptr);
std::string firmwareUpgrade; std::string firmwareUpgrade;
bool firmwareRCOnly;
if(CacheEntry == Cache_.end() || (CacheEntry->second.LastCheck-Now)>300) { if(CacheEntry == Cache_.end() || (CacheEntry->second.LastCheck-Now)>300) {
// get the firmware settings for that device. // get the firmware settings for that device.
SerialCache C; SerialCache C;
C.LastCheck = Now; C.LastCheck = Now;
bool firmwareRCOnly;
if(OpenWifi::SDK::Prov::GetFirmwareOptions(Entry.first, firmwareUpgrade, firmwareRCOnly)) { if(OpenWifi::SDK::Prov::GetFirmwareOptions(Entry.first, firmwareUpgrade, firmwareRCOnly)) {
Logger_.debug(Poco::format("Found firmware options for %s",Entry.first)); Logger().debug(Poco::format("Found firmware options for %s",Entry.first));
C.firmwareRCOnly = firmwareRCOnly; C.firmwareRCOnly = firmwareRCOnly;
C.firmwareUpgrade = firmwareUpgrade; C.firmwareUpgrade = firmwareUpgrade;
} else { } else {
Logger_.debug(Poco::format("Found no firmware options for %s",Entry.first)); Logger().debug(Poco::format("Found no firmware options for %s",Entry.first));
C.firmwareRCOnly = firmwareRCOnly; C.firmwareRCOnly = firmwareRCOnly;
C.firmwareUpgrade = firmwareUpgrade; C.firmwareUpgrade = firmwareUpgrade;
} }
@@ -68,7 +68,7 @@ namespace OpenWifi {
} }
if(firmwareUpgrade=="no") { if(firmwareUpgrade=="no") {
Logger_.information(Poco::format("Device %s not upgradable. Provisioning service settings.",Entry.first)); Logger().information(Poco::format("Device %s not upgradable. Provisioning service settings.",Entry.first));
continue; continue;
} }
@@ -76,29 +76,28 @@ namespace OpenWifi {
FMSObjects::Firmware fwDetails; FMSObjects::Firmware fwDetails;
auto LF = LatestFirmwareCache()->FindLatestFirmware(Entry.second, fwEntry ); auto LF = LatestFirmwareCache()->FindLatestFirmware(Entry.second, fwEntry );
if(LF) { if(LF) {
if(StorageService()->GetFirmware(fwEntry.Id,fwDetails)) { if(StorageService()->FirmwaresDB().GetFirmware(fwEntry.Id,fwDetails)) {
// send the command to upgrade this device... // send the command to upgrade this device...
Logger_.information(Poco::format("Upgrading %s to version %s", Entry.first, fwEntry.Revision)); Logger().information(Poco::format("Upgrading %s to version %s", Entry.first, fwEntry.Revision));
if(OpenWifi::SDK::GW::SendFirmwareUpgradeCommand(Entry.first,fwDetails.uri)) { if(OpenWifi::SDK::GW::SendFirmwareUpgradeCommand(Entry.first,fwDetails.uri)) {
Logger_.information(Poco::format("Upgrade command sent for %s",Entry.first)); Logger().information(Poco::format("Upgrade command sent for %s",Entry.first));
} else { } else {
Logger_.information(Poco::format("Upgrade command not sent for %s",Entry.first)); Logger().information(Poco::format("Upgrade command not sent for %s",Entry.first));
} }
} else { } else {
Logger_.information(Poco::format("Firmware for device %s (%s) cannot be found.", Entry.first, Entry.second )); Logger().information(Poco::format("Firmware for device %s (%s) cannot be found.", Entry.first, Entry.second ));
} }
} else { } else {
Logger_.information(Poco::format("Firmware for device %s (%s) cannot be found.", Entry.first, Entry.second )); Logger().information(Poco::format("Firmware for device %s (%s) cannot be found.", Entry.first, Entry.second ));
} }
} catch (...) { } catch (...) {
Logger_.information(Poco::format("Exception during auto update for device %s.", Entry.first )); Logger().information(Poco::format("Exception during auto update for device %s.", Entry.first ));
}
} }
} }
} }
void AutoUpdater::reinitialize(Poco::Util::Application &self) { void AutoUpdater::reinitialize(Poco::Util::Application &self) {
Logger_.information("Reinitializing."); Logger().information("Reinitializing.");
Reset(); Reset();
} }
} }

View File

@@ -8,9 +8,11 @@
#include "framework/MicroService.h" #include "framework/MicroService.h"
#include <deque> #include <deque>
#include "Poco/Util/Application.h" #include "Poco/Util/Application.h"
#include "Poco/Timer.h"
namespace OpenWifi { namespace OpenWifi {
class AutoUpdater : public SubSystemServer, Poco::Runnable {
class AutoUpdater : public SubSystemServer { // };, Poco::Runnable {
public: public:
struct SerialCache { struct SerialCache {
@@ -19,14 +21,13 @@ class AutoUpdater : public SubSystemServer, Poco::Runnable {
bool firmwareRCOnly=false; bool firmwareRCOnly=false;
}; };
static AutoUpdater *instance() { static auto instance() {
static AutoUpdater *instance_ = new AutoUpdater; static auto instance_ = new AutoUpdater;
return instance_; return instance_;
} }
int Start() override; int Start() override;
void Stop() override; void Stop() override;
void run() final;
void ToBeUpgraded(std::string serialNumber, std::string DeviceType); void ToBeUpgraded(std::string serialNumber, std::string DeviceType);
inline void Reset() { inline void Reset() {
std::lock_guard G(Mutex_); std::lock_guard G(Mutex_);
@@ -34,21 +35,24 @@ class AutoUpdater : public SubSystemServer, Poco::Runnable {
Queue_.clear(); Queue_.clear();
} }
void reinitialize(Poco::Util::Application &self) final; void reinitialize(Poco::Util::Application &self) final;
void onTimer(Poco::Timer & timer);
private: private:
std::atomic_bool Running_=false; std::atomic_bool Running_=false;
Poco::Thread Thr_;
std::map<std::string,SerialCache> Cache_; std::map<std::string,SerialCache> Cache_;
std::deque<std::pair<std::string,std::string>> Queue_; std::deque<std::pair<std::string,std::string>> Queue_;
uint64_t AutoUpdaterFrequency_=600; uint64_t AutoUpdaterFrequency_=600;
bool AutoUpdaterEnabled_=true; bool AutoUpdaterEnabled_=true;
Poco::Timer Timer_;
std::unique_ptr<Poco::TimerCallback<AutoUpdater>> AutoUpdaterCallBack_;
explicit AutoUpdater() noexcept: explicit AutoUpdater() noexcept:
SubSystemServer("AutoUpdater", "AUTO-UPDATER", "autoupdater") SubSystemServer("AutoUpdater", "AUTO-UPDATER", "autoupdater")
{ {
} }
}; };
inline AutoUpdater * AutoUpdater() { return AutoUpdater::instance(); } inline auto AutoUpdater() { return AutoUpdater::instance(); }
} }
#endif //OWFMS_AUTOUPDATER_H #endif //OWFMS_AUTOUPDATER_H

View File

@@ -17,6 +17,7 @@
#include "DeviceCache.h" #include "DeviceCache.h"
#include "FirmwareCache.h" #include "FirmwareCache.h"
#include "AutoUpdater.h" #include "AutoUpdater.h"
#include "NewCommandHandler.h"
namespace OpenWifi { namespace OpenWifi {
class Daemon *Daemon::instance_ = nullptr; class Daemon *Daemon::instance_ = nullptr;
@@ -35,7 +36,8 @@ namespace OpenWifi {
DeviceCache(), DeviceCache(),
NewConnectionHandler(), NewConnectionHandler(),
ManifestCreator(), ManifestCreator(),
AutoUpdater() AutoUpdater(),
NewCommandHandler()
}); });
} }
return instance_; return instance_;

View File

@@ -11,7 +11,7 @@ namespace OpenWifi {
if(LastRun_==0 || (Now-LastRun_)>120) { if(LastRun_==0 || (Now-LastRun_)>120) {
DB_.reset(); DB_.reset();
StorageService()->GenerateDeviceReport(DB_); StorageService()->DevicesDB().GenerateDeviceReport(DB_);
LastRun_ = Now; LastRun_ = Now;
} }
} }

View File

@@ -19,8 +19,8 @@ namespace OpenWifi {
class DeviceCache : public SubSystemServer { class DeviceCache : public SubSystemServer {
public: public:
static DeviceCache *instance() { static auto instance() {
static DeviceCache *instance_ = new DeviceCache; static auto instance_ = new DeviceCache;
return instance_; return instance_;
} }
@@ -40,7 +40,7 @@ namespace OpenWifi {
} }
}; };
inline DeviceCache * DeviceCache() { return DeviceCache::instance(); } inline auto DeviceCache() { return DeviceCache::instance(); }
} }

View File

@@ -17,8 +17,8 @@ namespace OpenWifi {
class FirmwareCache: public SubSystemServer { class FirmwareCache: public SubSystemServer {
public: public:
static FirmwareCache *instance() { static auto instance() {
static FirmwareCache *instance_= new FirmwareCache; static auto instance_= new FirmwareCache;
return instance_; return instance_;
} }
@@ -38,7 +38,7 @@ namespace OpenWifi {
} }
}; };
inline FirmwareCache * FirmwareCache() { return FirmwareCache::instance(); } inline auto FirmwareCache() { return FirmwareCache::instance(); }
} }

View File

@@ -8,7 +8,7 @@
namespace OpenWifi { namespace OpenWifi {
int LatestFirmwareCache::Start() { int LatestFirmwareCache::Start() {
StorageService()->PopulateLatestFirmwareCache(); StorageService()->FirmwaresDB().PopulateLatestFirmwareCache();
return 0; return 0;
} }

View File

@@ -24,8 +24,8 @@ namespace OpenWifi {
class LatestFirmwareCache : public SubSystemServer { class LatestFirmwareCache : public SubSystemServer {
public: public:
static LatestFirmwareCache *instance() { static auto instance() {
static LatestFirmwareCache *instance_ = new LatestFirmwareCache; static auto instance_ = new LatestFirmwareCache;
return instance_; return instance_;
} }
@@ -49,7 +49,7 @@ namespace OpenWifi {
} }
}; };
inline LatestFirmwareCache * LatestFirmwareCache() { return LatestFirmwareCache::instance(); } inline auto LatestFirmwareCache() { return LatestFirmwareCache::instance(); }
} }

View File

@@ -16,26 +16,15 @@
namespace OpenWifi { namespace OpenWifi {
void ManifestCreator::run() { void ManifestCreator::onTimer(Poco::Timer &timer) {
Running_ = true; Logger().information("Performing DB refresh");
bool FirstRun = true;
while(Running_) {
Poco::Thread::trySleep(FirstRun ? 10000 : DBRefresh_*1000);
if(!Running_)
break;
FirstRun = false;
Logger_.information("Performing DB refresh");
S3BucketContent BucketList; S3BucketContent BucketList;
StorageService()->RemoveOldFirmware(); StorageService()->FirmwaresDB().RemoveOldFirmware();
ReadBucket(BucketList); ReadBucket(BucketList);
if(!Running_) Logger().information(Poco::format("Found %Lu firmware entries in S3 repository.",(uint64_t)BucketList.size()));
break;
Logger_.information(Poco::format("Found %Lu firmware entries in S3 repository.",(uint64_t)BucketList.size()));
ComputeManifest(BucketList); ComputeManifest(BucketList);
AddManifestToDB(BucketList); AddManifestToDB(BucketList);
} }
}
bool ManifestCreator::ComputeManifest(S3BucketContent &BucketContent) { bool ManifestCreator::ComputeManifest(S3BucketContent &BucketContent) {
@@ -59,7 +48,7 @@ namespace OpenWifi {
Entry.Image = ParsedContent->get("image").toString(); Entry.Image = ParsedContent->get("image").toString();
auto FullNme = Name + "-upgrade.bin"; auto FullNme = Name + "-upgrade.bin";
if(FullNme!=Entry.Image) { if(FullNme!=Entry.Image) {
Logger_.error(Poco::format("MANIFEST(%s): Image name does not match manifest name (%s).",Name,Entry.Image)); Logger().error(Poco::format("MANIFEST(%s): Image name does not match manifest name (%s).",Name,Entry.Image));
Entry.Valid = false; Entry.Valid = false;
BadFormat++; BadFormat++;
continue; continue;
@@ -71,19 +60,19 @@ namespace OpenWifi {
Entry.Valid = false; Entry.Valid = false;
} }
} else { } else {
Logger_.error(Poco::format("MANIFEST(%s): Entry does not have a valid JSON manifest.",Name)); Logger().error(Poco::format("MANIFEST(%s): Entry does not have a valid JSON manifest.",Name));
MissingJson++; MissingJson++;
Entry.Valid = false; Entry.Valid = false;
} }
} catch (const Poco::Exception &E ) { } catch (const Poco::Exception &E ) {
Logger_.log(E); Logger().log(E);
} }
} }
Logger_.information(Poco::format("Accepted %Lu firmwares.", Accepted)); Logger().information(Poco::format("Accepted %Lu firmwares.", Accepted));
Logger_.information(Poco::format("Rejected %Lu too old firmwares.", Rejected)); Logger().information(Poco::format("Rejected %Lu too old firmwares.", Rejected));
Logger_.information(Poco::format("Rejected %Lu bad JSON.", BadFormat)); Logger().information(Poco::format("Rejected %Lu bad JSON.", BadFormat));
Logger_.information(Poco::format("Rejected %Lu missing JSON.", MissingJson)); Logger().information(Poco::format("Rejected %Lu missing JSON.", MissingJson));
return true; return true;
} }
@@ -98,7 +87,7 @@ namespace OpenWifi {
if(BucketEntry.URI.find("-staging-")!=std::string::npos) if(BucketEntry.URI.find("-staging-")!=std::string::npos)
continue; continue;
if(BucketEntry.Valid && !StorageService()->GetFirmwareByName(R,BucketEntry.Compatible,F)) { if(BucketEntry.Valid && !StorageService()->FirmwaresDB().GetFirmwareByName(R,BucketEntry.Compatible,F)) {
F.id = MicroService::instance().CreateUUID(); F.id = MicroService::instance().CreateUUID();
F.release = Release; F.release = Release;
F.size = BucketEntry.S3Size; F.size = BucketEntry.S3Size;
@@ -108,8 +97,8 @@ namespace OpenWifi {
F.uri = BucketEntry.URI; F.uri = BucketEntry.URI;
F.revision = BucketEntry.Revision; F.revision = BucketEntry.Revision;
F.deviceType = BucketEntry.Compatible; F.deviceType = BucketEntry.Compatible;
if(StorageService()->AddFirmware(F)) { if(StorageService()->FirmwaresDB().AddFirmware(F)) {
Logger_.information(Poco::format("Adding firmware '%s'",Release)); Logger().information(Poco::format("Adding firmware '%s'",Release));
} else { } else {
} }
} }
@@ -118,6 +107,7 @@ namespace OpenWifi {
} }
int ManifestCreator::Start() { int ManifestCreator::Start() {
Running_ = true;
S3BucketName_ = MicroService::instance().ConfigGetString("s3.bucketname"); S3BucketName_ = MicroService::instance().ConfigGetString("s3.bucketname");
S3Region_ = MicroService::instance().ConfigGetString("s3.region"); S3Region_ = MicroService::instance().ConfigGetString("s3.region");
S3Secret_ = MicroService::instance().ConfigGetString("s3.secret"); S3Secret_ = MicroService::instance().ConfigGetString("s3.secret");
@@ -135,23 +125,21 @@ namespace OpenWifi {
AwsCreds_.SetAWSAccessKeyId(S3Key_); AwsCreds_.SetAWSAccessKeyId(S3Key_);
AwsCreds_.SetAWSSecretKey(S3Secret_); AwsCreds_.SetAWSSecretKey(S3Secret_);
Worker_.start(*this); ManifestCreatorCallBack_ = std::make_unique<Poco::TimerCallback<ManifestCreator>>(*this, &ManifestCreator::onTimer);
Timer_.setStartInterval(5 * 60 * 1000); // first run in 5 minutes
Timer_.setPeriodicInterval(DBRefresh_ * 1000);
Timer_.start(*ManifestCreatorCallBack_);
return 0; return 0;
} }
void ManifestCreator::Stop() { void ManifestCreator::Stop() {
if(Running_) { if(Running_) {
Running_ = false; Running_ = false;
Worker_.wakeUp(); Timer_.stop();
Worker_.join();
} }
} }
bool ManifestCreator::Update() {
Worker_.wakeUp();
return true;
}
void ManifestCreator::CloseBucket() { void ManifestCreator::CloseBucket() {
} }
@@ -196,7 +184,7 @@ namespace OpenWifi {
while(!isDone) { while(!isDone) {
Outcome = S3Client.ListObjectsV2(Request); Outcome = S3Client.ListObjectsV2(Request);
if(!Outcome.IsSuccess()) { if(!Outcome.IsSuccess()) {
Logger_.error(Poco::format("Error while doing ListObjectsV2: %s, %s", Logger().error(Poco::format("Error while doing ListObjectsV2: %s, %s",
std::string{Outcome.GetError().GetExceptionName()}, std::string{Outcome.GetError().GetExceptionName()},
std::string{Outcome.GetError().GetMessage()})); std::string{Outcome.GetError().GetMessage()}));
return false; return false;
@@ -280,7 +268,7 @@ namespace OpenWifi {
// std::cout << "Count:" << Count << " Runs:" << Runs << std::endl; // std::cout << "Count:" << Count << " Runs:" << Runs << std::endl;
if(!Outcome.IsSuccess()) { if(!Outcome.IsSuccess()) {
Logger_.error(Poco::format("Error while doing ListObjectsV2: %s, %s", Logger().error(Poco::format("Error while doing ListObjectsV2: %s, %s",
std::string{Outcome.GetError().GetExceptionName()}, std::string{Outcome.GetError().GetExceptionName()},
std::string{Outcome.GetError().GetMessage()})); std::string{Outcome.GetError().GetMessage()}));
return false; return false;

View File

@@ -10,6 +10,7 @@
#include <aws/core/auth/AWSCredentials.h> #include <aws/core/auth/AWSCredentials.h>
#include "framework/MicroService.h" #include "framework/MicroService.h"
#include "Poco/Timer.h"
namespace OpenWifi { namespace OpenWifi {
@@ -28,17 +29,15 @@ namespace OpenWifi {
}; };
typedef std::map<const std::string, S3BucketEntry> S3BucketContent; typedef std::map<const std::string, S3BucketEntry> S3BucketContent;
class ManifestCreator : public SubSystemServer, Poco::Runnable { class ManifestCreator : public SubSystemServer {
public: public:
static ManifestCreator *instance() { static auto instance() {
static ManifestCreator *instance_ = new ManifestCreator; static auto instance_ = new ManifestCreator;
return instance_; return instance_;
} }
void run() override;
int Start() override; int Start() override;
void Stop() override; void Stop() override;
bool Update();
bool ComputeManifest(S3BucketContent & BucketContent); bool ComputeManifest(S3BucketContent & BucketContent);
bool AddManifestToDB(S3BucketContent & BucketContent); bool AddManifestToDB(S3BucketContent & BucketContent);
@@ -48,10 +47,9 @@ namespace OpenWifi {
void CloseBucket(); void CloseBucket();
void Print(const S3BucketContent &B); void Print(const S3BucketContent &B);
uint64_t MaxAge() const { return MaxAge_; } uint64_t MaxAge() const { return MaxAge_; }
void onTimer(Poco::Timer & timer);
private: private:
static ManifestCreator *instance_;
Poco::Thread Worker_;
std::atomic_bool Running_ = false; std::atomic_bool Running_ = false;
Aws::String S3BucketName_; Aws::String S3BucketName_;
Aws::String S3Region_; Aws::String S3Region_;
@@ -62,13 +60,15 @@ namespace OpenWifi {
Aws::Auth::AWSCredentials AwsCreds_; Aws::Auth::AWSCredentials AwsCreds_;
uint64_t DBRefresh_ = 30 * 60; uint64_t DBRefresh_ = 30 * 60;
uint64_t MaxAge_ = 0 ; uint64_t MaxAge_ = 0 ;
Poco::Timer Timer_;
std::unique_ptr<Poco::TimerCallback<ManifestCreator>> ManifestCreatorCallBack_;
ManifestCreator() noexcept: ManifestCreator() noexcept:
SubSystemServer("ManifestCreator", "MANIFEST-MGR", "manifestcreator") { SubSystemServer("ManifestCreator", "MANIFEST-MGR", "manifestcreator") {
} }
}; };
inline ManifestCreator * ManifestCreator() { return ManifestCreator::instance(); }; inline auto ManifestCreator() { return ManifestCreator::instance(); };
} }

86
src/NewCommandHandler.cpp Normal file
View File

@@ -0,0 +1,86 @@
//
// Created by stephane bourque on 2021-11-21.
//
#include "NewCommandHandler.h"
#include "StorageService.h"
namespace OpenWifi {
void NewCommandHandler::run() {
Running_ = true ;
while(Running_) {
Poco::Thread::trySleep(2000);
if(!Running_)
break;
while(!NewCommands_.empty()) {
if(!Running_)
break;
Types::StringPair S;
{
std::lock_guard G(Mutex_);
S = NewCommands_.front();
NewCommands_.pop();
}
try {
auto SerialNumber = S.first;
auto M = nlohmann::json::parse(S.second);
std::string EndPoint;
if(M.contains(uCentralProtocol::SYSTEM)) {
auto SystemObj = M[uCentralProtocol::SYSTEM];
if(SystemObj.contains(uCentralProtocol::HOST))
EndPoint = SystemObj[uCentralProtocol::HOST];
}
if(M.contains(uCentralProtocol::PAYLOAD)) {
auto PayloadSection = M[uCentralProtocol::PAYLOAD];
if(PayloadSection.contains("command")) {
auto Command = PayloadSection["command"];
if(Command=="delete_device") {
auto pSerialNumber = PayloadSection["payload"]["serialNumber"];
if(pSerialNumber==SerialNumber) {
Logger().debug(Poco::format("Removing device '%s' from upgrade history.",SerialNumber));
StorageService()->HistoryDB().DeleteHistory(SerialNumber);
Logger().debug(Poco::format("Removing device '%s' from device table.",SerialNumber));
StorageService()->DevicesDB().DeleteDevice(SerialNumber);
}
}
}
}
} catch (const Poco::Exception &E) {
Logger().log(E);
}
}
}
};
int NewCommandHandler::Start() {
Types::TopicNotifyFunction F = [this](std::string s1,std::string s2) { this->CommandReceived(s1,s2); };
WatcherId_ = KafkaManager()->RegisterTopicWatcher(KafkaTopics::COMMAND, F);
Worker_.start(*this);
return 0;
};
void NewCommandHandler::Stop() {
KafkaManager()->UnregisterTopicWatcher(KafkaTopics::COMMAND, WatcherId_);
Running_ = false;
Worker_.wakeUp();
Worker_.join();
};
bool NewCommandHandler::Update() {
Worker_.wakeUp();
return true;
}
void NewCommandHandler::CommandReceived( const std::string & Key, const std::string & Message) {
std::lock_guard G(Mutex_);
NewCommands_.push(std::make_pair(Key,Message));
}
}

41
src/NewCommandHandler.h Normal file
View File

@@ -0,0 +1,41 @@
//
// Created by stephane bourque on 2021-11-21.
//
#ifndef OWFMS_NEWCOMMANDHANDLER_H
#define OWFMS_NEWCOMMANDHANDLER_H
#include "framework/MicroService.h"
#include "framework/OpenWifiTypes.h"
namespace OpenWifi {
class NewCommandHandler : public SubSystemServer, Poco::Runnable {
public:
static auto instance() {
static auto instance_ = new NewCommandHandler;
return instance_;
}
void run() override;
int Start() override;
void Stop() override;
bool Update();
void CommandReceived( const std::string & Key, const std::string & Message);
private:
Poco::Thread Worker_;
std::atomic_bool Running_ = false;
int WatcherId_=0;
Types::StringPairQueue NewCommands_;
NewCommandHandler() noexcept:
SubSystemServer("NewCommandHandler", "NEWCOM-MGR", "commanmdhandler") {
}
};
inline auto NewCommandHandler() { return NewCommandHandler::instance(); };
}
#endif //OWFMS_NEWCOMMANDHANDLER_H

View File

@@ -64,15 +64,15 @@ namespace OpenWifi {
auto Revision = Storage::TrimRevision(PayloadObj->get(uCentralProtocol::FIRMWARE).toString()); auto Revision = Storage::TrimRevision(PayloadObj->get(uCentralProtocol::FIRMWARE).toString());
// std::cout << "ConnectionEvent: SerialNumber: " << SerialNumber << " DeviceType: " << DeviceType << " Revision:" << Revision << std::endl; // std::cout << "ConnectionEvent: SerialNumber: " << SerialNumber << " DeviceType: " << DeviceType << " Revision:" << Revision << std::endl;
FMSObjects::FirmwareAgeDetails FA; FMSObjects::FirmwareAgeDetails FA;
if(StorageService()->ComputeFirmwareAge(DeviceType, Revision, FA)) { if(StorageService()->FirmwaresDB().ComputeFirmwareAge(DeviceType, Revision, FA)) {
StorageService()->SetDeviceRevision(SerialNumber, Revision, DeviceType, EndPoint); StorageService()->DevicesDB().SetDeviceRevision(SerialNumber, Revision, DeviceType, EndPoint);
if(FA.age) if(FA.age)
Logger_.information(Poco::format("Device %s connection. Firmware is %s older than latest.",SerialNumber, Utils::SecondsToNiceText(FA.age))); Logger().information(Poco::format("Device %s connection. Firmware is %s older than latest.",SerialNumber, Utils::SecondsToNiceText(FA.age)));
else else
Logger_.information(Poco::format("Device %s connection. Device firmware is up to date.",SerialNumber)); Logger().information(Poco::format("Device %s connection. Device firmware is up to date.",SerialNumber));
} }
else { else {
Logger_.information(Poco::format("Device %s connection. Firmware age cannot be determined",SerialNumber)); Logger().information(Poco::format("Device %s connection. Firmware age cannot be determined",SerialNumber));
} }
if(!LatestFirmwareCache()->IsLatest(DeviceType, Revision)) { if(!LatestFirmwareCache()->IsLatest(DeviceType, Revision)) {
@@ -86,7 +86,7 @@ namespace OpenWifi {
if(DisconnectMessage->has(uCentralProtocol::SERIALNUMBER) && DisconnectMessage->has(uCentralProtocol::TIMESTAMP)) { if(DisconnectMessage->has(uCentralProtocol::SERIALNUMBER) && DisconnectMessage->has(uCentralProtocol::TIMESTAMP)) {
auto SNum = DisconnectMessage->get(uCentralProtocol::SERIALNUMBER).toString(); auto SNum = DisconnectMessage->get(uCentralProtocol::SERIALNUMBER).toString();
auto Timestamp = DisconnectMessage->get(uCentralProtocol::TIMESTAMP); auto Timestamp = DisconnectMessage->get(uCentralProtocol::TIMESTAMP);
StorageService()->SetDeviceDisconnected(SNum,EndPoint); StorageService()->DevicesDB().SetDeviceDisconnected(SNum,EndPoint);
// std::cout << "DISCONNECTION:" << SerialNumber << std::endl; // std::cout << "DISCONNECTION:" << SerialNumber << std::endl;
} }
} else if(PayloadObj->has(uCentralProtocol::PING)) { } else if(PayloadObj->has(uCentralProtocol::PING)) {
@@ -98,7 +98,7 @@ namespace OpenWifi {
auto Revision = Storage::TrimRevision(PingMessage->get(uCentralProtocol::FIRMWARE).toString()); auto Revision = Storage::TrimRevision(PingMessage->get(uCentralProtocol::FIRMWARE).toString());
auto Serial = PingMessage->get( uCentralProtocol::SERIALNUMBER).toString(); auto Serial = PingMessage->get( uCentralProtocol::SERIALNUMBER).toString();
auto DeviceType = PingMessage->get( uCentralProtocol::COMPATIBLE).toString(); auto DeviceType = PingMessage->get( uCentralProtocol::COMPATIBLE).toString();
StorageService()->SetDeviceRevision(Serial, Revision, DeviceType, EndPoint); StorageService()->DevicesDB().SetDeviceRevision(Serial, Revision, DeviceType, EndPoint);
DeviceCache()->AddToCache(Serial, DeviceType, EndPoint, Revision); DeviceCache()->AddToCache(Serial, DeviceType, EndPoint, Revision);
if(!LatestFirmwareCache()->IsLatest(DeviceType, Revision)) { if(!LatestFirmwareCache()->IsLatest(DeviceType, Revision)) {
// std::cout << "Device(ping): " << SerialNumber << " to be upgraded ... " << std::endl; // std::cout << "Device(ping): " << SerialNumber << " to be upgraded ... " << std::endl;
@@ -108,7 +108,7 @@ namespace OpenWifi {
} }
} }
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger_.log(E); Logger().log(E);
} }
} }
} }

View File

@@ -14,8 +14,8 @@ namespace OpenWifi {
class NewConnectionHandler : public SubSystemServer, Poco::Runnable { class NewConnectionHandler : public SubSystemServer, Poco::Runnable {
public: public:
static NewConnectionHandler *instance() { static auto instance() {
static NewConnectionHandler *instance_ = new NewConnectionHandler; static auto instance_ = new NewConnectionHandler;
return instance_; return instance_;
} }
@@ -38,7 +38,7 @@ namespace OpenWifi {
} }
}; };
inline NewConnectionHandler * NewConnectionHandler() { return NewConnectionHandler::instance(); }; inline auto NewConnectionHandler() { return NewConnectionHandler::instance(); };
} }
#endif //UCENTRALFMS_NEWCONNECTIONHANDLER_H #endif //UCENTRALFMS_NEWCONNECTIONHANDLER_H

View File

@@ -14,8 +14,8 @@
namespace OpenWifi { namespace OpenWifi {
Poco::Net::HTTPRequestHandler * RESTAPI_external_server(const char *Path, RESTAPIHandler::BindingMap &Bindings, Poco::Net::HTTPRequestHandler * RESTAPI_ExtRouter(const char *Path, RESTAPIHandler::BindingMap &Bindings,
Poco::Logger & L, RESTAPI_GenericServer & S) { Poco::Logger & L, RESTAPI_GenericServer & S, uint64_t TransactionId) {
return RESTAPI_Router< return RESTAPI_Router<
RESTAPI_firmwaresHandler, RESTAPI_firmwaresHandler,
RESTAPI_firmwareHandler, RESTAPI_firmwareHandler,
@@ -25,17 +25,17 @@ namespace OpenWifi {
RESTAPI_connectedDeviceHandler, RESTAPI_connectedDeviceHandler,
RESTAPI_historyHandler, RESTAPI_historyHandler,
RESTAPI_deviceReportHandler RESTAPI_deviceReportHandler
>(Path,Bindings,L, S); >(Path,Bindings,L, S, TransactionId);
} }
Poco::Net::HTTPRequestHandler * RESTAPI_internal_server(const char *Path, RESTAPIHandler::BindingMap &Bindings, Poco::Net::HTTPRequestHandler * RESTAPI_IntRouter(const char *Path, RESTAPIHandler::BindingMap &Bindings,
Poco::Logger & L, RESTAPI_GenericServer & S) { Poco::Logger & L, RESTAPI_GenericServer & S, uint64_t TransactionId) {
return RESTAPI_Router_I< return RESTAPI_Router_I<
RESTAPI_firmwaresHandler, RESTAPI_firmwaresHandler,
RESTAPI_firmwareHandler, RESTAPI_firmwareHandler,
RESTAPI_system_command, RESTAPI_system_command,
RESTAPI_connectedDevicesHandler, RESTAPI_connectedDevicesHandler,
RESTAPI_connectedDeviceHandler RESTAPI_connectedDeviceHandler
>(Path, Bindings, L, S); >(Path, Bindings, L, S, TransactionId);
} }
} }

View File

@@ -18,7 +18,7 @@ namespace OpenWifi {
} }
FMSObjects::DeviceConnectionInformation DevInfo; FMSObjects::DeviceConnectionInformation DevInfo;
if(StorageService()->GetDevice(SerialNumber, DevInfo)) { if(StorageService()->DevicesDB().GetDevice(SerialNumber, DevInfo)) {
Poco::JSON::Object Answer; Poco::JSON::Object Answer;
DevInfo.to_json(Answer); DevInfo.to_json(Answer);
return ReturnObject(Answer); return ReturnObject(Answer);

View File

@@ -10,12 +10,13 @@
namespace OpenWifi { namespace OpenWifi {
class RESTAPI_connectedDeviceHandler : public RESTAPIHandler { class RESTAPI_connectedDeviceHandler : public RESTAPIHandler {
public: public:
RESTAPI_connectedDeviceHandler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, bool Internal) RESTAPI_connectedDeviceHandler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, uint64_t TransactionId, bool Internal)
: RESTAPIHandler(bindings, L, : RESTAPIHandler(bindings, L,
std::vector<std::string> std::vector<std::string>
{Poco::Net::HTTPRequest::HTTP_GET, {Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_OPTIONS}, Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server, Server,
TransactionId,
Internal) {} Internal) {}
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/connectedDevice/{serialNumber}"};} static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/connectedDevice/{serialNumber}"};}

View File

@@ -15,7 +15,7 @@ namespace OpenWifi {
std::vector<FMSObjects::DeviceConnectionInformation> Devices; std::vector<FMSObjects::DeviceConnectionInformation> Devices;
Poco::JSON::Object AnswerObj; Poco::JSON::Object AnswerObj;
Poco::JSON::Array AnswerArr; Poco::JSON::Array AnswerArr;
if (StorageService()->GetDevices(QB_.Offset, QB_.Limit, Devices)) { if (StorageService()->DevicesDB().GetDevices(QB_.Offset, QB_.Limit, Devices)) {
for (const auto &i:Devices) { for (const auto &i:Devices) {
Poco::JSON::Object Obj; Poco::JSON::Object Obj;
i.to_json(Obj); i.to_json(Obj);

View File

@@ -11,12 +11,13 @@
namespace OpenWifi { namespace OpenWifi {
class RESTAPI_connectedDevicesHandler : public RESTAPIHandler { class RESTAPI_connectedDevicesHandler : public RESTAPIHandler {
public: public:
RESTAPI_connectedDevicesHandler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, bool Internal) RESTAPI_connectedDevicesHandler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, uint64_t TransactionId, bool Internal)
: RESTAPIHandler(bindings, L, : RESTAPIHandler(bindings, L,
std::vector<std::string> std::vector<std::string>
{Poco::Net::HTTPRequest::HTTP_GET, {Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_OPTIONS}, Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server, Server,
TransactionId,
Internal) {} Internal) {}
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/connectedDevices"};} static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/connectedDevices"};}
void DoGet() final; void DoGet() final;

View File

@@ -10,12 +10,13 @@
namespace OpenWifi { namespace OpenWifi {
class RESTAPI_deviceReportHandler : public RESTAPIHandler { class RESTAPI_deviceReportHandler : public RESTAPIHandler {
public: public:
RESTAPI_deviceReportHandler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, bool Internal) RESTAPI_deviceReportHandler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, uint64_t TransactionId, bool Internal)
: RESTAPIHandler(bindings, L, : RESTAPIHandler(bindings, L,
std::vector<std::string> std::vector<std::string>
{Poco::Net::HTTPRequest::HTTP_GET, {Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_OPTIONS}, Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server, Server,
TransactionId,
Internal) {} Internal) {}
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/deviceReport"};} static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/deviceReport"};}
void DoGet() final; void DoGet() final;

View File

@@ -11,16 +11,16 @@
#include "framework/RESTAPI_protocol.h" #include "framework/RESTAPI_protocol.h"
#include "framework/RESTAPI_errors.h" #include "framework/RESTAPI_errors.h"
namespace OpenWifi { namespace OpenWifi {
void RESTAPI_firmwareAgeHandler::DoGet() { void RESTAPI_firmwareAgeHandler::DoGet() {
if (!QB_.Select.empty()) { if (!QB_.Select.empty()) {
Poco::JSON::Array Objects; Poco::JSON::Array Objects;
std::vector<std::string> Numbers = Utils::Split(QB_.Select); for (auto &i : SelectedRecords()) {
for (auto &i : Numbers) {
DeviceCacheEntry E; DeviceCacheEntry E;
if (DeviceCache()->GetDevice(i, E)) { if (DeviceCache()->GetDevice(i, E)) {
FMSObjects::FirmwareAgeDetails FA; FMSObjects::FirmwareAgeDetails FA;
if(StorageService()->ComputeFirmwareAge(E.deviceType,E.revision,FA)) { if(StorageService()->FirmwaresDB().ComputeFirmwareAge(E.deviceType,E.revision,FA)) {
Poco::JSON::Object O; Poco::JSON::Object O;
FA.to_json(O); FA.to_json(O);
O.set(uCentralProtocol::SERIALNUMBER,i); O.set(uCentralProtocol::SERIALNUMBER,i);
@@ -50,7 +50,7 @@ namespace OpenWifi {
Revision = Storage::TrimRevision(Revision); Revision = Storage::TrimRevision(Revision);
FMSObjects::FirmwareAgeDetails FA; FMSObjects::FirmwareAgeDetails FA;
if (StorageService()->ComputeFirmwareAge(DeviceType, Revision, FA)) { if (StorageService()->FirmwaresDB().ComputeFirmwareAge(DeviceType, Revision, FA)) {
Poco::JSON::Object Answer; Poco::JSON::Object Answer;
FA.to_json(Answer); FA.to_json(Answer);

View File

@@ -10,12 +10,13 @@
namespace OpenWifi { namespace OpenWifi {
class RESTAPI_firmwareAgeHandler : public RESTAPIHandler { class RESTAPI_firmwareAgeHandler : public RESTAPIHandler {
public: public:
RESTAPI_firmwareAgeHandler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, bool Internal) RESTAPI_firmwareAgeHandler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, uint64_t TransactionId, bool Internal)
: RESTAPIHandler(bindings, L, : RESTAPIHandler(bindings, L,
std::vector<std::string> std::vector<std::string>
{Poco::Net::HTTPRequest::HTTP_GET, {Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_OPTIONS}, Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server, Server,
TransactionId,
Internal) {} Internal) {}
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/firmwareAge"};} static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/firmwareAge"};}
void DoGet() final; void DoGet() final;

View File

@@ -19,7 +19,7 @@ namespace OpenWifi {
return BadRequest(RESTAPI::Errors::InvalidJSONDocument); return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
} }
F.id = MicroService::instance().CreateUUID(); F.id = MicroService::instance().CreateUUID();
if(StorageService()->AddFirmware(F)) { if(StorageService()->FirmwaresDB().AddFirmware(F)) {
Poco::JSON::Object Answer; Poco::JSON::Object Answer;
F.to_json(Answer); F.to_json(Answer);
return ReturnObject(Answer); return ReturnObject(Answer);
@@ -36,7 +36,7 @@ namespace OpenWifi {
} }
FMSObjects::Firmware F; FMSObjects::Firmware F;
if (StorageService()->GetFirmware(UUID, F)) { if (StorageService()->FirmwaresDB().GetFirmware(UUID, F)) {
Poco::JSON::Object Object; Poco::JSON::Object Object;
F.to_json(Object); F.to_json(Object);
return ReturnObject(Object); return ReturnObject(Object);
@@ -51,7 +51,7 @@ namespace OpenWifi {
return BadRequest(RESTAPI::Errors::MissingUUID); return BadRequest(RESTAPI::Errors::MissingUUID);
} }
if (StorageService()->DeleteFirmware(UUID)) { if (StorageService()->FirmwaresDB().DeleteFirmware(UUID)) {
return OK(); return OK();
} }
BadRequest(RESTAPI::Errors::CouldNotBeDeleted); BadRequest(RESTAPI::Errors::CouldNotBeDeleted);
@@ -64,7 +64,7 @@ namespace OpenWifi {
} }
FMSObjects::Firmware F; FMSObjects::Firmware F;
if(!StorageService()->GetFirmware(UUID, F)) { if(!StorageService()->FirmwaresDB().GetFirmware(UUID, F)) {
return NotFound(); return NotFound();
} }
@@ -85,7 +85,7 @@ namespace OpenWifi {
} }
} }
if(StorageService()->UpdateFirmware(UUID, F)) { if(StorageService()->FirmwaresDB().UpdateFirmware(UUID, F)) {
Poco::JSON::Object Answer; Poco::JSON::Object Answer;
F.to_json(Answer); F.to_json(Answer);
return ReturnObject(Answer); return ReturnObject(Answer);

View File

@@ -10,7 +10,7 @@
namespace OpenWifi { namespace OpenWifi {
class RESTAPI_firmwareHandler : public RESTAPIHandler { class RESTAPI_firmwareHandler : public RESTAPIHandler {
public: public:
RESTAPI_firmwareHandler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, bool Internal) RESTAPI_firmwareHandler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, uint64_t TransactionId, bool Internal)
: RESTAPIHandler(bindings, L, : RESTAPIHandler(bindings, L,
std::vector<std::string> std::vector<std::string>
{Poco::Net::HTTPRequest::HTTP_GET, {Poco::Net::HTTPRequest::HTTP_GET,
@@ -19,6 +19,7 @@ namespace OpenWifi {
Poco::Net::HTTPRequest::HTTP_DELETE, Poco::Net::HTTPRequest::HTTP_DELETE,
Poco::Net::HTTPRequest::HTTP_OPTIONS}, Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server, Server,
TransactionId,
Internal) {} Internal) {}
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/firmware/{id}"};} static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/firmware/{id}"};}
void DoGet() final; void DoGet() final;

View File

@@ -47,7 +47,7 @@ namespace OpenWifi {
} }
FMSObjects::Firmware F; FMSObjects::Firmware F;
if(StorageService()->GetFirmware(Entry.Id,F)) { if(StorageService()->FirmwaresDB().GetFirmware(Entry.Id,F)) {
Poco::JSON::Object Answer; Poco::JSON::Object Answer;
F.to_json(Answer); F.to_json(Answer);
return ReturnObject(Answer); return ReturnObject(Answer);
@@ -55,7 +55,7 @@ namespace OpenWifi {
return NotFound(); return NotFound();
} else { } else {
std::vector<FMSObjects::Firmware> List; std::vector<FMSObjects::Firmware> List;
if (StorageService()->GetFirmwares(QB_.Offset, QB_.Limit, DeviceType, List)) { if (StorageService()->FirmwaresDB().GetFirmwares(QB_.Offset, QB_.Limit, DeviceType, List)) {
Poco::JSON::Array ObjectArray; Poco::JSON::Array ObjectArray;
for (const auto &i:List) { for (const auto &i:List) {
if(IdOnly) { if(IdOnly) {
@@ -78,7 +78,7 @@ namespace OpenWifi {
std::vector<FMSObjects::Firmware> List; std::vector<FMSObjects::Firmware> List;
Poco::JSON::Array ObjectArray; Poco::JSON::Array ObjectArray;
Poco::JSON::Object Answer; Poco::JSON::Object Answer;
if (StorageService()->GetFirmwares(QB_.Offset, QB_.Limit, DeviceType, List)) { if (StorageService()->FirmwaresDB().GetFirmwares(QB_.Offset, QB_.Limit, DeviceType, List)) {
for (const auto &i:List) { for (const auto &i:List) {
if(IdOnly) { if(IdOnly) {
ObjectArray.add(i.id); ObjectArray.add(i.id);

View File

@@ -10,12 +10,13 @@
namespace OpenWifi { namespace OpenWifi {
class RESTAPI_firmwaresHandler : public RESTAPIHandler { class RESTAPI_firmwaresHandler : public RESTAPIHandler {
public: public:
RESTAPI_firmwaresHandler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, bool Internal) RESTAPI_firmwaresHandler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, uint64_t TransactionId, bool Internal)
: RESTAPIHandler(bindings, L, : RESTAPIHandler(bindings, L,
std::vector<std::string> std::vector<std::string>
{Poco::Net::HTTPRequest::HTTP_GET, {Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_OPTIONS}, Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server, Server,
TransactionId,
Internal) {} Internal) {}
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/firmwares"};} static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/firmwares"};}

View File

@@ -17,7 +17,7 @@ namespace OpenWifi {
} }
FMSObjects::RevisionHistoryEntryVec H; FMSObjects::RevisionHistoryEntryVec H;
if (StorageService()->GetHistory(SerialNumber, QB_.Offset, QB_.Limit, H)) { if (StorageService()->HistoryDB().GetHistory(SerialNumber, QB_.Offset, QB_.Limit, H)) {
Poco::JSON::Array A; Poco::JSON::Array A;
for (auto const &i:H) { for (auto const &i:H) {
Poco::JSON::Object O; Poco::JSON::Object O;
@@ -38,7 +38,7 @@ namespace OpenWifi {
return BadRequest(RESTAPI::Errors::IdOrSerialEmpty); return BadRequest(RESTAPI::Errors::IdOrSerialEmpty);
} }
if (!StorageService()->DeleteHistory(SerialNumber, Id)) { if (!StorageService()->HistoryDB().DeleteHistory(SerialNumber, Id)) {
return OK(); return OK();
} }
NotFound(); NotFound();

View File

@@ -11,13 +11,14 @@
namespace OpenWifi { namespace OpenWifi {
class RESTAPI_historyHandler : public RESTAPIHandler { class RESTAPI_historyHandler : public RESTAPIHandler {
public: public:
RESTAPI_historyHandler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, bool Internal) RESTAPI_historyHandler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, uint64_t TransactionId, bool Internal)
: RESTAPIHandler(bindings, L, : RESTAPIHandler(bindings, L,
std::vector<std::string> std::vector<std::string>
{Poco::Net::HTTPRequest::HTTP_GET, {Poco::Net::HTTPRequest::HTTP_GET,
Poco::Net::HTTPRequest::HTTP_DELETE, Poco::Net::HTTPRequest::HTTP_DELETE,
Poco::Net::HTTPRequest::HTTP_OPTIONS}, Poco::Net::HTTPRequest::HTTP_OPTIONS},
Server, Server,
TransactionId,
Internal) {} Internal) {}
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/revisionHistory/{serialNumber}"};} static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/revisionHistory/{serialNumber}"};}
void DoGet() final; void DoGet() final;

View File

@@ -0,0 +1,178 @@
//
// Created by stephane bourque on 2021-12-07.
//
#include "RESTAPI_CertObjects.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);
}
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;
}
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;
}
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;
}
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;
}
}
}

View File

@@ -0,0 +1,101 @@
//
// Created by stephane bourque on 2021-12-07.
//
#pragma once
#include <string>
#include "framework/MicroService.h"
#include "framework/OpenWifiTypes.h"
#include "RESTObjects/RESTAPI_SecurityObjects.h"
namespace OpenWifi {
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;
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 ;
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 ;
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;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
}
}

View File

@@ -29,7 +29,7 @@ namespace OpenWifi::FMSObjects {
std::string location; std::string location;
std::string uploader; std::string uploader;
std::string digest; std::string digest;
bool latest=false; bool latest=0;
SecurityObjects::NoteInfoVec notes; SecurityObjects::NoteInfoVec notes;
uint64_t created=0; uint64_t created=0;

View File

@@ -12,6 +12,7 @@
#include "Daemon.h" #include "Daemon.h"
#ifdef TIP_GATEWAY_SERVICE #ifdef TIP_GATEWAY_SERVICE
#include "DeviceRegistry.h" #include "DeviceRegistry.h"
#include "CapabilitiesCache.h"
#endif #endif
#include "RESTAPI_GWobjects.h" #include "RESTAPI_GWobjects.h"
@@ -26,7 +27,7 @@ namespace OpenWifi::GWObjects {
void Device::to_json(Poco::JSON::Object &Obj) const { void Device::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"serialNumber", SerialNumber); field_to_json(Obj,"serialNumber", SerialNumber);
#ifdef TIP_GATEWAY_SERVICE #ifdef TIP_GATEWAY_SERVICE
field_to_json(Obj,"deviceType", Daemon::instance()->IdentifyDevice(Compatible)); field_to_json(Obj,"deviceType", CapabilitiesCache::instance()->Get(Compatible));
#endif #endif
field_to_json(Obj,"macAddress", MACAddress); field_to_json(Obj,"macAddress", MACAddress);
field_to_json(Obj,"manufacturer", Manufacturer); field_to_json(Obj,"manufacturer", Manufacturer);
@@ -145,6 +146,7 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj,"custom", Custom); field_to_json(Obj,"custom", Custom);
field_to_json(Obj,"waitingForFile", WaitingForFile); field_to_json(Obj,"waitingForFile", WaitingForFile);
field_to_json(Obj,"attachFile", AttachDate); field_to_json(Obj,"attachFile", AttachDate);
field_to_json(Obj,"executionTime", executionTime);
} }
bool DefaultConfiguration::from_json(Poco::JSON::Object::Ptr &Obj) { bool DefaultConfiguration::from_json(Poco::JSON::Object::Ptr &Obj) {
@@ -179,7 +181,6 @@ namespace OpenWifi::GWObjects {
} }
void ConnectionState::to_json(Poco::JSON::Object &Obj) const { void ConnectionState::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"serialNumber", SerialNumber);
field_to_json(Obj,"ipAddress", Address); field_to_json(Obj,"ipAddress", Address);
field_to_json(Obj,"txBytes", TX); field_to_json(Obj,"txBytes", TX);
field_to_json(Obj,"rxBytes", RX); field_to_json(Obj,"rxBytes", RX);
@@ -190,6 +191,10 @@ namespace OpenWifi::GWObjects {
field_to_json(Obj,"lastContact", LastContact); field_to_json(Obj,"lastContact", LastContact);
field_to_json(Obj,"associations_2G", Associations_2G); field_to_json(Obj,"associations_2G", Associations_2G);
field_to_json(Obj,"associations_5G", Associations_5G); field_to_json(Obj,"associations_5G", Associations_5G);
field_to_json(Obj,"webSocketClients", webSocketClients);
field_to_json(Obj,"websocketPackets", websocketPackets);
field_to_json(Obj,"kafkaClients", kafkaClients);
field_to_json(Obj,"kafkaPackets", kafkaPackets);
switch(VerifiedCertificate) { switch(VerifiedCertificate) {
case NO_CERTIFICATE: case NO_CERTIFICATE:

View File

@@ -6,8 +6,7 @@
// Arilia Wireless Inc. // Arilia Wireless Inc.
// //
#ifndef UCENTRAL_RESTAPI_OBJECTS_H #pragma once
#define UCENTRAL_RESTAPI_OBJECTS_H
#include "Poco/JSON/Object.h" #include "Poco/JSON/Object.h"
#include "RESTAPI_SecurityObjects.h" #include "RESTAPI_SecurityObjects.h"
@@ -23,7 +22,6 @@ namespace OpenWifi::GWObjects {
struct ConnectionState { struct ConnectionState {
uint64_t MessageCount = 0 ; uint64_t MessageCount = 0 ;
std::string SerialNumber;
std::string Address; std::string Address;
uint64_t UUID = 0 ; uint64_t UUID = 0 ;
uint64_t PendingUUID = 0 ; uint64_t PendingUUID = 0 ;
@@ -35,6 +33,10 @@ namespace OpenWifi::GWObjects {
std::string Firmware; std::string Firmware;
CertificateValidation VerifiedCertificate = NO_CERTIFICATE; CertificateValidation VerifiedCertificate = NO_CERTIFICATE;
std::string Compatible; std::string Compatible;
uint64_t kafkaClients=0;
uint64_t webSocketClients=0;
uint64_t kafkaPackets=0;
uint64_t websocketPackets=0;
void to_json(Poco::JSON::Object &Obj) const; void to_json(Poco::JSON::Object &Obj) const;
}; };
@@ -50,11 +52,11 @@ namespace OpenWifi::GWObjects {
std::string Firmware; std::string Firmware;
std::string Compatible; std::string Compatible;
std::string FWUpdatePolicy; std::string FWUpdatePolicy;
uint64_t UUID; uint64_t UUID = 0 ;
uint64_t CreationTimestamp; uint64_t CreationTimestamp = 0 ;
uint64_t LastConfigurationChange; uint64_t LastConfigurationChange = 0 ;
uint64_t LastConfigurationDownload; uint64_t LastConfigurationDownload = 0 ;
uint64_t LastFWUpdate; uint64_t LastFWUpdate = 0 ;
std::string Venue; std::string Venue;
std::string DevicePassword; std::string DevicePassword;
void to_json(Poco::JSON::Object &Obj) const; void to_json(Poco::JSON::Object &Obj) const;
@@ -65,25 +67,25 @@ namespace OpenWifi::GWObjects {
struct Statistics { struct Statistics {
std::string SerialNumber; std::string SerialNumber;
uint64_t UUID; uint64_t UUID = 0 ;
std::string Data; std::string Data;
uint64_t Recorded; uint64_t Recorded = 0;
void to_json(Poco::JSON::Object &Obj) const; void to_json(Poco::JSON::Object &Obj) const;
}; };
struct HealthCheck { struct HealthCheck {
std::string SerialNumber; std::string SerialNumber;
uint64_t UUID; uint64_t UUID = 0 ;
std::string Data; std::string Data;
uint64_t Recorded; uint64_t Recorded = 0 ;
uint64_t Sanity; uint64_t Sanity = 0 ;
void to_json(Poco::JSON::Object &Obj) const; void to_json(Poco::JSON::Object &Obj) const;
}; };
struct Capabilities { struct Capabilities {
std::string Capabilities; std::string Capabilities;
uint64_t FirstUpdate; uint64_t FirstUpdate = 0 ;
uint64_t LastUpdate; uint64_t LastUpdate = 0 ;
void to_json(Poco::JSON::Object &Obj) const; void to_json(Poco::JSON::Object &Obj) const;
}; };
@@ -101,17 +103,17 @@ namespace OpenWifi::GWObjects {
std::string SerialNumber; std::string SerialNumber;
std::string Log; std::string Log;
std::string Data; std::string Data;
uint64_t Severity; uint64_t Severity = 0 ;
uint64_t Recorded; uint64_t Recorded = 0 ;
uint64_t LogType; uint64_t LogType = 0 ;
uint64_t UUID; uint64_t UUID = 0 ;
void to_json(Poco::JSON::Object &Obj) const; void to_json(Poco::JSON::Object &Obj) const;
}; };
struct DefaultConfiguration { struct DefaultConfiguration {
std::string Name; std::string Name;
std::string Configuration; std::string Configuration;
std::string Models; Types::StringVec Models;
std::string Description; std::string Description;
uint64_t Created; uint64_t Created;
uint64_t LastModified; uint64_t LastModified;
@@ -138,6 +140,7 @@ namespace OpenWifi::GWObjects {
uint64_t AttachDate = 0 ; uint64_t AttachDate = 0 ;
uint64_t AttachSize = 0 ; uint64_t AttachSize = 0 ;
std::string AttachType; std::string AttachType;
double executionTime = 0.0;
void to_json(Poco::JSON::Object &Obj) const; void to_json(Poco::JSON::Object &Obj) const;
}; };
@@ -153,20 +156,20 @@ namespace OpenWifi::GWObjects {
struct RttySessionDetails { struct RttySessionDetails {
std::string SerialNumber; std::string SerialNumber;
std::string Server; std::string Server;
uint64_t Port; uint64_t Port = 0 ;
std::string Token; std::string Token;
uint64_t TimeOut; uint64_t TimeOut = 0 ;
std::string ConnectionId; std::string ConnectionId;
uint64_t Started; uint64_t Started = 0 ;
std::string CommandUUID; std::string CommandUUID;
uint64_t ViewPort; uint64_t ViewPort = 0 ;
std::string DevicePassword; std::string DevicePassword;
void to_json(Poco::JSON::Object &Obj) const; void to_json(Poco::JSON::Object &Obj) const;
}; };
struct Dashboard { struct Dashboard {
uint64_t snapshot; uint64_t snapshot = 0 ;
uint64_t numberOfDevices; uint64_t numberOfDevices = 0 ;
Types::CountedMap commands; Types::CountedMap commands;
Types::CountedMap upTimes; Types::CountedMap upTimes;
Types::CountedMap memoryUsed; Types::CountedMap memoryUsed;
@@ -191,5 +194,3 @@ namespace OpenWifi::GWObjects {
void to_json(Poco::JSON::Object &Obj) const; void to_json(Poco::JSON::Object &Obj) const;
}; };
} }
#endif //UCENTRAL_RESTAPI_OBJECTS_H

View File

@@ -309,6 +309,7 @@ namespace OpenWifi::ProvObjects {
field_to_json( Obj,"deviceConfiguration",deviceConfiguration); field_to_json( Obj,"deviceConfiguration",deviceConfiguration);
field_to_json( Obj,"rrm",rrm); field_to_json( Obj,"rrm",rrm);
field_to_json( Obj,"managementPolicy",managementPolicy); field_to_json( Obj,"managementPolicy",managementPolicy);
field_to_json( Obj,"state",state);
} }
bool InventoryTag::from_json(const Poco::JSON::Object::Ptr &Obj) { bool InventoryTag::from_json(const Poco::JSON::Object::Ptr &Obj) {
@@ -326,6 +327,7 @@ namespace OpenWifi::ProvObjects {
field_from_json( Obj,"deviceConfiguration",deviceConfiguration); field_from_json( Obj,"deviceConfiguration",deviceConfiguration);
field_from_json( Obj,"rrm",rrm); field_from_json( Obj,"rrm",rrm);
field_from_json( Obj,"managementPolicy",managementPolicy); field_from_json( Obj,"managementPolicy",managementPolicy);
field_from_json( Obj,"state",state);
return true; return true;
} catch(...) { } catch(...) {
@@ -333,6 +335,20 @@ namespace OpenWifi::ProvObjects {
return false; return false;
} }
void InventoryTagList::to_json(Poco::JSON::Object &Obj) const {
field_to_json( Obj,"taglist",taglist);
}
bool InventoryTagList::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json( Obj,"taglist",taglist);
return false;
} catch (...) {
}
return false;
};
void DeviceConfigurationElement::to_json(Poco::JSON::Object &Obj) const { void DeviceConfigurationElement::to_json(Poco::JSON::Object &Obj) const {
field_to_json( Obj,"name", name); field_to_json( Obj,"name", name);
field_to_json( Obj,"description", description); field_to_json( Obj,"description", description);
@@ -440,11 +456,11 @@ namespace OpenWifi::ProvObjects {
return false; return false;
} }
void UserList::to_json(Poco::JSON::Object &Obj) const { void UuidList::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "list", list); field_to_json(Obj, "list", list);
} }
bool UserList::from_json(const Poco::JSON::Object::Ptr &Obj) { bool UuidList::from_json(const Poco::JSON::Object::Ptr &Obj) {
try { try {
field_from_json(Obj, "list", list); field_from_json(Obj, "list", list);
return true; return true;
@@ -454,14 +470,46 @@ namespace OpenWifi::ProvObjects {
return false; return false;
} }
void field_to_json(Poco::JSON::Object &Obj, const char * FieldName, ACLACCESS A) {
switch(A) {
case READ: Obj.set(FieldName,"read"); break;
case MODIFY: Obj.set(FieldName,"modify"); break;
case CREATE: Obj.set(FieldName,"create"); break;
case DELETE: Obj.set(FieldName,"delete"); break;
case NONE:
default:
Obj.set(FieldName,"none");
}
}
void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char * FieldName, ACLACCESS &A) {
if(Obj->has(FieldName)) {
auto V = Obj->getValue<std::string>(FieldName);
if(V=="read")
A = READ;
else if(V=="modify")
A = MODIFY;
else if(V=="create")
A = CREATE;
else if(V=="delete")
A = DELETE;
else if(V=="none")
A = NONE;
else
throw Poco::Exception("invalid JSON");
}
}
void ObjectACL::to_json(Poco::JSON::Object &Obj) const { void ObjectACL::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "users", users); RESTAPI_utils::field_to_json(Obj, "users", users);
RESTAPI_utils::field_to_json(Obj, "roles", roles);
field_to_json(Obj, "access", access); field_to_json(Obj, "access", access);
} }
bool ObjectACL::from_json(const Poco::JSON::Object::Ptr &Obj) { bool ObjectACL::from_json(const Poco::JSON::Object::Ptr &Obj) {
try { try {
field_from_json(Obj, "users", users); RESTAPI_utils::field_from_json(Obj, "users", users);
RESTAPI_utils::field_from_json(Obj, "roles", roles);
field_from_json(Obj, "access", access); field_from_json(Obj, "access", access);
return true; return true;
} catch(...) { } catch(...) {
@@ -471,12 +519,12 @@ namespace OpenWifi::ProvObjects {
} }
void ObjectACLList::to_json(Poco::JSON::Object &Obj) const { void ObjectACLList::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "list", list); RESTAPI_utils::field_to_json(Obj, "list", list);
} }
bool ObjectACLList::from_json(const Poco::JSON::Object::Ptr &Obj) { bool ObjectACLList::from_json(const Poco::JSON::Object::Ptr &Obj) {
try { try {
field_from_json(Obj, "list", list); RESTAPI_utils::field_from_json(Obj, "list", list);
return true; return true;
} catch(...) { } catch(...) {
@@ -484,23 +532,54 @@ namespace OpenWifi::ProvObjects {
return false; return false;
} }
std::string to_string(VISIBILITY A) {
switch(A) {
case PUBLIC: return "public";
case SELECT: return "select";
case PRIVATE:
default:
return "private";
}
}
void field_to_json(Poco::JSON::Object &Obj, const char * FieldName, VISIBILITY A) {
Obj.set(FieldName,to_string(A));
}
VISIBILITY visibility_from_string(const std::string &V) {
if(V=="public")
return PUBLIC;
else if(V=="select")
return SELECT;
else if(V=="private")
return PRIVATE;
throw Poco::Exception("invalid json");
}
void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char * FieldName, VISIBILITY &A) {
if(Obj->has(FieldName)) {
auto V = Obj->getValue<std::string>(FieldName);
A = visibility_from_string(V);
}
}
void Map::to_json(Poco::JSON::Object &Obj) const { void Map::to_json(Poco::JSON::Object &Obj) const {
info.to_json(Obj); info.to_json(Obj);
field_to_json( Obj,"data",data); RESTAPI_utils::field_to_json( Obj,"data",data);
field_to_json( Obj,"entity",entity); RESTAPI_utils::field_to_json( Obj,"entity",entity);
field_to_json( Obj,"creator",creator); RESTAPI_utils::field_to_json( Obj,"creator",creator);
field_to_json( Obj,"visibility",visibility); field_to_json( Obj,"visibility",visibility);
field_to_json( Obj,"access",access); RESTAPI_utils::field_to_json( Obj,"access",access);
} }
bool Map::from_json(const Poco::JSON::Object::Ptr &Obj) { bool Map::from_json(const Poco::JSON::Object::Ptr &Obj) {
try { try {
info.from_json(Obj); info.from_json(Obj);
field_from_json( Obj,"data",data); RESTAPI_utils::field_from_json( Obj,"data",data);
field_from_json( Obj,"entity",entity); RESTAPI_utils::field_from_json( Obj,"entity",entity);
field_from_json( Obj,"creator",creator); RESTAPI_utils::field_from_json( Obj,"creator",creator);
field_from_json( Obj,"visibility",visibility); field_from_json( Obj,"visibility",visibility);
field_from_json( Obj,"access",access); RESTAPI_utils::field_from_json( Obj,"access",access);
return true; return true;
} catch(...) { } catch(...) {
@@ -509,12 +588,12 @@ namespace OpenWifi::ProvObjects {
} }
void MapList::to_json(Poco::JSON::Object &Obj) const { void MapList::to_json(Poco::JSON::Object &Obj) const {
field_to_json( Obj,"list",list); RESTAPI_utils::field_to_json( Obj,"list",list);
} }
bool MapList::from_json(const Poco::JSON::Object::Ptr &Obj) { bool MapList::from_json(const Poco::JSON::Object::Ptr &Obj) {
try { try {
field_from_json( Obj,"list",list); RESTAPI_utils::field_from_json( Obj,"list",list);
return true; return true;
} catch(...) { } catch(...) {
@@ -562,8 +641,9 @@ namespace OpenWifi::ProvObjects {
} }
I.notes = N; I.notes = N;
I.modified = I.created = Now; I.modified = I.created = Now;
I.id = MicroService::instance().CreateUUID(); I.id = MicroService::CreateUUID();
return true; return true;
} }
}; }

View File

@@ -6,9 +6,7 @@
// Arilia Wireless Inc. // Arilia Wireless Inc.
// //
#pragma once
#ifndef OWPROV_RESTAPI_PROVOBJECTS_H
#define OWPROV_RESTAPI_PROVOBJECTS_H
#include <string> #include <string>
#include "RESTAPI_SecurityObjects.h" #include "RESTAPI_SecurityObjects.h"
@@ -286,12 +284,22 @@ namespace OpenWifi::ProvObjects {
std::string deviceConfiguration; std::string deviceConfiguration;
std::string rrm; std::string rrm;
Types::UUID_t managementPolicy; Types::UUID_t managementPolicy;
std::string state;
void to_json(Poco::JSON::Object &Obj) const; 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);
}; };
typedef std::vector<InventoryTag> InventoryTagVec; typedef std::vector<InventoryTag> InventoryTagVec;
struct InventoryTagList {
InventoryTagVec taglist;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct Report { struct Report {
uint64_t snapShot=0; uint64_t snapShot=0;
Types::CountedMap tenants; Types::CountedMap tenants;
@@ -324,16 +332,21 @@ namespace OpenWifi::ProvObjects {
bool from_json(const Poco::JSON::Object::Ptr &Obj); bool from_json(const Poco::JSON::Object::Ptr &Obj);
}; };
struct UserList { struct UuidList {
std::vector<std::string> list; std::vector<std::string> list;
void to_json(Poco::JSON::Object &Obj) const; 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);
}; };
enum ACLACCESS {
NONE, READ, MODIFY, CREATE, DELETE
};
struct ObjectACL { struct ObjectACL {
UserList users; UuidList users;
std::string access; UuidList roles;
ACLACCESS access = NONE;
void to_json(Poco::JSON::Object &Obj) const; 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);
@@ -346,12 +359,19 @@ namespace OpenWifi::ProvObjects {
bool from_json(const Poco::JSON::Object::Ptr &Obj); bool from_json(const Poco::JSON::Object::Ptr &Obj);
}; };
enum VISIBILITY {
PUBLIC, PRIVATE, SELECT
};
std::string to_string(VISIBILITY A);
VISIBILITY visibility_from_string(const std::string &V);
struct Map { struct Map {
ObjectInfo info; ObjectInfo info;
std::string data; std::string data;
std::string entity; std::string entity;
std::string creator; std::string creator;
std::string visibility; VISIBILITY visibility = PRIVATE;
ObjectACLList access; ObjectACLList access;
void to_json(Poco::JSON::Object &Obj) const; void to_json(Poco::JSON::Object &Obj) const;
@@ -367,8 +387,4 @@ namespace OpenWifi::ProvObjects {
bool UpdateObjectInfo(const Poco::JSON::Object::Ptr &O, const SecurityObjects::UserInfo &U, ObjectInfo &I); bool UpdateObjectInfo(const Poco::JSON::Object::Ptr &O, const SecurityObjects::UserInfo &U, ObjectInfo &I);
bool CreateObjectInfo(const Poco::JSON::Object::Ptr &O, const SecurityObjects::UserInfo &U, ObjectInfo &I); bool CreateObjectInfo(const Poco::JSON::Object::Ptr &O, const SecurityObjects::UserInfo &U, ObjectInfo &I);
}; };
#endif //OWPROV_RESTAPI_PROVOBJECTS_H

View File

@@ -54,6 +54,8 @@ namespace OpenWifi::SecurityObjects {
return ADMIN; return ADMIN;
else if (!Poco::icompare(U,"subscriber")) else if (!Poco::icompare(U,"subscriber"))
return SUBSCRIBER; return SUBSCRIBER;
else if (!Poco::icompare(U,"partner"))
return PARTNER;
else if (!Poco::icompare(U,"csr")) else if (!Poco::icompare(U,"csr"))
return CSR; return CSR;
else if (!Poco::icompare(U, "system")) else if (!Poco::icompare(U, "system"))
@@ -72,6 +74,7 @@ namespace OpenWifi::SecurityObjects {
case ROOT: return "root"; case ROOT: return "root";
case ADMIN: return "admin"; case ADMIN: return "admin";
case SUBSCRIBER: return "subscriber"; case SUBSCRIBER: return "subscriber";
case PARTNER: return "partner";
case CSR: return "csr"; case CSR: return "csr";
case SYSTEM: return "system"; case SYSTEM: return "system";
case INSTALLER: return "installer"; case INSTALLER: return "installer";
@@ -169,12 +172,14 @@ namespace OpenWifi::SecurityObjects {
void UserLoginLoginExtensions::to_json(Poco::JSON::Object &Obj) const { void UserLoginLoginExtensions::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "mobiles", mobiles); field_to_json(Obj, "mobiles", mobiles);
field_to_json(Obj, "mfa", mfa); field_to_json(Obj, "mfa", mfa);
field_to_json(Obj, "authenticatorSecret", authenticatorSecret);
} }
bool UserLoginLoginExtensions::from_json(Poco::JSON::Object::Ptr &Obj) { bool UserLoginLoginExtensions::from_json(Poco::JSON::Object::Ptr &Obj) {
try { try {
field_from_json(Obj,"mobiles",mobiles); field_from_json(Obj,"mobiles",mobiles);
field_from_json(Obj,"mfa",mfa); field_from_json(Obj,"mfa",mfa);
field_from_json(Obj, "authenticatorSecret", authenticatorSecret);
return true; return true;
} catch (...) { } catch (...) {
@@ -221,7 +226,7 @@ namespace OpenWifi::SecurityObjects {
} }
void UserInfo::to_json(Poco::JSON::Object &Obj) const { void UserInfo::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"Id",Id); field_to_json(Obj,"id",id);
field_to_json(Obj,"name",name); field_to_json(Obj,"name",name);
field_to_json(Obj,"description", description); field_to_json(Obj,"description", description);
field_to_json(Obj,"avatar", avatar); field_to_json(Obj,"avatar", avatar);
@@ -251,11 +256,12 @@ namespace OpenWifi::SecurityObjects {
field_to_json(Obj,"lastPasswords",lastPasswords); field_to_json(Obj,"lastPasswords",lastPasswords);
field_to_json(Obj,"oauthType",oauthType); field_to_json(Obj,"oauthType",oauthType);
field_to_json(Obj,"oauthUserInfo",oauthUserInfo); field_to_json(Obj,"oauthUserInfo",oauthUserInfo);
field_to_json(Obj,"modified",modified);
}; };
bool UserInfo::from_json(const Poco::JSON::Object::Ptr &Obj) { bool UserInfo::from_json(const Poco::JSON::Object::Ptr &Obj) {
try { try {
field_from_json(Obj,"Id",Id); field_from_json(Obj,"id",id);
field_from_json(Obj,"name",name); field_from_json(Obj,"name",name);
field_from_json(Obj,"description",description); field_from_json(Obj,"description",description);
field_from_json(Obj,"avatar",avatar); field_from_json(Obj,"avatar",avatar);
@@ -265,6 +271,8 @@ namespace OpenWifi::SecurityObjects {
field_from_json(Obj,"currentLoginURI",currentLoginURI); field_from_json(Obj,"currentLoginURI",currentLoginURI);
field_from_json(Obj,"locale",locale); field_from_json(Obj,"locale",locale);
field_from_json(Obj,"notes",notes); field_from_json(Obj,"notes",notes);
field_from_json(Obj,"location", location);
field_from_json(Obj,"owner", owner);
field_from_json<USER_ROLE>(Obj,"userRole",userRole, UserTypeFromString); field_from_json<USER_ROLE>(Obj,"userRole",userRole, UserTypeFromString);
field_from_json(Obj,"securityPolicy",securityPolicy); field_from_json(Obj,"securityPolicy",securityPolicy);
field_from_json(Obj,"userTypeProprietaryInfo",userTypeProprietaryInfo); field_from_json(Obj,"userTypeProprietaryInfo",userTypeProprietaryInfo);
@@ -283,6 +291,7 @@ namespace OpenWifi::SecurityObjects {
field_from_json(Obj,"lastPasswords",lastPasswords); field_from_json(Obj,"lastPasswords",lastPasswords);
field_from_json(Obj,"oauthType",oauthType); field_from_json(Obj,"oauthType",oauthType);
field_from_json(Obj,"oauthUserInfo",oauthUserInfo); field_from_json(Obj,"oauthUserInfo",oauthUserInfo);
field_from_json(Obj,"modified",modified);
return true; return true;
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
@@ -491,7 +500,7 @@ namespace OpenWifi::SecurityObjects {
field_to_json(Obj,"expires",expires); field_to_json(Obj,"expires",expires);
field_to_json(Obj,"completed",completed); field_to_json(Obj,"completed",completed);
field_to_json(Obj,"canceled",canceled); field_to_json(Obj,"canceled",canceled);
field_to_json(Obj,"userAction",userAction);
} }
bool ActionLink::from_json(Poco::JSON::Object::Ptr &Obj) { bool ActionLink::from_json(Poco::JSON::Object::Ptr &Obj) {
@@ -508,11 +517,86 @@ namespace OpenWifi::SecurityObjects {
field_from_json(Obj,"expires",expires); field_from_json(Obj,"expires",expires);
field_from_json(Obj,"completed",completed); field_from_json(Obj,"completed",completed);
field_from_json(Obj,"canceled",canceled); field_from_json(Obj,"canceled",canceled);
field_from_json(Obj,"userAction",userAction);
return true; return true;
} catch(...) { } catch(...) {
} }
return false; return false;
} }
void Preferences::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"id",id);
field_to_json(Obj,"modified",modified);
field_to_json(Obj,"data",data);
}
bool Preferences::from_json(Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj,"id",id);
field_from_json(Obj,"modified",modified);
field_from_json(Obj,"data",data);
return true;
} catch(...) {
}
return false;
}
void SubMfaConfig::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"id",id);
field_to_json(Obj,"type",type);
field_to_json(Obj,"sms",sms);
field_to_json(Obj,"email",email);
}
bool SubMfaConfig::from_json(Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj,"id",id);
field_from_json(Obj,"type",type);
field_from_json(Obj,"sms",sms);
field_from_json(Obj,"email",email);
return true;
} catch(...) {
}
return false;
}
void Token::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"token",token);
field_to_json(Obj,"refreshToken",refreshToken);
field_to_json(Obj,"tokenType",tokenType);
field_to_json(Obj,"userName",userName);
field_to_json(Obj,"created",created);
field_to_json(Obj,"expires",expires);
field_to_json(Obj,"idleTimeout",idleTimeout);
field_to_json(Obj,"revocationDate",revocationDate);
}
bool Token::from_json(Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj,"token",token);
field_from_json(Obj,"refreshToken",refreshToken);
field_from_json(Obj,"tokenType",tokenType);
field_from_json(Obj,"userName",userName);
field_from_json(Obj,"created",created);
field_from_json(Obj,"expires",expires);
field_from_json(Obj,"idleTimeout",idleTimeout);
field_from_json(Obj,"revocationDate",revocationDate);
return true;
} catch(...) {
}
return false;
}
void LoginRecordInfo::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"sessionId",sessionId);
field_to_json(Obj,"userId",userId);
field_to_json(Obj,"email",email);
field_to_json(Obj,"login",login);
field_to_json(Obj,"logout",logout);
}
} }

View File

@@ -6,13 +6,18 @@
// Arilia Wireless Inc. // Arilia Wireless Inc.
// //
#ifndef UCENTRAL_RESTAPI_SECURITYOBJECTS_H #pragma once
#define UCENTRAL_RESTAPI_SECURITYOBJECTS_H
#include "Poco/JSON/Object.h" #include <string>
#include "framework/OpenWifiTypes.h" #include "framework/OpenWifiTypes.h"
#include "Poco/JSON/Object.h"
#include "Poco/Data/LOB.h"
#include "Poco/Data/LOBStream.h"
namespace OpenWifi::SecurityObjects { namespace OpenWifi {
namespace SecurityObjects {
typedef std::string USER_ID_TYPE;
struct AclTemplate { struct AclTemplate {
bool Read_ = true; bool Read_ = true;
@@ -42,7 +47,7 @@ namespace OpenWifi::SecurityObjects {
}; };
enum USER_ROLE { enum USER_ROLE {
UNKNOWN, ROOT, ADMIN, SUBSCRIBER, CSR, SYSTEM, INSTALLER, NOC, ACCOUNTING UNKNOWN, ROOT, ADMIN, SUBSCRIBER, CSR, SYSTEM, INSTALLER, NOC, ACCOUNTING, PARTNER
}; };
USER_ROLE UserTypeFromString(const std::string &U); USER_ROLE UserTypeFromString(const std::string &U);
@@ -77,6 +82,7 @@ namespace OpenWifi::SecurityObjects {
struct UserLoginLoginExtensions { struct UserLoginLoginExtensions {
std::vector<MobilePhoneNumber> mobiles; std::vector<MobilePhoneNumber> mobiles;
struct MfaAuthInfo mfa; struct MfaAuthInfo mfa;
std::string authenticatorSecret;
void to_json(Poco::JSON::Object &Obj) const; void to_json(Poco::JSON::Object &Obj) const;
bool from_json(Poco::JSON::Object::Ptr &Obj); bool from_json(Poco::JSON::Object::Ptr &Obj);
@@ -101,7 +107,7 @@ namespace OpenWifi::SecurityObjects {
}; };
struct UserInfo { struct UserInfo {
std::string Id; std::string id;
std::string name; std::string name;
std::string description; std::string description;
std::string avatar; std::string avatar;
@@ -128,9 +134,10 @@ namespace OpenWifi::SecurityObjects {
std::string securityPolicy; std::string securityPolicy;
uint64_t securityPolicyChange = 0 ; uint64_t securityPolicyChange = 0 ;
std::string currentPassword; std::string currentPassword;
Types::StringVec lastPasswords; OpenWifi::Types::StringVec lastPasswords;
std::string oauthType; std::string oauthType;
std::string oauthUserInfo; std::string oauthUserInfo;
uint64_t modified;
void to_json(Poco::JSON::Object &Obj) const; 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);
@@ -224,7 +231,9 @@ namespace OpenWifi::SecurityObjects {
enum LinkActions { enum LinkActions {
FORGOT_PASSWORD=1, FORGOT_PASSWORD=1,
VERIFY_EMAIL VERIFY_EMAIL,
SUB_FORGOT_PASSWORD,
SUB_VERIFY_EMAIL
}; };
struct ActionLink { struct ActionLink {
@@ -240,10 +249,60 @@ namespace OpenWifi::SecurityObjects {
uint64_t expires=0; uint64_t expires=0;
uint64_t completed=0; uint64_t completed=0;
uint64_t canceled=0; uint64_t canceled=0;
bool userAction=true;
void to_json(Poco::JSON::Object &Obj) const; void to_json(Poco::JSON::Object &Obj) const;
bool from_json(Poco::JSON::Object::Ptr &Obj); bool from_json(Poco::JSON::Object::Ptr &Obj);
}; };
}
#endif //UCENTRAL_RESTAPI_SECURITYOBJECTS_H struct Preferences {
std::string id;
uint64_t modified;
Types::StringPairVec data;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(Poco::JSON::Object::Ptr &Obj);
};
struct SubMfaConfig {
std::string id;
std::string type;
std::string sms;
std::string email;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(Poco::JSON::Object::Ptr &Obj);
};
struct Token {
std::string token;
std::string refreshToken;
std::string tokenType;
std::string userName;
uint64_t created=0;
uint64_t expires=0;
uint64_t idleTimeout=0;
uint64_t revocationDate=0;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(Poco::JSON::Object::Ptr &Obj);
};
struct Avatar {
std::string id;
std::string type;
uint64_t created=0;
std::string name;
Poco::Data::LOB<char> avatar;
};
struct LoginRecordInfo {
std::string sessionId;
std::string userId;
std::string email;
uint64_t login=0;
uint64_t logout=0;
void to_json(Poco::JSON::Object &Obj) const;
};
}
}

View File

@@ -0,0 +1,547 @@
//
// Created by stephane bourque on 2021-10-27.
//
#include "RESTAPI_SubObjects.h"
#include "framework/MicroService.h"
using OpenWifi::RESTAPI_utils::field_to_json;
using OpenWifi::RESTAPI_utils::field_from_json;
namespace OpenWifi::SubObjects {
void HomeDeviceMode::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "enableLEDS", enableLEDS);
field_to_json(Obj, "type", type);
field_to_json(Obj, "subnet", subnet);
field_to_json(Obj, "subnetMask", subnetMask);
field_to_json(Obj, "startIP", startIP);
field_to_json(Obj, "endIP", endIP);
field_to_json(Obj, "created", created);
field_to_json(Obj, "modified", modified);
field_to_json(Obj, "subnetV6", subnetV6);
field_to_json(Obj, "subnetMaskV6", subnetMaskV6);
field_to_json(Obj, "startIPV6", startIPV6);
field_to_json(Obj, "endIPV6", endIPV6);
}
bool HomeDeviceMode::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "enableLEDS", enableLEDS);
field_from_json(Obj, "type", type);
field_from_json(Obj, "subnet", subnet);
field_from_json(Obj, "subnetMask", subnetMask);
field_from_json(Obj, "startIP", startIP);
field_from_json(Obj, "endIP", endIP);
field_from_json(Obj, "created", created);
field_from_json(Obj, "modified", modified);
field_from_json(Obj, "subnetV6", subnetV6);
field_from_json(Obj, "subnetMaskV6", subnetMaskV6);
field_from_json(Obj, "startIPV6", startIPV6);
field_from_json(Obj, "endIPV6", endIPV6);
return true;
} catch (...) {
}
return false;
}
void IPReservation::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "nickname", nickname);
field_to_json(Obj, "ipAddress", ipAddress);
field_to_json(Obj, "macAddress", macAddress);
}
bool IPReservation::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "nickname", nickname);
field_from_json(Obj, "ipAddress", ipAddress);
field_from_json(Obj, "macAddress", macAddress);
return true;
} catch (...) {
}
return false;
}
void IPReservationList::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "id", id);
field_to_json(Obj, "reservations", reservations);
field_to_json(Obj, "created", created);
field_to_json(Obj, "modified", modified);
}
bool IPReservationList::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "id", id);
field_from_json(Obj, "reservations", reservations);
field_from_json(Obj, "created", created);
field_from_json(Obj, "modified", modified);
return true;
} catch (...) {
}
return false;
}
void DnsConfiguration::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "ISP", ISP);
field_to_json(Obj, "custom", custom);
field_to_json(Obj, "primary", primary);
field_to_json(Obj, "secondary", secondary);
field_to_json(Obj, "primaryV6", primaryV6);
field_to_json(Obj, "secondaryV6", secondaryV6);
}
bool DnsConfiguration::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "ISP", ISP);
field_from_json(Obj, "custom", custom);
field_from_json(Obj, "primary", primary);
field_from_json(Obj, "secondary", secondary);
field_from_json(Obj, "primaryV6", primaryV6);
field_from_json(Obj, "secondaryV6", secondaryV6);
return true;
} catch (...) {
}
return false;
}
void InternetConnection::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "type", type);
field_to_json(Obj, "username", username);
field_to_json(Obj, "password", password);
field_to_json(Obj, "ipAddress", ipAddress);
field_to_json(Obj, "subnetMask", subnetMask);
field_to_json(Obj, "defaultGateway", defaultGateway);
field_to_json(Obj, "sendHostname", sendHostname);
field_to_json(Obj, "primaryDns", primaryDns);
field_to_json(Obj, "secondaryDns", secondaryDns);
field_to_json(Obj, "created", created);
field_to_json(Obj, "modified", modified);
field_to_json(Obj, "ipV6Support", ipV6Support);
field_to_json(Obj, "ipAddressV6", ipAddressV6);
field_to_json(Obj, "subnetMaskV6", subnetMaskV6);
field_to_json(Obj, "defaultGatewayV6", defaultGatewayV6);
field_to_json(Obj, "primaryDnsV6", primaryDnsV6);
field_to_json(Obj, "secondaryDnsV6", secondaryDnsV6);
}
bool InternetConnection::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "type", type);
field_from_json(Obj, "username", username);
field_from_json(Obj, "password", password);
field_from_json(Obj, "ipAddress", ipAddress);
field_from_json(Obj, "subnetMask", subnetMask);
field_from_json(Obj, "defaultGateway", defaultGateway);
field_from_json(Obj, "sendHostname", sendHostname);
field_from_json(Obj, "primaryDns", primaryDns);
field_from_json(Obj, "secondaryDns", secondaryDns);
field_from_json(Obj, "created", created);
field_from_json(Obj, "modified", modified);
field_from_json(Obj, "ipV6Support", ipV6Support);
field_from_json(Obj, "ipAddressV6", ipAddressV6);
field_from_json(Obj, "subnetMaskV6", subnetMaskV6);
field_from_json(Obj, "defaultGatewayV6", defaultGatewayV6);
field_from_json(Obj, "primaryDnsV6", primaryDnsV6);
field_from_json(Obj, "secondaryDnsV6", secondaryDnsV6);
return true;
} catch (...) {
}
return false;
}
void WifiNetwork::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "type", type);
field_to_json(Obj, "name", name);
field_to_json(Obj, "password", password);
field_to_json(Obj, "encryption", encryption);
field_to_json(Obj, "bands", bands);
}
bool WifiNetwork::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "type", type);
field_from_json(Obj, "name", name);
field_from_json(Obj, "password", password);
field_from_json(Obj, "encryption", encryption);
field_from_json(Obj, "bands", bands);
return true;
} catch (...) {
}
return false;
}
void WifiNetworkList::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "wifiNetworks", wifiNetworks);
field_to_json(Obj, "created", created);
field_to_json(Obj, "modified", modified);
}
bool WifiNetworkList::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "wifiNetworks", wifiNetworks);
field_from_json(Obj, "created", created);
field_from_json(Obj, "modified", modified);
return true;
} catch (...) {
}
return false;
}
void AccessTime::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "day", day);
field_to_json(Obj, "rangeList", rangeList);
}
bool AccessTime::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "day", day);
field_from_json(Obj, "rangeList", rangeList);
return true;
} catch (...) {
}
return false;
}
void AccessTimes::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "schedule", schedule);
field_to_json(Obj, "created", created);
field_to_json(Obj, "modified", modified);
}
bool AccessTimes::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "schedule", schedule);
field_from_json(Obj, "created", created);
field_from_json(Obj, "modified", modified);
return true;
} catch (...) {
}
return false;
}
void SubscriberDevice::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "name", name);
field_to_json(Obj, "description", description);
field_to_json(Obj, "macAddress", macAddress);
field_to_json(Obj, "manufacturer", manufacturer);
field_to_json(Obj, "firstContact", firstContact);
field_to_json(Obj, "lastContact", lastContact);
field_to_json(Obj, "group", group);
field_to_json(Obj, "icon", icon);
field_to_json(Obj, "suspended", suspended);
field_to_json(Obj, "ip", ip);
field_to_json(Obj, "schedule", schedule);
}
bool SubscriberDevice::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "name", name);
field_from_json(Obj, "description", description);
field_from_json(Obj, "macAddress", macAddress);
field_from_json(Obj, "manufacturer", manufacturer);
field_from_json(Obj, "firstContact", firstContact);
field_from_json(Obj, "lastContact", lastContact);
field_from_json(Obj, "group", group);
field_from_json(Obj, "icon", icon);
field_from_json(Obj, "suspended", suspended);
field_from_json(Obj, "ip", ip);
field_from_json(Obj, "schedule", schedule);
return true;
} catch (...) {
}
return false;
}
void SubscriberDeviceList::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "devices", devices);
field_to_json(Obj, "created", created);
field_to_json(Obj, "modified", modified);
}
bool SubscriberDeviceList::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "devices", devices);
field_from_json(Obj, "created", created);
field_from_json(Obj, "modified", modified);
return true;
} catch (...) {
}
return false;
}
void Association::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "name", name);
field_to_json(Obj, "ssid", ssid);
field_to_json(Obj, "macAddress", macAddress);
field_to_json(Obj, "rssi", rssi);
field_to_json(Obj, "power", power);
field_to_json(Obj, "ipv4", ipv4);
field_to_json(Obj, "ipv6", ipv6);
field_to_json(Obj, "tx", tx);
field_to_json(Obj, "rx", rx);
}
bool Association::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "name", name);
field_from_json(Obj, "ssid", ssid);
field_from_json(Obj, "macAddress", macAddress);
field_from_json(Obj, "rssi", rssi);
field_from_json(Obj, "power", power);
field_from_json(Obj, "ipv4", ipv4);
field_from_json(Obj, "ipv6", ipv6);
field_from_json(Obj, "tx", tx);
field_from_json(Obj, "rx", rx);
return true;
} catch (...) {
}
return false;
}
void AssociationList::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "associations", associations);
field_to_json(Obj, "created", created);
field_to_json(Obj, "modified", modified);
}
bool AssociationList::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "associations", associations);
field_from_json(Obj, "created", created);
field_from_json(Obj, "modified", modified);
return true;
} catch (...) {
}
return false;
}
void Client::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "macAddress", macAddress);
field_to_json(Obj, "speed", speed);
field_to_json(Obj, "mode", mode);
field_to_json(Obj, "ipv4", ipv4);
field_to_json(Obj, "ipv6", ipv6);
field_to_json(Obj, "tx", tx);
field_to_json(Obj, "rx", rx);
}
bool Client::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "macAddress", macAddress);
field_from_json(Obj, "speed", speed);
field_from_json(Obj, "mode", mode);
field_from_json(Obj, "ipv4", ipv4);
field_from_json(Obj, "ipv6", ipv6);
field_from_json(Obj, "tx", tx);
field_from_json(Obj, "rx", rx);
return true;
} catch (...) {
}
return false;
}
void ClientList::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "clients", clients);
field_to_json(Obj, "created", created);
field_to_json(Obj, "modified", modified);
}
bool ClientList::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "clients", clients);
field_from_json(Obj, "created", created);
field_from_json(Obj, "modified", modified);
return true;
} catch (...) {
}
return false;
}
void Location::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "buildingName", buildingName);
field_to_json(Obj, "addressLines", addressLines);
field_to_json(Obj, "city", city);
field_to_json(Obj, "state", state);
field_to_json(Obj, "postal", postal);
field_to_json(Obj, "country", country);
field_to_json(Obj, "phones", phones);
field_to_json(Obj, "mobiles", mobiles);
}
bool Location::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "buildingName", buildingName);
field_from_json(Obj, "addressLines", addressLines);
field_from_json(Obj, "city", city);
field_from_json(Obj, "state", state);
field_from_json(Obj, "postal", postal);
field_from_json(Obj, "country", country);
field_from_json(Obj, "phones", phones);
field_from_json(Obj, "mobiles", mobiles);
return true;
} catch (...) {
}
return false;
}
void RadioHE::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "multipleBSSID", multipleBSSID);
field_to_json(Obj, "ema", ema);
field_to_json(Obj, "bssColor", bssColor);
}
bool RadioHE::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "multipleBSSID", multipleBSSID);
field_from_json(Obj, "ema", ema);
field_from_json(Obj, "bssColor", bssColor);
return true;
} catch (...) {
}
return false;
}
void RadioRates::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "beacon", beacon);
field_to_json(Obj, "multicast", multicast);
}
bool RadioRates::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "beacon", beacon);
field_from_json(Obj, "multicast", multicast);
return true;
} catch (...) {
}
return false;
}
void RadioInformation::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "band", band);
field_to_json(Obj, "bandwidth", bandwidth);
field_to_json(Obj, "channel", channel);
field_to_json(Obj, "country", country);
field_to_json(Obj, "channelMode", channelMode);
field_to_json(Obj, "channelWidth", channelWidth);
field_to_json(Obj, "requireMode", requireMode);
field_to_json(Obj, "txpower", txpower);
field_to_json(Obj, "legacyRates", legacyRates);
field_to_json(Obj, "beaconInterval", beaconInterval);
field_to_json(Obj, "dtimPeriod", dtimPeriod);
field_to_json(Obj, "maximumClients", maximumClients);
field_to_json(Obj, "rates", rates);
field_to_json(Obj, "he", he);
field_to_json(Obj, "rawInfo", rawInfo);
}
bool RadioInformation::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "band", band);
field_from_json(Obj, "bandwidth", bandwidth);
field_from_json(Obj, "channel", channel);
field_from_json(Obj, "country", country);
field_from_json(Obj, "channelMode", channelMode);
field_from_json(Obj, "channelWidth", channelWidth);
field_from_json(Obj, "requireMode", requireMode);
field_from_json(Obj, "txpower", txpower);
field_from_json(Obj, "legacyRates", legacyRates);
field_from_json(Obj, "beaconInterval", beaconInterval);
field_from_json(Obj, "dtimPeriod", dtimPeriod);
field_from_json(Obj, "maximumClients", maximumClients);
field_from_json(Obj, "rates", rates);
field_from_json(Obj, "he", he);
field_from_json(Obj, "rawInfo", rawInfo);
return true;
} catch (...) {
}
return false;
}
void AccessPoint::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "id", id);
field_to_json(Obj, "macAddress", macAddress);
field_to_json(Obj, "name", name);
field_to_json(Obj, "deviceType", deviceType);
field_to_json(Obj, "subscriberDevices", subscriberDevices);
field_to_json(Obj, "ipReservations", ipReservations);
field_to_json(Obj, "address", address);
field_to_json(Obj, "wifiNetworks", wifiNetworks);
field_to_json(Obj, "internetConnection", internetConnection);
field_to_json(Obj, "deviceMode", deviceMode);
field_to_json(Obj, "dnsConfiguration", dnsConfiguration);
field_to_json(Obj, "radios", radios);
field_to_json(Obj, "automaticUpgrade", automaticUpgrade);
field_to_json(Obj, "configurationUUID", configurationUUID);
}
bool AccessPoint::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "id", id);
field_from_json(Obj, "macAddress", macAddress);
field_from_json(Obj, "name", name);
field_from_json(Obj, "deviceType", deviceType);
field_from_json(Obj, "subscriberDevices", subscriberDevices);
field_from_json(Obj, "ipReservations", ipReservations);
field_from_json(Obj, "address", address);
field_from_json(Obj, "wifiNetworks", wifiNetworks);
field_from_json(Obj, "internetConnection", internetConnection);
field_from_json(Obj, "deviceMode", deviceMode);
field_from_json(Obj, "dnsConfiguration", dnsConfiguration);
field_from_json(Obj, "radios", radios);
field_from_json(Obj, "automaticUpgrade", automaticUpgrade);
field_from_json(Obj, "configurationUUID", configurationUUID);
return true;
} catch (...) {
}
return false;
}
void AccessPointList::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "list", list);
}
bool AccessPointList::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "list", list);
return true;
} catch (...) {
}
return false;
}
void SubscriberInfo::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "id", id);
field_to_json(Obj, "userId", userId);
field_to_json(Obj, "firstName", firstName);
field_to_json(Obj, "initials", initials);
field_to_json(Obj, "lastName", lastName);
field_to_json(Obj, "phoneNumber", phoneNumber);
field_to_json(Obj, "secondaryEmail", secondaryEmail);
field_to_json(Obj, "accessPoints", accessPoints);
field_to_json(Obj, "serviceAddress", serviceAddress);
field_to_json(Obj, "billingAddress", billingAddress);
field_to_json(Obj, "created", created);
field_to_json(Obj, "modified", modified);
}
bool SubscriberInfo::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "id", id);
field_from_json(Obj, "userId", userId);
field_from_json(Obj, "firstName", firstName);
field_from_json(Obj, "initials", initials);
field_from_json(Obj, "lastName", lastName);
field_from_json(Obj, "phoneNumber", phoneNumber);
field_from_json(Obj, "secondaryEmail", secondaryEmail);
field_from_json(Obj, "accessPoints", accessPoints);
field_from_json(Obj, "serviceAddress", serviceAddress);
field_from_json(Obj, "billingAddress", billingAddress);
field_from_json(Obj, "created", created);
field_from_json(Obj, "modified", modified);
return true;
} catch (...) {
}
return false;
}
}

View File

@@ -0,0 +1,293 @@
//
// Created by stephane bourque on 2021-10-27.
//
#ifndef OWSUB_RESTAPI_SUBOBJECTS_H
#define OWSUB_RESTAPI_SUBOBJECTS_H
#include <string>
#include "Poco/JSON/Object.h"
namespace OpenWifi::SubObjects {
struct HomeDeviceMode {
bool enableLEDS = true;
std::string type; // bridge, manual, automatic
std::string subnet;
std::string subnetMask;
std::string startIP;
std::string endIP;
uint64_t created = 0 ;
uint64_t modified = 0 ;
std::string subnetV6;
int subnetMaskV6=0;
std::string startIPV6;
std::string endIPV6;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct IPReservation {
std::string nickname;
std::string ipAddress;
std::string macAddress;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct IPReservationList {
std::string id;
std::vector<IPReservation> reservations;
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);
};
struct DnsConfiguration {
bool ISP=false;
bool custom=false;
std::string primary;
std::string secondary;
std::string primaryV6;
std::string secondaryV6;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct InternetConnection {
std::string type; // automatic, pppoe, manual
std::string username;
std::string password;
std::string ipAddress;
std::string subnetMask;
std::string defaultGateway;
bool sendHostname = true;
std::string primaryDns;
std::string secondaryDns;
uint64_t created=0;
uint64_t modified=0;
bool ipV6Support=false;
std::string ipAddressV6;
int subnetMaskV6=0;
std::string defaultGatewayV6;
std::string primaryDnsV6;
std::string secondaryDnsV6;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct WifiNetwork {
std::string type; // main, guest
std::string name;
std::string password;
std::string encryption;
std::vector<std::string> bands;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct WifiNetworkList {
std::vector<WifiNetwork> wifiNetworks;
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);
};
struct AccessTime {
std::string day;
std::vector<std::string> rangeList;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct AccessTimes {
std::vector<AccessTime> schedule;
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);
};
struct SubscriberDevice {
std::string name;
std::string description;
std::string macAddress;
std::string manufacturer;
uint64_t firstContact=0;
uint64_t lastContact=0;
std::string group;
std::string icon;
bool suspended=false;
std::string ip;
std::vector<AccessTimes> schedule;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct SubscriberDeviceList {
std::vector<SubscriberDevice> devices;
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);
};
struct Association {
std::string name;
std::string ssid;
std::string macAddress;
int rssi=0;
int power=0;
std::string ipv4;
std::string ipv6;
uint64_t tx=0;
uint64_t rx=0;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct AssociationList {
std::vector<Association> associations;
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);
};
struct Client {
std::string macAddress;
std::string speed;
std::string mode;
std::string ipv4;
std::string ipv6;
uint64_t tx=0;
uint64_t rx=0;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct ClientList {
std::vector<Client> clients;
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);
};
struct Location {
std::string buildingName;
std::vector<std::string> addressLines;
std::string city;
std::string state;
std::string postal;
std::string country;
std::vector<std::string> phones;
std::vector<std::string> mobiles;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct RadioHE {
bool multipleBSSID = false;
bool ema = false;
uint64_t bssColor = 64;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct RadioRates {
uint64_t beacon = 6000;
uint64_t multicast = 24000;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct RadioInformation {
std::string band;
uint64_t bandwidth;
uint64_t channel = 0 ;
std::string country;
std::string channelMode{"HE"};
uint64_t channelWidth = 80;
std::string requireMode;
uint64_t txpower=0;
bool legacyRates = false;
uint64_t beaconInterval = 100;
uint64_t dtimPeriod = 2;
uint64_t maximumClients = 64;
RadioRates rates;
RadioHE he;
std::vector<std::string> rawInfo;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct AccessPoint {
std::string id;
std::string macAddress;
std::string name;
std::string deviceType;
SubscriberDeviceList subscriberDevices;
IPReservationList ipReservations;
Location address;
WifiNetworkList wifiNetworks;
InternetConnection internetConnection;
HomeDeviceMode deviceMode;
DnsConfiguration dnsConfiguration;
std::vector<RadioInformation> radios;
bool automaticUpgrade = true;
std::string configurationUUID;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct AccessPointList {
std::vector<AccessPoint> list;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct SubscriberInfo {
std::string id;
std::string userId;
std::string firstName;
std::string initials;
std::string lastName;
std::string phoneNumber;
std::string secondaryEmail;
AccessPointList accessPoints;
Location serviceAddress;
Location billingAddress;
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);
};
}
#endif //OWSUB_RESTAPI_SUBOBJECTS_H

View File

@@ -13,18 +13,22 @@ namespace OpenWifi {
int Storage::Start() { int Storage::Start() {
std::lock_guard Guard(Mutex_); std::lock_guard Guard(Mutex_);
Logger_.setLevel(Poco::Message::PRIO_NOTICE);
StorageClass::Start(); StorageClass::Start();
Create_Tables(); HistoryDB_ = std::make_unique<OpenWifi::HistoryDB>(dbType_,*Pool_, Logger());
FirmwaresDB_ = std::make_unique<OpenWifi::FirmwaresDB>(dbType_,*Pool_, Logger());
DevicesDB_ = std::make_unique<OpenWifi::DevicesDB>(dbType_,*Pool_, Logger());
HistoryDB_->Create();
FirmwaresDB_->Create();
DevicesDB_->Create();
return 0; return 0;
} }
void Storage::Stop() { void Storage::Stop() {
std::lock_guard Guard(Mutex_); std::lock_guard Guard(Mutex_);
Logger_.notice("Stopping."); Logger().notice("Stopping.");
StorageClass::Stop(); StorageClass::Stop();
} }

View File

@@ -13,61 +13,43 @@
#include "framework/StorageClass.h" #include "framework/StorageClass.h"
#include "RESTObjects/RESTAPI_FMSObjects.h" #include "RESTObjects/RESTAPI_FMSObjects.h"
#include "storage/storage_firmwares.h"
#include "storage/storage_history.h" #include "storage/orm_history.h"
#include "storage/storage_deviceTypes.h" #include "storage/orm_firmwares.h"
#include "storage/storage_deviceInfo.h" #include "storage/orm_deviceInfo.h"
namespace OpenWifi { namespace OpenWifi {
class Storage : public StorageClass { class Storage : public StorageClass {
public: public:
int Create_Tables();
int Create_Firmwares();
int Create_History();
int Create_DeviceTypes();
int Create_DeviceInfo();
bool AddFirmware(FMSObjects::Firmware & F);
bool UpdateFirmware(std::string & UUID, FMSObjects::Firmware & C);
bool DeleteFirmware(std::string & UUID);
bool GetFirmware(std::string & UUID, FMSObjects::Firmware & C);
bool GetFirmwares(uint64_t From, uint64_t HowMany, std::string & Compatible, FMSObjects::FirmwareVec & Firmwares);
bool BuildFirmwareManifest(Poco::JSON::Object & Manifest, uint64_t & Version);
bool GetFirmwareByName(std::string & Release, std::string &DeviceType,FMSObjects::Firmware & C );
bool GetFirmwareByRevision(std::string & Revision, std::string &DeviceType,FMSObjects::Firmware & C );
bool ComputeFirmwareAge(std::string & DeviceType, std::string & Revision, FMSObjects::FirmwareAgeDetails &AgeDetails);
bool GetHistory(std::string &SerialNumber,uint64_t From, uint64_t HowMany,FMSObjects::RevisionHistoryEntryVec &History);
bool AddHistory(FMSObjects::RevisionHistoryEntry &History);
void PopulateLatestFirmwareCache();
void RemoveOldFirmware();
int Start() override; int Start() override;
void Stop() override; void Stop() override;
bool SetDeviceRevision(std::string &SerialNumber, std::string & Revision, std::string & DeviceType, std::string &EndPoint); int Create_Tables();
bool AddHistory( std::string & SerialNumber, std::string &DeviceType, std::string & PreviousRevision, std::string & NewVersion); int Create_DeviceTypes();
bool DeleteHistory( std::string & SerialNumber, std::string &Id); int Create_DeviceInfo();
bool GetDevices(uint64_t From, uint64_t HowMany, std::vector<FMSObjects::DeviceConnectionInformation> & Devices); bool BuildFirmwareManifest(Poco::JSON::Object & Manifest, uint64_t & Version);
bool GetDevice(std::string &SerialNumber, FMSObjects::DeviceConnectionInformation & Device);
bool SetDeviceDisconnected(std::string &SerialNumber, std::string &EndPoint);
bool GenerateDeviceReport(FMSObjects::DeviceReport &Report);
static std::string TrimRevision(const std::string &R); static std::string TrimRevision(const std::string &R);
static Storage *instance() { static auto instance() {
static Storage *instance_ = new Storage; static auto instance_ = new Storage;
return instance_; return instance_;
} }
OpenWifi::HistoryDB & HistoryDB() { return * HistoryDB_; }
OpenWifi::FirmwaresDB & FirmwaresDB() { return * FirmwaresDB_; }
OpenWifi::DevicesDB & DevicesDB() { return * DevicesDB_; }
private: private:
std::unique_ptr<OpenWifi::HistoryDB> HistoryDB_;
std::unique_ptr<OpenWifi::FirmwaresDB> FirmwaresDB_;
std::unique_ptr<OpenWifi::DevicesDB> DevicesDB_;
}; };
inline class Storage * StorageService() { return Storage::instance(); }; inline auto StorageService() { return Storage::instance(); };
} // namespace } // namespace

93
src/framework/API_Proxy.h Normal file
View File

@@ -0,0 +1,93 @@
//
// Created by stephane bourque on 2021-11-30.
//
#pragma once
#include "framework/MicroService.h"
#include "Poco/JSON/Parser.h"
namespace OpenWifi {
inline void API_Proxy( Poco::Logger &Logger,
Poco::Net::HTTPServerRequest *Request,
Poco::Net::HTTPServerResponse *Response,
const char * ServiceType,
const char * PathRewrite,
uint64_t msTimeout_ = 10000 ) {
try {
auto Services = MicroService::instance().GetServices(ServiceType);
for(auto const &Svc:Services) {
Poco::URI SourceURI(Request->getURI());
Poco::URI DestinationURI(Svc.PrivateEndPoint);
DestinationURI.setPath(PathRewrite);
DestinationURI.setQuery(SourceURI.getQuery());
// std::cout << " Source: " << SourceURI.toString() << std::endl;
// std::cout << "Destination: " << DestinationURI.toString() << std::endl;
Poco::Net::HTTPSClientSession Session(DestinationURI.getHost(), DestinationURI.getPort());
Session.setKeepAlive(true);
Session.setTimeout(Poco::Timespan(msTimeout_/1000, msTimeout_ % 1000));
Poco::Net::HTTPRequest ProxyRequest(Request->getMethod(),
DestinationURI.getPathAndQuery(),
Poco::Net::HTTPMessage::HTTP_1_1);
if(Request->has("Authorization")) {
ProxyRequest.add("Authorization", Request->get("Authorization"));
} else {
ProxyRequest.add("X-API-KEY", Svc.AccessKey);
ProxyRequest.add("X-INTERNAL-NAME", MicroService::instance().PublicEndPoint());
}
if(Request->getMethod() == Poco::Net::HTTPRequest::HTTP_DELETE) {
Session.sendRequest(ProxyRequest);
Poco::Net::HTTPResponse ProxyResponse;
Session.receiveResponse(ProxyResponse);
Response->setStatus(ProxyResponse.getStatus());
Response->send();
return;
} else {
Poco::JSON::Parser P;
std::stringstream SS;
try {
auto Body = P.parse(Request->stream()).extract<Poco::JSON::Object::Ptr>();
Poco::JSON::Stringifier::condense(Body,SS);
SS << "\r\n\r\n";
} catch(const Poco::Exception &E) {
Logger.log(E);
}
if(SS.str().empty()) {
Session.sendRequest(ProxyRequest);
} else {
ProxyRequest.setContentType("application/json");
ProxyRequest.setContentLength(SS.str().size());
std::ostream & os = Session.sendRequest(ProxyRequest);
os << SS.str() ;
}
Poco::Net::HTTPResponse ProxyResponse;
std::stringstream SSR;
try {
std::istream &ProxyResponseStream = Session.receiveResponse(ProxyResponse);
Poco::JSON::Parser P2;
auto ProxyResponseBody = P2.parse(ProxyResponseStream).extract<Poco::JSON::Object::Ptr>();
Poco::JSON::Stringifier::condense(ProxyResponseBody,SSR);
Response->setContentType("application/json");
Response->setContentLength(SSR.str().size());
Response->setStatus(ProxyResponse.getStatus());
Response->sendBuffer(SSR.str().c_str(),SSR.str().size());
return;
} catch( const Poco::Exception & E) {
}
Response->setStatus(ProxyResponse.getStatus());
Response->send();
return;
}
}
} catch (const Poco::Exception &E) {
Logger.log(E);
}
}
}

View File

@@ -2327,7 +2327,7 @@ namespace OpenWifi {
if(Utils::wgets(GitUCentralJSONSchemaFile, GitSchema)) { if(Utils::wgets(GitUCentralJSONSchemaFile, GitSchema)) {
auto schema = json::parse(GitSchema); auto schema = json::parse(GitSchema);
Validator_->set_root_schema(schema); Validator_->set_root_schema(schema);
Logger_.information("Using uCentral validation schema from GIT."); Logger().information("Using uCentral validation schema from GIT.");
} else { } else {
std::string FileName{ MicroService::instance().DataDir() + "/ucentral.schema.json" }; std::string FileName{ MicroService::instance().DataDir() + "/ucentral.schema.json" };
std::ifstream input(FileName); std::ifstream input(FileName);
@@ -2336,11 +2336,11 @@ namespace OpenWifi {
input.close(); input.close();
auto schema = json::parse(schema_file.str()); auto schema = json::parse(schema_file.str());
Validator_->set_root_schema(schema); Validator_->set_root_schema(schema);
Logger_.information("Using uCentral validation schema from local file."); Logger().information("Using uCentral validation schema from local file.");
} }
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Validator_->set_root_schema(DefaultUCentralSchema); Validator_->set_root_schema(DefaultUCentralSchema);
Logger_.information("Using uCentral validation from built-in default."); Logger().information("Using uCentral validation from built-in default.");
} }
Initialized_ = Working_ = true; Initialized_ = Working_ = true;
} }
@@ -2471,7 +2471,7 @@ namespace OpenWifi {
} }
void ConfigurationValidator::reinitialize(Poco::Util::Application &self) { void ConfigurationValidator::reinitialize(Poco::Util::Application &self) {
Logger_.information("Reinitializing."); Logger().information("Reinitializing.");
Working_ = Initialized_ = false; Working_ = Initialized_ = false;
Init(); Init();
} }

View File

@@ -2,8 +2,7 @@
// Created by stephane bourque on 2021-09-14. // Created by stephane bourque on 2021-09-14.
// //
#ifndef OWPROV_CONFIGURATIONVALIDATOR_H #pragma once
#define OWPROV_CONFIGURATIONVALIDATOR_H
#include <nlohmann/json-schema.hpp> #include <nlohmann/json-schema.hpp>
#include "framework/MicroService.h" #include "framework/MicroService.h"
@@ -43,4 +42,3 @@ namespace OpenWifi {
inline bool ValidateUCentralConfiguration(const std::string &C, std::string &Error) { return ConfigurationValidator::instance()->Validate(C, Error); } inline bool ValidateUCentralConfiguration(const std::string &C, std::string &Error) { return ConfigurationValidator::instance()->Validate(C, Error); }
} }
#endif //OWPROV_CONFIGURATIONVALIDATOR_H

View File

@@ -2,8 +2,7 @@
// Created by stephane bourque on 2021-10-08. // Created by stephane bourque on 2021-10-08.
// //
#ifndef OWPROV_COUNTRYCODES_H #pragma once
#define OWPROV_COUNTRYCODES_H
#include <vector> #include <vector>
#include <string> #include <string>
@@ -270,4 +269,3 @@ namespace OpenWifi {
} }
#endif //OWPROV_COUNTRYCODES_H

View File

@@ -5,8 +5,8 @@
// Created by Stephane Bourque on 2021-03-04. // Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc. // Arilia Wireless Inc.
// //
#ifndef UCENTRALGW_KAFKA_TOPICS_H
#define UCENTRALGW_KAFKA_TOPICS_H #pragma once
namespace OpenWifi::KafkaTopics { namespace OpenWifi::KafkaTopics {
static const std::string HEALTHCHECK{"healthcheck"}; static const std::string HEALTHCHECK{"healthcheck"};
@@ -17,6 +17,7 @@ namespace OpenWifi::KafkaTopics {
static const std::string COMMAND{"command"}; static const std::string COMMAND{"command"};
static const std::string SERVICE_EVENTS{"service_events"}; static const std::string SERVICE_EVENTS{"service_events"};
static const std::string DEVICE_EVENT_QUEUE{"device_event_queue"}; static const std::string DEVICE_EVENT_QUEUE{"device_event_queue"};
static const std::string DEVICE_TELEMETRY{"device_telemetry"};
namespace ServiceEvents { namespace ServiceEvents {
static const std::string EVENT_JOIN{"join"}; static const std::string EVENT_JOIN{"join"};
@@ -37,4 +38,3 @@ namespace OpenWifi::KafkaTopics {
} }
} }
#endif // UCENTRALGW_KAFKA_TOPICS_H

File diff suppressed because it is too large Load Diff

View File

@@ -1,25 +1,17 @@
// //
// License type: BSD 3-Clause License // Created by stephane bourque on 2021-11-16.
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
// //
#ifndef UCENTRALGW_UCENTRALTYPES_H #pragma once
#define UCENTRALGW_UCENTRALTYPES_H
#include <vector>
#include <string>
#include <map> #include <map>
#include <functional>
#include <list>
#include <utility> #include <utility>
#include <vector>
#include <functional>
#include <string>
#include <queue> #include <queue>
#include <list>
#include "Poco/StringTokenizer.h" #include <set>
#include "Poco/JSON/Parser.h"
#include "Poco/JSON/Stringifier.h"
namespace OpenWifi::Types { namespace OpenWifi::Types {
typedef std::pair<std::string,std::string> StringPair; typedef std::pair<std::string,std::string> StringPair;
@@ -28,15 +20,19 @@ namespace OpenWifi::Types {
typedef std::vector<std::string> StringVec; typedef std::vector<std::string> StringVec;
typedef std::set<std::string> StringSet; typedef std::set<std::string> StringSet;
typedef std::map<std::string,std::set<std::string>> StringMapStringSet; typedef std::map<std::string,std::set<std::string>> StringMapStringSet;
typedef std::function<void(std::string, std::string)> TopicNotifyFunction; typedef std::function<void(const std::string &, const std::string &)> TopicNotifyFunction;
typedef std::list<std::pair<TopicNotifyFunction,int>> TopicNotifyFunctionList; typedef std::list<std::pair<TopicNotifyFunction,int>> TopicNotifyFunctionList;
typedef std::map<std::string, TopicNotifyFunctionList> NotifyTable; typedef std::map<std::string, TopicNotifyFunctionList> NotifyTable;
typedef std::map<std::string,uint64_t> CountedMap; typedef std::map<std::string,uint64_t> CountedMap;
typedef std::vector<uint64_t> TagList; typedef std::vector<uint64_t> TagList;
typedef std::string UUID_t; typedef std::string UUID_t;
typedef std::vector<UUID_t> UUIDvec_t; typedef std::vector<UUID_t> UUIDvec_t;
typedef std::map<std::string,std::map<uint32_t,uint64_t>> Counted3DMapSII;
}
inline void UpdateCountedMap(CountedMap &M, const std::string &S, uint64_t Increment=1) { namespace OpenWifi {
inline void UpdateCountedMap(OpenWifi::Types::CountedMap &M, const std::string &S, uint64_t Increment=1) {
auto it = M.find(S); auto it = M.find(S);
if(it==M.end()) if(it==M.end())
M[S] = Increment; M[S] = Increment;
@@ -44,60 +40,21 @@ namespace OpenWifi::Types {
it->second += Increment; it->second += Increment;
} }
inline std::string to_string( const StringVec &V) { inline void UpdateCountedMap(OpenWifi::Types::Counted3DMapSII &M, const std::string &S, uint32_t Index, uint64_t Increment=1) {
Poco::JSON::Array O; auto it = M.find(S);
for(const auto &i:V) { if(it==M.end()) {
O.add(i); std::map<uint32_t,uint64_t> E;
E[Index] = Increment;
M[S] = E;
} }
std::stringstream SS; else {
Poco::JSON::Stringifier::stringify(O,SS); std::map<uint32_t,uint64_t> & IndexMap = it->second;
return SS.str(); auto it_index = IndexMap.find(Index);
} if(it_index == IndexMap.end()) {
IndexMap[Index] = Increment;
inline std::string to_string( const StringPairVec &V) { } else {
Poco::JSON::Array O; it_index->second += Increment;
for(const auto &i:V) {
Poco::JSON::Array OO;
OO.add(i.first);
OO.add(i.second);
O.add(OO);
}
std::stringstream SS;
Poco::JSON::Stringifier::stringify(O,SS);
return SS.str();
}
inline void from_string(const std::string &S, StringPairVec &V) {
try {
Poco::JSON::Parser P;
auto O = P.parse(S).extract<Poco::JSON::Array::Ptr>();
for(const auto &i:*O) {
auto Inner = i.extract<Poco::JSON::Array::Ptr>();
for(const auto &j:*Inner) {
auto S1 = i[0].toString();
auto S2 = i[1].toString();
V.push_back(std::make_pair(S1,S2));
} }
} }
} catch (...) {
} }
} }
inline void from_string(const std::string &S, StringVec &V) {
try {
Poco::JSON::Parser P;
auto O = P.parse(S).extract<Poco::JSON::Array::Ptr>();
for(auto const &i:*O) {
V.push_back(i.toString());
}
} catch (...) {
}
}
};
#endif // UCENTRALGW_UCENTRALTYPES_H

View File

@@ -2,8 +2,7 @@
// Created by stephane bourque on 2021-09-12. // Created by stephane bourque on 2021-09-12.
// //
#ifndef OWPROV_RESTAPI_ERRORS_H #pragma once
#define OWPROV_RESTAPI_ERRORS_H
namespace OpenWifi::RESTAPI::Errors { namespace OpenWifi::RESTAPI::Errors {
static const std::string MissingUUID{"Missing UUID."}; static const std::string MissingUUID{"Missing UUID."};
@@ -15,7 +14,7 @@ namespace OpenWifi::RESTAPI::Errors {
static const std::string CouldNotBeDeleted{"Element could not be deleted."}; static const std::string CouldNotBeDeleted{"Element could not be deleted."};
static const std::string NameMustBeSet{"The name property must be set."}; static const std::string NameMustBeSet{"The name property must be set."};
static const std::string ConfigBlockInvalid{"Configuration block type invalid."}; static const std::string ConfigBlockInvalid{"Configuration block type invalid."};
static const std::string UnknownId{"Unknown management policy."}; static const std::string UnknownId{"Unknown UUID."};
static const std::string InvalidDeviceTypes{"Unknown or invalid device type(s)."}; static const std::string InvalidDeviceTypes{"Unknown or invalid device type(s)."};
static const std::string RecordNotCreated{"Record could not be created."}; static const std::string RecordNotCreated{"Record could not be created."};
static const std::string RecordNotUpdated{"Record could not be updated."}; static const std::string RecordNotUpdated{"Record could not be updated."};
@@ -60,6 +59,10 @@ namespace OpenWifi::RESTAPI::Errors {
static const std::string MissingAuthenticationInformation{"Missing authentication information."}; static const std::string MissingAuthenticationInformation{"Missing authentication information."};
static const std::string InsufficientAccessRights{"Insufficient access rights to complete the operation."}; static const std::string InsufficientAccessRights{"Insufficient access rights to complete the operation."};
static const std::string ExpiredToken{"Token has expired, user must login."}; static const std::string ExpiredToken{"Token has expired, user must login."};
static const std::string SubscriberMustExist{"Subscriber must exist."};
static const std::string AuthenticatorVerificationIncomplete{"Authenticator validation is not complete."};
static const std::string SMSCouldNotBeSentRetry{"SMS could not be sent to validate device, try later or change the phone number."};
static const std::string SMSCouldNotValidate{"Code and number could not be validated"};
static const std::string InvalidDeviceClass{"Invalid device class. Must be: any, venue, entity, or subscriber"};
} }
#endif //OWPROV_RESTAPI_ERRORS_H

View File

@@ -6,8 +6,7 @@
// Arilia Wireless Inc. // Arilia Wireless Inc.
// //
#ifndef UCENTRALGW_RESTAPI_PROTOCOL_H #pragma once
#define UCENTRALGW_RESTAPI_PROTOCOL_H
namespace OpenWifi::RESTAPI::Protocol { namespace OpenWifi::RESTAPI::Protocol {
static const char * CAPABILITIES = "capabilities"; static const char * CAPABILITIES = "capabilities";
@@ -85,11 +84,13 @@ namespace OpenWifi::RESTAPI::Protocol {
static const char * GETSUBSYSTEMNAMES = "getsubsystemnames"; static const char * GETSUBSYSTEMNAMES = "getsubsystemnames";
static const char * GETLOGLEVELNAMES = "getloglevelnames"; static const char * GETLOGLEVELNAMES = "getloglevelnames";
static const char * STATS = "stats"; static const char * STATS = "stats";
static const char * PING = "ping";
static const char * PARAMETERS = "parameters"; static const char * PARAMETERS = "parameters";
static const char * VALUE = "value"; static const char * VALUE = "value";
static const char * LASTONLY = "lastOnly"; static const char * LASTONLY = "lastOnly";
static const char * NEWEST = "newest"; static const char * NEWEST = "newest";
static const char * ACTIVESCAN = "activeScan"; static const char * ACTIVESCAN = "activeScan";
static const char * OVERRIDEDFS = "override_dfs";
static const char * LIST = "list"; static const char * LIST = "list";
static const char * TAG = "tag"; static const char * TAG = "tag";
static const char * TAGLIST = "tagList"; static const char * TAGLIST = "tagList";
@@ -136,5 +137,3 @@ namespace OpenWifi::RESTAPI::Protocol {
static const char * UI = "UI"; static const char * UI = "UI";
} }
#endif // UCENTRALGW_RESTAPI_PROTOCOL_H

View File

@@ -2,8 +2,7 @@
// Created by stephane bourque on 2021-10-06. // Created by stephane bourque on 2021-10-06.
// //
#ifndef OPENWIFI_STORAGE_H #pragma once
#define OPENWIFI_STORAGE_H
#include "Poco/Data/Session.h" #include "Poco/Data/Session.h"
#include "Poco/Data/SessionPool.h" #include "Poco/Data/SessionPool.h"
@@ -34,8 +33,8 @@ namespace OpenWifi {
int Start() override { int Start() override {
std::lock_guard Guard(Mutex_); std::lock_guard Guard(Mutex_);
Logger_.setLevel(Poco::Message::PRIO_NOTICE); Logger().setLevel(Poco::Message::PRIO_INFORMATION);
Logger_.notice("Starting."); Logger().notice("Starting.");
std::string DBType = MicroService::instance().ConfigGetString("storage.type"); std::string DBType = MicroService::instance().ConfigGetString("storage.type");
if (DBType == "sqlite") { if (DBType == "sqlite") {
@@ -52,37 +51,6 @@ namespace OpenWifi {
Pool_->shutdown(); Pool_->shutdown();
} }
[[nodiscard]] inline std::string ComputeRange(uint64_t From, uint64_t HowMany) {
if(dbType_==sqlite) {
return " LIMIT " + std::to_string(From-1) + ", " + std::to_string(HowMany) + " ";
} else if(dbType_==pgsql) {
return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From-1) + " ";
} else if(dbType_==mysql) {
return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From-1) + " ";
}
return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From-1) + " ";
}
inline std::string ConvertParams(const std::string & S) const {
std::string R;
R.reserve(S.size()*2+1);
if(dbType_==pgsql) {
auto Idx=1;
for(auto const & i:S)
{
if(i=='?') {
R += '$';
R.append(std::to_string(Idx++));
} else {
R += i;
}
}
} else {
R = S;
}
return R;
}
private: private:
inline int Setup_SQLite(); inline int Setup_SQLite();
inline int Setup_MySQL(); inline int Setup_MySQL();
@@ -102,7 +70,7 @@ namespace OpenWifi {
#else #else
inline int StorageClass::Setup_SQLite() { inline int StorageClass::Setup_SQLite() {
Logger_.notice("SQLite StorageClass enabled."); Logger().notice("SQLite StorageClass enabled.");
dbType_ = sqlite; dbType_ = sqlite;
auto DBName = MicroService::instance().DataDir() + "/" + MicroService::instance().ConfigGetString("storage.type.sqlite.db"); auto DBName = MicroService::instance().DataDir() + "/" + MicroService::instance().ConfigGetString("storage.type.sqlite.db");
auto NumSessions = MicroService::instance().ConfigGetInt("storage.type.sqlite.maxsessions", 64); auto NumSessions = MicroService::instance().ConfigGetInt("storage.type.sqlite.maxsessions", 64);
@@ -113,7 +81,7 @@ namespace OpenWifi {
} }
inline int StorageClass::Setup_MySQL() { inline int StorageClass::Setup_MySQL() {
Logger_.notice("MySQL StorageClass enabled."); Logger().notice("MySQL StorageClass enabled.");
dbType_ = mysql; dbType_ = mysql;
auto NumSessions = MicroService::instance().ConfigGetInt("storage.type.mysql.maxsessions", 64); auto NumSessions = MicroService::instance().ConfigGetInt("storage.type.mysql.maxsessions", 64);
auto IdleTime = MicroService::instance().ConfigGetInt("storage.type.mysql.idletime", 60); auto IdleTime = MicroService::instance().ConfigGetInt("storage.type.mysql.idletime", 60);
@@ -138,7 +106,7 @@ namespace OpenWifi {
} }
inline int StorageClass::Setup_PostgreSQL() { inline int StorageClass::Setup_PostgreSQL() {
Logger_.notice("PostgreSQL StorageClass enabled."); Logger().notice("PostgreSQL StorageClass enabled.");
dbType_ = pgsql; dbType_ = pgsql;
auto NumSessions = MicroService::instance().ConfigGetInt("storage.type.postgresql.maxsessions", 64); auto NumSessions = MicroService::instance().ConfigGetInt("storage.type.postgresql.maxsessions", 64);
auto IdleTime = MicroService::instance().ConfigGetInt("storage.type.postgresql.idletime", 60); auto IdleTime = MicroService::instance().ConfigGetInt("storage.type.postgresql.idletime", 60);
@@ -165,5 +133,3 @@ namespace OpenWifi {
#endif #endif
} }
#endif //OPENWIFI_STORAGE_H

View File

@@ -6,8 +6,7 @@
// Arilia Wireless Inc. // Arilia Wireless Inc.
// //
#ifndef __OPENWIFI_ORM_H__ #pragma once
#define __OPENWIFI_ORM_H__
#include <string> #include <string>
#include <memory> #include <memory>
@@ -33,7 +32,8 @@ namespace ORM {
FT_BIGINT, FT_BIGINT,
FT_TEXT, FT_TEXT,
FT_VARCHAR, FT_VARCHAR,
FT_BLOB FT_BLOB,
FT_BOOLEAN
}; };
enum Indextype { enum Indextype {
@@ -97,6 +97,7 @@ namespace ORM {
case FT_INT: return "INT"; case FT_INT: return "INT";
case FT_BIGINT: return "BIGINT"; case FT_BIGINT: return "BIGINT";
case FT_TEXT: return "TEXT"; case FT_TEXT: return "TEXT";
case FT_BOOLEAN: return "BOOLEAN";
case FT_VARCHAR: case FT_VARCHAR:
if(Size) if(Size)
return std::string("VARCHAR(") + std::to_string(Size) + std::string(")"); return std::string("VARCHAR(") + std::to_string(Size) + std::string(")");
@@ -154,28 +155,46 @@ namespace ORM {
return S; return S;
} }
template <typename RecordType> class DBCache {
public:
DBCache(unsigned Size, unsigned Timeout)
{
}
virtual void Create(const RecordType &R)=0;
virtual bool GetFromCache(const std::string &FieldName, const std::string &Value, RecordType &R)=0;
virtual void UpdateCache(const RecordType &R)=0;
virtual void Delete(const std::string &FieldName, const std::string &Value)=0;
private:
};
template <typename RecordTuple, typename RecordType> class DB { template <typename RecordTuple, typename RecordType> class DB {
public: public:
typedef const char * field_name_t;
DB( OpenWifi::DBType dbtype, DB( OpenWifi::DBType dbtype,
const char *TableName, const char *TableName,
const FieldVec & Fields, const FieldVec & Fields,
const IndexVec & Indexes, const IndexVec & Indexes,
Poco::Data::SessionPool & Pool, Poco::Data::SessionPool & Pool,
Poco::Logger &L, Poco::Logger &L,
const char *Prefix): const char *Prefix,
Type(dbtype), DBCache<RecordType> * Cache=nullptr):
DBName(TableName), Type_(dbtype),
TableName_(TableName),
Pool_(Pool), Pool_(Pool),
Logger_(L), Logger_(L),
Prefix_(Prefix) Prefix_(Prefix),
Cache_(Cache)
{ {
assert(RecordTuple::length == Fields.size());
bool first = true; bool first = true;
int Place=0; int Place=0;
assert( RecordTuple::length == Fields.size());
for(const auto &i:Fields) { for(const auto &i:Fields) {
FieldNames_[i.Name] = Place; FieldNames_[i.Name] = Place;
if(!first) { if(!first) {
CreateFields_ += ", "; CreateFields_ += ", ";
@@ -186,7 +205,7 @@ namespace ORM {
SelectList_ += "("; SelectList_ += "(";
} }
CreateFields_ += i.Name + " " + FieldTypeToChar(Type, i.Type,i.Size) + (i.Index ? " unique primary key" : ""); CreateFields_ += i.Name + " " + FieldTypeToChar(Type_, i.Type,i.Size) + (i.Index ? " unique primary key" : "");
SelectFields_ += i.Name ; SelectFields_ += i.Name ;
UpdateFields_ += i.Name + "=?"; UpdateFields_ += i.Name + "=?";
SelectList_ += "?"; SelectList_ += "?";
@@ -196,11 +215,11 @@ namespace ORM {
SelectList_ += ")"; SelectList_ += ")";
if(!Indexes.empty()) { if(!Indexes.empty()) {
if(Type==OpenWifi::DBType::sqlite || Type==OpenWifi::DBType::pgsql) { if(Type_==OpenWifi::DBType::sqlite || Type_==OpenWifi::DBType::pgsql) {
for(const auto &j:Indexes) { for(const auto &j:Indexes) {
std::string IndexLine; std::string IndexLine;
IndexLine = std::string("CREATE INDEX IF NOT EXISTS ") + j.Name + std::string(" ON ") + DBName + " ("; IndexLine = std::string("CREATE INDEX IF NOT EXISTS ") + j.Name + std::string(" ON ") + TableName_+ " (";
bool first_entry=true; bool first_entry=true;
for(const auto &k:j.Entries) { for(const auto &k:j.Entries) {
assert(FieldNames_.find(k.FieldName) != FieldNames_.end()); assert(FieldNames_.find(k.FieldName) != FieldNames_.end());
@@ -210,10 +229,10 @@ namespace ORM {
first_entry = false; first_entry = false;
IndexLine += k.FieldName + std::string(" ") + std::string(k.Type == Indextype::ASC ? "ASC" : "DESC") ; IndexLine += k.FieldName + std::string(" ") + std::string(k.Type == Indextype::ASC ? "ASC" : "DESC") ;
} }
IndexLine += " );"; IndexLine += " )";
IndexCreation += IndexLine; IndexCreation_.template emplace_back(IndexLine);
} }
} else if(Type==OpenWifi::DBType::mysql) { } else if(Type_==OpenWifi::DBType::mysql) {
bool firstIndex = true; bool firstIndex = true;
std::string IndexLine; std::string IndexLine;
for(const auto &j:Indexes) { for(const auto &j:Indexes) {
@@ -232,7 +251,7 @@ namespace ORM {
} }
IndexLine += " ) "; IndexLine += " ) ";
} }
IndexCreation = IndexLine; IndexCreation_.template emplace_back(IndexLine);
} }
} }
} }
@@ -242,22 +261,27 @@ namespace ORM {
[[nodiscard]] const std::string & SelectList() const { return SelectList_; }; [[nodiscard]] const std::string & SelectList() const { return SelectList_; };
[[nodiscard]] const std::string & UpdateFields() const { return UpdateFields_; }; [[nodiscard]] const std::string & UpdateFields() const { return UpdateFields_; };
inline std::string OP(const char *F, SqlComparison O , int V) { inline std::string OP(field_name_t F, SqlComparison O , bool V) {
assert( FieldNames_.find(F) != FieldNames_.end() );
return std::string{"("} + F + SQLCOMPS[O] + (V ? "true" : "false") + ")" ;
}
inline std::string OP(field_name_t F, SqlComparison O , int V) {
assert( FieldNames_.find(F) != FieldNames_.end() ); assert( FieldNames_.find(F) != FieldNames_.end() );
return std::string{"("} + F + SQLCOMPS[O] + std::to_string(V) + ")" ; return std::string{"("} + F + SQLCOMPS[O] + std::to_string(V) + ")" ;
} }
inline std::string OP(const char *F, SqlComparison O , uint64_t V) { inline std::string OP(field_name_t F, SqlComparison O , uint64_t V) {
assert( FieldNames_.find(F) != FieldNames_.end() ); assert( FieldNames_.find(F) != FieldNames_.end() );
return std::string{"("} + F + SQLCOMPS[O] + std::to_string(V) + ")" ; return std::string{"("} + F + SQLCOMPS[O] + std::to_string(V) + ")" ;
} }
std::string OP(const char *F, SqlComparison O , const std::string & V) { std::string OP(field_name_t F, SqlComparison O , const std::string & V) {
assert( FieldNames_.find(F) != FieldNames_.end() ); assert( FieldNames_.find(F) != FieldNames_.end() );
return std::string{"("} + F + SQLCOMPS[O] + "'" + Escape(V) + "')" ; return std::string{"("} + F + SQLCOMPS[O] + "'" + Escape(V) + "')" ;
} }
std::string OP(const char *F, SqlComparison O , const char * V) { std::string OP(field_name_t F, SqlComparison O , const char * V) {
assert( FieldNames_.find(F) != FieldNames_.end() ); assert( FieldNames_.find(F) != FieldNames_.end() );
return std::string{"("} + F + SQLCOMPS[O] + "'" + Escape(V) + "')" ; return std::string{"("} + F + SQLCOMPS[O] + "'" + Escape(V) + "')" ;
} }
@@ -278,35 +302,61 @@ namespace ORM {
return std::string{"("} + P1 + BOPS[BOP] + OP(true, P2, More...); return std::string{"("} + P1 + BOPS[BOP] + OP(true, P2, More...);
} }
inline bool Create() { bool Upgrade() {
std::string S; uint32_t To;
return Upgrade(0, To);
if(Type==OpenWifi::DBType::mysql) {
if(IndexCreation.empty())
S = "create table if not exists " + DBName +" ( " + CreateFields_ + " )" ;
else
S = "create table if not exists " + DBName +" ( " + CreateFields_ + " ), " + IndexCreation + " )";
} else if (Type==OpenWifi::DBType::pgsql || Type==OpenWifi::DBType::sqlite) {
S = "create table if not exists " + DBName + " ( " + CreateFields_ + " ); " + IndexCreation ;
} }
// std::cout << "CREATE-DB: " << S << std::endl; inline bool Create() {
switch(Type_) {
case OpenWifi::DBType::mysql: {
try { try {
Poco::Data::Session Session = Pool_.get(); Poco::Data::Session Session = Pool_.get();
Poco::Data::Statement CreateStatement(Session); std::string Statement = IndexCreation_.empty() ? "create table if not exists " + TableName_ +" ( " + CreateFields_ + " )" :
"create table if not exists " + TableName_ +" ( " + CreateFields_ + " ), " + IndexCreation_[0] + " )";
CreateStatement << S; Session << Statement , Poco::Data::Keywords::now;
CreateStatement.execute();
return true;
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
std::cout << "Exception while creating DB: " << E.name() << std::endl; Logger_.error("Failure to create MySQL DB resources.");
Logger_.log(E);
} }
return false; }
break;
case OpenWifi::DBType::sqlite: {
try {
Poco::Data::Session Session = Pool_.get();
std::string Statement = "create table if not exists " + TableName_ + " ( " + CreateFields_ + " )";
Session << Statement , Poco::Data::Keywords::now;
for(const auto &i:IndexCreation_) {
Session << i , Poco::Data::Keywords::now;
}
} catch (const Poco::Exception &E) {
Logger_.error("Failure to create SQLITE DB resources.");
Logger_.log(E);
}
}
break;
case OpenWifi::DBType::pgsql: {
try {
Poco::Data::Session Session = Pool_.get();
std::string Statement = "create table if not exists " + TableName_ + " ( " + CreateFields_ + " )";
Session << Statement , Poco::Data::Keywords::now;
for(const auto &i:IndexCreation_) {
Session << i , Poco::Data::Keywords::now;
}
} catch (const Poco::Exception &E) {
Logger_.error("Failure to create POSTGRESQL DB resources.");
Logger_.log(E);
}
}
break;
}
return Upgrade();
} }
[[nodiscard]] std::string ConvertParams(const std::string & S) const { [[nodiscard]] std::string ConvertParams(const std::string & S) const {
if(Type!=OpenWifi::DBType::pgsql) if(Type_!=OpenWifi::DBType::pgsql)
return S; return S;
std::string R; std::string R;
@@ -325,45 +375,59 @@ namespace ORM {
return R; return R;
} }
void Convert( RecordTuple &in , RecordType &out); void Convert( const RecordTuple &in , RecordType &out);
void Convert( RecordType &in , RecordTuple &out); void Convert( const RecordType &in , RecordTuple &out);
inline const std::string & Prefix() { return Prefix_; }; inline const std::string & Prefix() { return Prefix_; };
bool CreateRecord( RecordType & R) { bool CreateRecord( const RecordType & R) {
try { try {
Poco::Data::Session Session = Pool_.get(); Poco::Data::Session Session = Pool_.get();
Poco::Data::Statement Insert(Session); Poco::Data::Statement Insert(Session);
RecordTuple RT; RecordTuple RT;
Convert(R, RT); Convert(R, RT);
std::string St = "insert into " + DBName + " ( " + SelectFields_ + " ) values " + SelectList_; std::string St = "insert into " + TableName_ + " ( " + SelectFields_ + " ) values " + SelectList_;
Insert << ConvertParams(St) , Insert << ConvertParams(St) ,
Poco::Data::Keywords::use(RT); Poco::Data::Keywords::use(RT);
Insert.execute(); Insert.execute();
if(Cache_)
Cache_->Create(R);
return true; return true;
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger_.log(E); Logger_.log(E);
} }
return false; return false;
} }
template<typename T> bool GetRecord( const char * FieldName, T Value, RecordType & R) { template<typename T> bool GetRecord(field_name_t FieldName, const T & Value, RecordType & R) {
try { try {
assert( FieldNames_.find(FieldName) != FieldNames_.end() ); assert( FieldNames_.find(FieldName) != FieldNames_.end() );
if(Cache_) {
if(Cache_->GetFromCache(FieldName, Value, R))
return true;
}
Poco::Data::Session Session = Pool_.get(); Poco::Data::Session Session = Pool_.get();
Poco::Data::Statement Select(Session); Poco::Data::Statement Select(Session);
RecordTuple RT; RecordTuple RT;
std::string St = "select " + SelectFields_ + " from " + DBName + " where " + FieldName + "=?" ; std::string St = "select " + SelectFields_ + " from " + TableName_ + " where " + FieldName + "=?" ;
auto tValue{Value};
Select << ConvertParams(St) , Select << ConvertParams(St) ,
Poco::Data::Keywords::into(RT), Poco::Data::Keywords::into(RT),
Poco::Data::Keywords::use(Value); Poco::Data::Keywords::use(tValue);
if(Select.execute()==1) { Select.execute();
if(Select.rowsExtracted()==1) {
Convert(RT,R); Convert(RT,R);
if(Cache_)
Cache_->UpdateCache(R);
return true; return true;
} }
return false; return false;
@@ -376,7 +440,7 @@ namespace ORM {
typedef std::vector<std::string> StringVec; typedef std::vector<std::string> StringVec;
template < typename T, template < typename T,
typename T0, typename T1> bool GR(const char *FieldName, T & R,T0 &V0, T1 &V1) { typename T0, typename T1> bool GR(field_name_t FieldName, T & R,T0 &V0, T1 &V1) {
try { try {
assert( FieldNames_.find(FieldName) != FieldNames_.end() ); assert( FieldNames_.find(FieldName) != FieldNames_.end() );
@@ -385,7 +449,7 @@ namespace ORM {
Poco::Data::Statement Select(Session); Poco::Data::Statement Select(Session);
RecordTuple RT; RecordTuple RT;
std::string St = "select " + SelectFields_ + " from " + DBName std::string St = "select " + SelectFields_ + " from " + TableName_
+ " where " + FieldName[0] + "=? and " + FieldName[1] + "=?" ; + " where " + FieldName[0] + "=? and " + FieldName[1] + "=?" ;
Select << ConvertParams(St) , Select << ConvertParams(St) ,
Poco::Data::Keywords::into(RT), Poco::Data::Keywords::into(RT),
@@ -410,14 +474,15 @@ namespace ORM {
Poco::Data::Session Session = Pool_.get(); Poco::Data::Session Session = Pool_.get();
Poco::Data::Statement Select(Session); Poco::Data::Statement Select(Session);
RecordList RL; RecordList RL;
std::string St = "select " + SelectFields_ + " from " + DBName + std::string St = "select " + SelectFields_ + " from " + TableName_ +
(Where.empty() ? "" : " where " + Where) + OrderBy + (Where.empty() ? "" : " where " + Where) + OrderBy +
ComputeRange(Offset, HowMany) ; ComputeRange(Offset, HowMany) ;
Select << St , Select << St ,
Poco::Data::Keywords::into(RL); Poco::Data::Keywords::into(RL);
Select.execute();
if(Select.execute()>0) { if(Select.rowsExtracted()>0) {
for(auto &i:RL) { for(auto &i:RL) {
RecordType R; RecordType R;
Convert(i, R); Convert(i, R);
@@ -432,7 +497,7 @@ namespace ORM {
return false; return false;
} }
template <typename T> bool UpdateRecord( const char *FieldName, T & Value, RecordType & R) { template <typename T> bool UpdateRecord(field_name_t FieldName, const T & Value, const RecordType & R) {
try { try {
assert( FieldNames_.find(FieldName) != FieldNames_.end() ); assert( FieldNames_.find(FieldName) != FieldNames_.end() );
@@ -443,11 +508,15 @@ namespace ORM {
Convert(R, RT); Convert(R, RT);
std::string St = "update " + DBName + " set " + UpdateFields_ + " where " + FieldName + "=?" ; auto tValue(Value);
std::string St = "update " + TableName_ + " set " + UpdateFields_ + " where " + FieldName + "=?" ;
Update << ConvertParams(St) , Update << ConvertParams(St) ,
Poco::Data::Keywords::use(RT), Poco::Data::Keywords::use(RT),
Poco::Data::Keywords::use(Value); Poco::Data::Keywords::use(tValue);
Update.execute(); Update.execute();
if(Cache_)
Cache_->UpdateCache(R);
return true; return true;
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger_.log(E); Logger_.log(E);
@@ -455,18 +524,32 @@ namespace ORM {
return false; return false;
} }
template <typename T> bool GetNameAndDescription(const char *FieldName, T & Value, std::string & Name, std::string & Description ) { template <typename T> bool ReplaceRecord(field_name_t FieldName, const T & Value, RecordType & R) {
try {
if(Exists(FieldName, Value)) {
return UpdateRecord(FieldName,Value,R);
}
return CreateRecord(R);
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
return false;
}
template <typename T> bool GetNameAndDescription(field_name_t FieldName, const T & Value, std::string & Name, std::string & Description ) {
try { try {
assert( FieldNames_.find(FieldName) != FieldNames_.end() ); assert( FieldNames_.find(FieldName) != FieldNames_.end() );
Poco::Data::Session Session = Pool_.get(); Poco::Data::Session Session = Pool_.get();
Poco::Data::Statement Select(Session); Poco::Data::Statement Select(Session);
RecordTuple RT; RecordTuple RT;
std::string St = "select " + SelectFields_ + " from " + DBName + " where " + FieldName + "=?" ; std::string St = "select " + SelectFields_ + " from " + TableName_ + " where " + FieldName + "=?" ;
RecordType R; RecordType R;
auto tValue{Value};
Select << ConvertParams(St) , Select << ConvertParams(St) ,
Poco::Data::Keywords::into(RT), Poco::Data::Keywords::into(RT),
Poco::Data::Keywords::use(Value); Poco::Data::Keywords::use(tValue);
if(Select.execute()==1) { if(Select.execute()==1) {
Convert(RT,R); Convert(RT,R);
Name = R.info.name; Name = R.info.name;
@@ -480,17 +563,21 @@ namespace ORM {
return false; return false;
} }
template <typename T> bool DeleteRecord( const char *FieldName, T Value) { template <typename T> bool DeleteRecord(field_name_t FieldName, const T & Value) {
try { try {
assert( FieldNames_.find(FieldName) != FieldNames_.end() ); assert( FieldNames_.find(FieldName) != FieldNames_.end() );
Poco::Data::Session Session = Pool_.get(); Poco::Data::Session Session = Pool_.get();
Poco::Data::Statement Delete(Session); Poco::Data::Statement Delete(Session);
std::string St = "delete from " + DBName + " where " + FieldName + "=?" ; std::string St = "delete from " + TableName_ + " where " + FieldName + "=?" ;
auto tValue{Value};
Delete << ConvertParams(St) , Delete << ConvertParams(St) ,
Poco::Data::Keywords::use(Value); Poco::Data::Keywords::use(tValue);
Delete.execute(); Delete.execute();
if(Cache_)
Cache_->Delete(FieldName, Value);
return true; return true;
} catch (const Poco::Exception &E) { } catch (const Poco::Exception &E) {
Logger_.log(E); Logger_.log(E);
@@ -504,7 +591,7 @@ namespace ORM {
Poco::Data::Session Session = Pool_.get(); Poco::Data::Session Session = Pool_.get();
Poco::Data::Statement Delete(Session); Poco::Data::Statement Delete(Session);
std::string St = "delete from " + DBName + " where " + WhereClause; std::string St = "delete from " + TableName_ + " where " + WhereClause;
Delete << St; Delete << St;
Delete.execute(); Delete.execute();
return true; return true;
@@ -514,7 +601,7 @@ namespace ORM {
return false; return false;
} }
bool Exists(const char *FieldName, std::string & Value) { bool Exists(field_name_t FieldName, const std::string & Value) {
try { try {
assert( FieldNames_.find(FieldName) != FieldNames_.end() ); assert( FieldNames_.find(FieldName) != FieldNames_.end() );
@@ -528,15 +615,15 @@ namespace ORM {
return false; return false;
} }
bool Iterate( std::function<bool(const RecordType &R)> F) { bool Iterate( std::function<bool(const RecordType &R)> F, const std::string & WhereClause = "" ) {
try { try {
uint64_t Offset=1; uint64_t Offset=0;
uint64_t Batch=50; uint64_t Batch=50;
bool Done=false; bool Done=false;
while(!Done) { while(!Done) {
std::vector<RecordType> Records; std::vector<RecordType> Records;
if(GetRecords(Offset,Batch,Records)) { if(GetRecords(Offset,Batch,Records, WhereClause)) {
for(const auto &i:Records) { for(const auto &i:Records) {
if(!F(i)) if(!F(i))
return true; return true;
@@ -592,7 +679,7 @@ namespace ORM {
Poco::Data::Session Session = Pool_.get(); Poco::Data::Session Session = Pool_.get();
Poco::Data::Statement Select(Session); Poco::Data::Statement Select(Session);
std::string st{"SELECT COUNT(*) FROM " + DBName + " " + (Where.empty() ? "" : (" where " + Where)) }; std::string st{"SELECT COUNT(*) FROM " + TableName_ + " " + (Where.empty() ? "" : (" where " + Where)) };
Select << st , Select << st ,
Poco::Data::Keywords::into(Cnt); Poco::Data::Keywords::into(Cnt);
@@ -606,7 +693,7 @@ namespace ORM {
return 0; return 0;
} }
template <typename X> bool ManipulateVectorMember( X T, const char *FieldName, std::string & ParentUUID, std::string & ChildUUID, bool Add) { template <typename X> bool ManipulateVectorMember( X T, field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID, bool Add) {
try { try {
assert( FieldNames_.find(FieldName) != FieldNames_.end() ); assert( FieldNames_.find(FieldName) != FieldNames_.end() );
@@ -633,89 +720,122 @@ namespace ORM {
return false; return false;
} }
inline bool AddChild( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) { bool RunScript(const std::vector<std::string> & Statements, bool IgnoreExceptions=true) {
try {
Poco::Data::Session Session = Pool_.get();
Poco::Data::Statement Command(Session);
for(const auto &i:Statements) {
try {
Command << i, Poco::Data::Keywords::now;
} catch (const Poco::Exception &E) {
Logger_.log(E);
Logger_.error(Poco::format("The following statement '%s' generated an exception during a table upgrade. This maya or may not be a problem.", i));
}
if(!IgnoreExceptions) {
return false;
}
Command.reset(Session);
}
return true;
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
return false;
}
virtual uint32_t Version() {
return 0;
}
virtual bool Upgrade(uint32_t from, uint32_t &to) {
to = from;
return true;
}
inline bool AddChild(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
return ManipulateVectorMember(&RecordType::children, FieldName, ParentUUID, ChildUUID, true); return ManipulateVectorMember(&RecordType::children, FieldName, ParentUUID, ChildUUID, true);
} }
inline bool DeleteChild( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) { inline bool DeleteChild(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
return ManipulateVectorMember(&RecordType::children, FieldName, ParentUUID, ChildUUID, false); return ManipulateVectorMember(&RecordType::children, FieldName, ParentUUID, ChildUUID, false);
} }
inline bool AddLocation( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) { inline bool AddLocation(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
return ManipulateVectorMember(&RecordType::locations, FieldName, ParentUUID, ChildUUID, true); return ManipulateVectorMember(&RecordType::locations, FieldName, ParentUUID, ChildUUID, true);
} }
inline bool DeleteLocation( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) { inline bool DeleteLocation(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
return ManipulateVectorMember(&RecordType::locations, FieldName, ParentUUID, ChildUUID, false); return ManipulateVectorMember(&RecordType::locations, FieldName, ParentUUID, ChildUUID, false);
} }
inline bool AddContact( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) { inline bool AddContact(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
return ManipulateVectorMember(&RecordType::contacts, FieldName, ParentUUID, ChildUUID, true); return ManipulateVectorMember(&RecordType::contacts, FieldName, ParentUUID, ChildUUID, true);
} }
inline bool DeleteContact( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) { inline bool DeleteContact(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
return ManipulateVectorMember(&RecordType::contacts, FieldName, ParentUUID, ChildUUID, false); return ManipulateVectorMember(&RecordType::contacts, FieldName, ParentUUID, ChildUUID, false);
} }
inline bool AddVenue( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) { inline bool AddVenue(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
return ManipulateVectorMember(&RecordType::venues, FieldName, ParentUUID, ChildUUID, true); return ManipulateVectorMember(&RecordType::venues, FieldName, ParentUUID, ChildUUID, true);
} }
inline bool DeleteVenue( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) { inline bool DeleteVenue(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
return ManipulateVectorMember(&RecordType::venues, FieldName, ParentUUID, ChildUUID, false); return ManipulateVectorMember(&RecordType::venues, FieldName, ParentUUID, ChildUUID, false);
} }
inline bool AddDevice( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) { inline bool AddDevice(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
return ManipulateVectorMember(&RecordType::devices, FieldName, ParentUUID, ChildUUID, true); return ManipulateVectorMember(&RecordType::devices, FieldName, ParentUUID, ChildUUID, true);
} }
inline bool DeleteDevice( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) { inline bool DeleteDevice(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
return ManipulateVectorMember(&RecordType::devices, FieldName, ParentUUID, ChildUUID, false); return ManipulateVectorMember(&RecordType::devices, FieldName, ParentUUID, ChildUUID, false);
} }
inline bool AddEntity( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) { inline bool AddEntity(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
return ManipulateVectorMember(&RecordType::entities, FieldName, ParentUUID, ChildUUID, true); return ManipulateVectorMember(&RecordType::entities, FieldName, ParentUUID, ChildUUID, true);
} }
inline bool DeleteEntity( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) { inline bool DeleteEntity(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
return ManipulateVectorMember(&RecordType::entities, FieldName, ParentUUID, ChildUUID, false); return ManipulateVectorMember(&RecordType::entities, FieldName, ParentUUID, ChildUUID, false);
} }
inline bool AddUser( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) { inline bool AddUser(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
return ManipulateVectorMember(&RecordType::users, FieldName, ParentUUID, ChildUUID, true); return ManipulateVectorMember(&RecordType::users, FieldName, ParentUUID, ChildUUID, true);
} }
inline bool DelUser( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) { inline bool DelUser(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
return ManipulateVectorMember(&RecordType::users, FieldName, ParentUUID, ChildUUID, false); return ManipulateVectorMember(&RecordType::users, FieldName, ParentUUID, ChildUUID, false);
} }
inline bool AddInUse(const char *FieldName, std::string & ParentUUID, const std::string & Prefix, const std::string & ChildUUID) { inline bool AddInUse(field_name_t FieldName, std::string & ParentUUID, const std::string & Prefix, const std::string & ChildUUID) {
std::string FakeUUID{ Prefix + ":" + ChildUUID}; std::string FakeUUID{ Prefix + ":" + ChildUUID};
return ManipulateVectorMember(&RecordType::inUse,FieldName, ParentUUID, FakeUUID, true); return ManipulateVectorMember(&RecordType::inUse,FieldName, ParentUUID, FakeUUID, true);
} }
inline bool DeleteInUse(const char *FieldName, std::string & ParentUUID, const std::string & Prefix, const std::string & ChildUUID) { inline bool DeleteInUse(field_name_t FieldName, std::string & ParentUUID, const std::string & Prefix, const std::string & ChildUUID) {
std::string FakeUUID{ Prefix + ":" + ChildUUID}; std::string FakeUUID{ Prefix + ":" + ChildUUID};
return ManipulateVectorMember(&RecordType::inUse,FieldName, ParentUUID, FakeUUID, false); return ManipulateVectorMember(&RecordType::inUse,FieldName, ParentUUID, FakeUUID, false);
} }
inline bool DeleteContact(const char *FieldName, std::string & ParentUUID, const std::string & ChildUUID) { inline bool DeleteContact(field_name_t FieldName, std::string & ParentUUID, const std::string & ChildUUID) {
return ManipulateVectorMember(&RecordType::contacts,FieldName, ParentUUID, ChildUUID, false); return ManipulateVectorMember(&RecordType::contacts,FieldName, ParentUUID, ChildUUID, false);
} }
inline bool AddContact(const char *FieldName, std::string & ParentUUID, const std::string & ChildUUID) { inline bool AddContact(field_name_t FieldName, std::string & ParentUUID, const std::string & ChildUUID) {
return ManipulateVectorMember(&RecordType::contacts,FieldName, ParentUUID, ChildUUID, true); return ManipulateVectorMember(&RecordType::contacts,FieldName, ParentUUID, ChildUUID, true);
} }
inline bool DeleteLocation(const char *FieldName, std::string & ParentUUID, const std::string & ChildUUID) { inline bool DeleteLocation(field_name_t FieldName, std::string & ParentUUID, const std::string & ChildUUID) {
return ManipulateVectorMember(&RecordType::locations,FieldName, ParentUUID, ChildUUID, false); return ManipulateVectorMember(&RecordType::locations,FieldName, ParentUUID, ChildUUID, false);
} }
inline bool AddLocation(const char *FieldName, std::string & ParentUUID, const std::string & ChildUUID) { inline bool AddLocation(field_name_t FieldName, std::string & ParentUUID, const std::string & ChildUUID) {
return ManipulateVectorMember(&RecordType::locations,FieldName, ParentUUID, ChildUUID, true); return ManipulateVectorMember(&RecordType::locations,FieldName, ParentUUID, ChildUUID, true);
} }
inline bool GetInUse(const char *FieldName, std::string & UUID, std::vector<std::string> & UUIDs ) { inline bool GetInUse(field_name_t FieldName, const std::string & UUID, std::vector<std::string> & UUIDs ) {
RecordType R; RecordType R;
if(GetRecord(FieldName,UUID,R)) { if(GetRecord(FieldName,UUID,R)) {
UUIDs = R.inUse; UUIDs = R.inUse;
@@ -725,34 +845,41 @@ namespace ORM {
} }
[[nodiscard]] inline std::string ComputeRange(uint64_t From, uint64_t HowMany) { [[nodiscard]] inline std::string ComputeRange(uint64_t From, uint64_t HowMany) {
if(From<1) From=1; if(From<1) From=0;
switch(Type) { switch(Type_) {
case OpenWifi::DBType::sqlite: case OpenWifi::DBType::sqlite:
return " LIMIT " + std::to_string(From-1) + ", " + std::to_string(HowMany) + " "; return " LIMIT " + std::to_string(From) + ", " + std::to_string(HowMany) + " ";
case OpenWifi::DBType::pgsql: case OpenWifi::DBType::pgsql:
return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From-1) + " "; return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From) + " ";
case OpenWifi::DBType::mysql: case OpenWifi::DBType::mysql:
return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From-1) + " "; return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From) + " ";
default: default:
return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From-1) + " "; return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From) + " ";
} }
} }
Poco::Logger & Logger() { return Logger_; } Poco::Logger & Logger() { return Logger_; }
bool DeleteRecordsFromCache(const char *FieldName, const std::string &Value ) {
if(Cache_)
Cache_->Delete(FieldName, Value);
return true;
}
protected:
Poco::Data::SessionPool &Pool_;
Poco::Logger &Logger_;
std::string TableName_;
DBCache<RecordType> *Cache_= nullptr;
private: private:
OpenWifi::DBType Type; OpenWifi::DBType Type_;
std::string DBName;
std::string CreateFields_; std::string CreateFields_;
std::string SelectFields_; std::string SelectFields_;
std::string SelectList_; std::string SelectList_;
std::string UpdateFields_; std::string UpdateFields_;
std::string IndexCreation; std::vector<std::string> IndexCreation_;
std::map<std::string,int> FieldNames_; std::map<std::string,int> FieldNames_;
Poco::Data::SessionPool &Pool_;
Poco::Logger &Logger_;
std::string Prefix_; std::string Prefix_;
}; };
} }
#endif

View File

@@ -5,9 +5,7 @@
// Created by Stephane Bourque on 2021-03-04. // Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc. // Arilia Wireless Inc.
// //
#pragma once
#ifndef UCENTRALGW_UCENTRALPROTOCOL_H
#define UCENTRALGW_UCENTRALPROTOCOL_H
#include "Poco/String.h" #include "Poco/String.h"
@@ -40,6 +38,7 @@ namespace OpenWifi::uCentralProtocol {
static const char * LOGLINES = "loglines"; static const char * LOGLINES = "loglines";
static const char * SEVERITY = "severity"; static const char * SEVERITY = "severity";
static const char * ACTIVE = "active"; static const char * ACTIVE = "active";
static const char * OVERRIDEDFS = "override_dfs";
static const char * REBOOT = "reboot"; static const char * REBOOT = "reboot";
static const char * WHEN = "when"; static const char * WHEN = "when";
static const char * CONFIG = "config"; static const char * CONFIG = "config";
@@ -130,5 +129,3 @@ namespace OpenWifi::uCentralProtocol {
return ET_UNKNOWN; return ET_UNKNOWN;
}; };
} }
#endif // UCENTRALGW_UCENTRALPROTOCOL_H

13
src/ow_version.h.in Normal file
View File

@@ -0,0 +1,13 @@
//
// Created by stephane bourque on 2021-12-06.
//
#pragma once
#include <string>
namespace OW_VERSION {
inline static const std::string VERSION{"@CMAKE_PROJECT_VERSION@"};
inline static const std::string BUILD{"@BUILD_NUM@"};
inline static const std::string HASH{"@GIT_HASH@"};
}

View File

@@ -0,0 +1,119 @@
//
// Created by stephane bourque on 2021-12-29.
//
#include "orm_deviceInfo.h"
#include "StorageService.h"
/*
"serialNumber varchar(36) UNIQUE PRIMARY KEY, "
"revision varchar, "
"deviceType varchar, "
"endPoint varchar, "
"lastUpdate bigint, "
"status varchar "
*/
namespace OpenWifi {
static ORM::FieldVec DevicesDB_Fields{
ORM::Field{"serialNumber", 36, true},
ORM::Field{"revision", ORM::FieldType::FT_TEXT},
ORM::Field{"deviceType", ORM::FieldType::FT_TEXT},
ORM::Field{"endPoint", ORM::FieldType::FT_TEXT},
ORM::Field{"lastUpdate", ORM::FieldType::FT_BIGINT},
ORM::Field{"status", ORM::FieldType::FT_TEXT}
};
DevicesDB::DevicesDB(OpenWifi::DBType T,
Poco::Data::SessionPool &P, Poco::Logger &L) :
DB(T, "devices", DevicesDB_Fields,{}, P, L, "fdi") {
}
bool DevicesDB::SetDeviceRevision(std::string &SerialNumber, std::string & Revision, std::string & DeviceType, std::string &EndPoint) {
FMSObjects::DeviceConnectionInformation D;
if(GetRecord("serialNumber", SerialNumber, D)) {
if(D.revision!=Revision) {
StorageService()->HistoryDB().AddHistory(SerialNumber, DeviceType, D.revision, Revision);
}
D.revision = Revision;
D.deviceType = DeviceType;
D.endPoint = EndPoint;
D.status = "connected";
return UpdateRecord("serialNumber", SerialNumber, D);
} else {
FMSObjects::DeviceConnectionInformation DI{
.serialNumber = SerialNumber,
.revision = Revision,
.deviceType = DeviceType,
.endPoint = EndPoint,
.lastUpdate = (uint64_t)std::time(nullptr),
.status = "connected"};
return CreateRecord(DI);
}
}
bool DevicesDB::DeleteDevice( std::string & SerialNumber) {
return DeleteRecord("serialNumber", SerialNumber);
}
bool DevicesDB::SetDeviceDisconnected(std::string &SerialNumber, std::string &EndPoint) {
FMSObjects::DeviceConnectionInformation D;
if(GetRecord("serialNumber", SerialNumber, D)) {
D.status = "not connected";
D.endPoint = EndPoint;
return UpdateRecord("serialNumber", SerialNumber, D);
}
return false;
}
bool DevicesDB::GetDevices(uint64_t From, uint64_t HowMany, std::vector<FMSObjects::DeviceConnectionInformation> & Devices) {
return GetRecords(From, HowMany, Devices, "", " ORDER BY SerialNumber ASC ");
}
bool DevicesDB::GetDevice(std::string &SerialNumber, FMSObjects::DeviceConnectionInformation & Device) {
return GetRecord("serialNumber", SerialNumber, Device);
}
bool DevicesDB::GenerateDeviceReport(FMSObjects::DeviceReport &Report) {
Iterate([&Report](const FMSObjects::DeviceConnectionInformation &D) {
Report.numberOfDevices++;
UpdateCountedMap(Report.DeviceTypes_, D.deviceType);
UpdateCountedMap(Report.Revisions_, D.revision);
UpdateCountedMap(Report.Status_, D.status);
UpdateCountedMap(Report.EndPoints_, D.endPoint);
UpdateCountedMap(Report.OUI_, D.serialNumber.substr(0, 6));
FMSObjects::FirmwareAgeDetails Age;
if (StorageService()->FirmwaresDB().ComputeFirmwareAge(D.deviceType, D.revision, Age)) {
if (Age.latest) {
UpdateCountedMap(Report.UsingLatest_, D.revision);
} else if (Age.age == 0) {
UpdateCountedMap(Report.UnknownFirmwares_, D.revision);
} else {
UpdateCountedMap(Report.totalSecondsOld_,"total_seconds", Age.age);
}
}
return true;
});
return true;
}
}
template<> void ORM::DB<OpenWifi::DevicesRecordTuple, OpenWifi::FMSObjects::DeviceConnectionInformation>::Convert(const OpenWifi::DevicesRecordTuple &T, OpenWifi::FMSObjects::DeviceConnectionInformation &F ) {
F.serialNumber = T.get<0>();
F.revision = T.get<1>();
F.deviceType = T.get<2>();
F.endPoint = T.get<3>();
F.lastUpdate = T.get<4>();
F.status = T.get<5>();
}
template<> void ORM::DB<OpenWifi::DevicesRecordTuple, OpenWifi::FMSObjects::DeviceConnectionInformation>::Convert(const OpenWifi::FMSObjects::DeviceConnectionInformation &F, OpenWifi::DevicesRecordTuple &T ) {
T.set<0>(F.serialNumber);
T.set<1>(F.revision);
T.set<2>(F.deviceType);
T.set<3>(F.endPoint);
T.set<4>(F.lastUpdate);
T.set<5>(F.status);
}

View File

@@ -0,0 +1,34 @@
//
// Created by stephane bourque on 2021-12-29.
//
#pragma once
#include "framework/orm.h"
#include "RESTObjects/RESTAPI_FMSObjects.h"
namespace OpenWifi {
typedef Poco::Tuple<
std::string,
std::string,
std::string,
std::string,
uint64_t,
std::string> DevicesRecordTuple;
typedef std::vector<DevicesRecordTuple> DevicesRecordTupleList;
class DevicesDB : public ORM::DB<DevicesRecordTuple, FMSObjects::DeviceConnectionInformation> {
public:
DevicesDB(OpenWifi::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L);
bool SetDeviceRevision(std::string &SerialNumber, std::string & Revision, std::string & DeviceType, std::string &EndPoint);
bool DeleteDevice( std::string & SerialNumber);
bool SetDeviceDisconnected(std::string &SerialNumber, std::string &EndPoint);
bool GetDevices(uint64_t From, uint64_t HowMany, std::vector<FMSObjects::DeviceConnectionInformation> & Devices);
bool GetDevice(std::string &SerialNumber, FMSObjects::DeviceConnectionInformation & Device);
bool GenerateDeviceReport(FMSObjects::DeviceReport &Report);
private:
};
}

View File

@@ -0,0 +1,216 @@
//
// Created by stephane bourque on 2021-12-28.
//
#include "orm_firmwares.h"
#include "LatestFirmwareCache.h"
#include "ManifestCreator.h"
/*
"Id varchar(36) UNIQUE PRIMARY KEY, "
"release varchar, "
"deviceType varchar, "
"description varchar, "
"revision varchar, "
"uri varchar, "
"image varchar, "
"imageDate bigint, "
"size bigint, "
"downloadCount bigint, "
"firmwareHash varchar, "
"owner varchar, "
"location varchar, "
"uploader varchar, "
"digest varchar, "
"latest boolean, "
"notes text, "
"created bigint"
*/
namespace OpenWifi {
static ORM::FieldVec FirmwaresDB_Fields{
ORM::Field{"id", 36, true},
ORM::Field{"release", ORM::FieldType::FT_TEXT},
ORM::Field{"deviceType", ORM::FieldType::FT_TEXT},
ORM::Field{"description", ORM::FieldType::FT_TEXT},
ORM::Field{"revision", ORM::FieldType::FT_TEXT},
ORM::Field{"uri", ORM::FieldType::FT_TEXT},
ORM::Field{"image", ORM::FieldType::FT_TEXT},
ORM::Field{"imageDate", ORM::FieldType::FT_BIGINT},
ORM::Field{"size", ORM::FieldType::FT_BIGINT},
ORM::Field{"downloadCount", ORM::FieldType::FT_BIGINT},
ORM::Field{"firmwareHash", ORM::FieldType::FT_TEXT},
ORM::Field{"owner", ORM::FieldType::FT_TEXT},
ORM::Field{"location", ORM::FieldType::FT_TEXT},
ORM::Field{"uploader", ORM::FieldType::FT_TEXT},
ORM::Field{"digest", ORM::FieldType::FT_TEXT},
ORM::Field{"latest", ORM::FieldType::FT_BOOLEAN},
ORM::Field{"notes", ORM::FieldType::FT_TEXT},
ORM::Field{"created", ORM::FieldType::FT_BIGINT}
};
FirmwaresDB::FirmwaresDB(OpenWifi::DBType T,
Poco::Data::SessionPool &P, Poco::Logger &L) :
DB(T, "firmwares", FirmwaresDB_Fields,{}, P, L, "fws") {
}
bool FirmwaresDB::AddFirmware(FMSObjects::Firmware & F) {
// find the older software and change to latest = 0
F.id = MicroService::CreateUUID();
if (LatestFirmwareCache()->AddToCache(F.deviceType, F.revision, F.id, F.imageDate)) {
F.latest = true;
std::vector<FMSObjects::Firmware> Fs;
std::string WhereClause{" deviceType='" + F.deviceType + "' AND Latest=true "};
if (GetRecords(0, 200, Fs, WhereClause)) {
for (auto &i: Fs) {
i.latest = false;
UpdateRecord("id", i.id, i);
}
}
} else {
F.latest = false;
}
return CreateRecord(F);
}
bool FirmwaresDB::UpdateFirmware(std::string & Id, FMSObjects::Firmware & F) {
return UpdateRecord("id",Id, F);
}
bool FirmwaresDB::DeleteFirmware(std::string & Id) {
return DeleteRecord("id", Id);
}
void FirmwaresDB::RemoveOldFirmware() {
uint64_t Limit = std::time(nullptr) - ManifestCreator()->MaxAge();
std::string WhereClause{"imageDate < " + std::to_string(Limit)};
DeleteRecords(WhereClause);
}
bool FirmwaresDB::GetFirmware(std::string & Id, FMSObjects::Firmware & F) {
return GetRecord("id", Id, F);
}
bool FirmwaresDB::GetFirmwareByName(const std::string & Release, const std::string &DeviceType, FMSObjects::Firmware & Firmware ) {
std::string WhereClause{" release='" + Release + "' and DeviceType='" + DeviceType + "' "};
std::vector<FMSObjects::Firmware> Fs;
if(GetRecords(0,2,Fs,WhereClause)) {
Firmware = Fs[0];
return true;
}
return false;
}
bool FirmwaresDB::GetFirmwareByRevision(const std::string & Revision, const std::string &DeviceType,FMSObjects::Firmware & Firmware ) {
std::string WhereClause{" Revision='" + Revision + "' and DeviceType='" + DeviceType + "' "};
std::vector<FMSObjects::Firmware> Fs;
if (GetRecords(0, 2, Fs, WhereClause)) {
Firmware = Fs[0];
return true;
}
return false;
}
bool FirmwaresDB::GetFirmwares(uint64_t From, uint64_t HowMany, const std::string & Compatible, FMSObjects::FirmwareVec & Firmwares) {
if(Compatible.empty()) {
GetRecords(From, HowMany, Firmwares);
return true;
} else {
std::string WhereClause{ " DeviceType='" + Compatible + "' "};
GetRecords(From, HowMany, Firmwares, WhereClause);
return true;
}
}
void FirmwaresDB::PopulateLatestFirmwareCache() {
Iterate([](const OpenWifi::FMSObjects::Firmware &F){
LatestFirmwareCache()->AddToCache(F.deviceType, F.revision, F.id, F.imageDate);
return true;
});
}
bool FirmwaresDB::ComputeFirmwareAge(const std::string & DeviceType, const std::string & Revision, FMSObjects::FirmwareAgeDetails &AgeDetails) {
try {
FMSObjects::Firmware CurrentFirmware;
FMSObjects::Firmware LatestFirmware;
bool CurrentFirmwareExists = false;
if(GetFirmwareByRevision(Revision,DeviceType,CurrentFirmware)) {
CurrentFirmwareExists = true;
}
LatestFirmwareCacheEntry LE;
if(LatestFirmwareCache()->FindLatestFirmware(DeviceType,LE)) {
// std::cout << "LE.id" << LE.Id << std::endl;
if(GetFirmware(LE.Id, LatestFirmware)) {
AgeDetails.imageDate = LatestFirmware.imageDate;
AgeDetails.uri = LatestFirmware.uri;
AgeDetails.image = LatestFirmware.image;
AgeDetails.revision = LatestFirmware.revision;
AgeDetails.latestId = LatestFirmware.id;
// std::cout << " Revision='" << Revision << "'" << std::endl;
// std::cout << "LF Revision='" << LatestFirmware.revision << "'" << std::endl;
AgeDetails.latest = (Revision == LatestFirmware.revision);
// std::cout << "Latest=" << AgeDetails.latest << std::endl;
AgeDetails.age = CurrentFirmwareExists ? (LatestFirmware.imageDate - CurrentFirmware.imageDate) : 0;
//std::cout << "Revision: '" << Revision << "' vs '" << LatestFirmware.revision << "'" << std::endl;
//if (AgeDetails.latest)
// std::cout << "Found latest firmware" << std::endl;
return true;
} else {
// std::cout << "Cannot find firmware: " << LE.Id << std::endl;
}
}
} catch (const Poco::Exception &E) {
Logger().log(E);
}
return false;
}
}
template<> void ORM::DB<OpenWifi::FirmwaresRecordTuple, OpenWifi::FMSObjects::Firmware>::Convert(const OpenWifi::FirmwaresRecordTuple &T, OpenWifi::FMSObjects::Firmware &F ) {
F.id = T.get<0>();
F.release = T.get<1>();
F.deviceType = T.get<2>();
F.description = T.get<3>();
F.revision = T.get<4>();
F.uri = T.get<5>();
F.image = T.get<6>();
F.imageDate = T.get<7>();
F.size = T.get<8>();
F.downloadCount = T.get<9>();
F.firmwareHash = T.get<10>();
F.owner = T.get<11>();
F.location = T.get<12>();
F.uploader = T.get<13>();
F.digest = T.get<14>();
F.latest = T.get<15>();
F.notes = OpenWifi::RESTAPI_utils::to_object_array<OpenWifi::SecurityObjects::NoteInfo>(T.get<16>());
F.created = T.get<17>();
}
template<> void ORM::DB<OpenWifi::FirmwaresRecordTuple, OpenWifi::FMSObjects::Firmware>::Convert(const OpenWifi::FMSObjects::Firmware &F, OpenWifi::FirmwaresRecordTuple &T ) {
T.set<0>(F.id);
T.set<1>(F.release);
T.set<2>(F.deviceType);
T.set<3>(F.description);
T.set<4>(F.revision);
T.set<5>(F.uri);
T.set<6>(F.image);
T.set<7>(F.imageDate);
T.set<8>(F.size);
T.set<9>(F.downloadCount);
T.set<10>(F.firmwareHash);
T.set<11>(F.owner);
T.set<12>(F.location);
T.set<13>(F.uploader);
T.set<14>(F.digest);
T.set<15>(F.latest);
T.set<16>(OpenWifi::RESTAPI_utils::to_string(F.notes));
T.set<17>(F.created);
}

View File

@@ -0,0 +1,50 @@
//
// Created by stephane bourque on 2021-12-28.
//
#pragma once
#include "framework/orm.h"
#include "RESTObjects/RESTAPI_FMSObjects.h"
namespace OpenWifi {
typedef Poco::Tuple<
std::string,
std::string,
std::string,
std::string,
std::string,
std::string,
std::string,
uint64_t,
uint64_t,
uint64_t,
std::string,
std::string,
std::string,
std::string,
std::string,
bool,
std::string,
uint64_t> FirmwaresRecordTuple;
typedef std::vector <FirmwaresRecordTuple> FirmwaresRecordTupleList;
class FirmwaresDB : public ORM::DB<FirmwaresRecordTuple, FMSObjects::Firmware> {
public:
FirmwaresDB(OpenWifi::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L);
bool AddFirmware(FMSObjects::Firmware & F);
bool UpdateFirmware(std::string & ID, FMSObjects::Firmware & F);
bool DeleteFirmware(std::string & ID);
void RemoveOldFirmware();
bool GetFirmware(std::string & ID, FMSObjects::Firmware & F);
bool GetFirmwareByName(const std::string & Release, const std::string &DeviceType, FMSObjects::Firmware & Firmware );
bool GetFirmwareByRevision(const std::string & Revision, const std::string &DeviceType,FMSObjects::Firmware & Firmware );
bool GetFirmwares(uint64_t From, uint64_t HowMany, const std::string & Compatible, FMSObjects::FirmwareVec & Firmwares);
void PopulateLatestFirmwareCache();
bool ComputeFirmwareAge(const std::string & DeviceType, const std::string & Revision, FMSObjects::FirmwareAgeDetails &AgeDetails);
private:
};
}

View File

@@ -0,0 +1,97 @@
//
// Created by stephane bourque on 2021-12-28.
//
#include "orm_history.h"
#include "StorageService.h"
/*
"id varchar(36) UNIQUE PRIMARY KEY, "
"serialNumber varchar, "
"fromRelease varchar, "
"toRelease varchar, "
"commandUUID varchar, "
"revisionId varchar, "
"upgraded bigint "
*/
namespace OpenWifi {
static ORM::FieldVec HistoryDB_Fields{
ORM::Field{"id", 36, true},
ORM::Field{"serialNumber", ORM::FieldType::FT_TEXT},
ORM::Field{"fromRelease", ORM::FieldType::FT_TEXT},
ORM::Field{"toRelease", ORM::FieldType::FT_TEXT},
ORM::Field{"commandUUID", ORM::FieldType::FT_TEXT},
ORM::Field{"revisionId", ORM::FieldType::FT_TEXT},
ORM::Field{"upgraded", ORM::FieldType::FT_BIGINT}
};
HistoryDB::HistoryDB(OpenWifi::DBType T,
Poco::Data::SessionPool &P, Poco::Logger &L) :
DB(T, "history", HistoryDB_Fields,{}, P, L, "his") {
}
bool HistoryDB::GetHistory(const std::string &SerialNumber, uint64_t From, uint64_t HowMany,
FMSObjects::RevisionHistoryEntryVec &History) {
std::string WhereClause{" serialNumber='" + SerialNumber + "' "};
std::string OrderBy{ " order by upgraded DESC "};
return GetRecords(From, HowMany, History, WhereClause, OrderBy);
}
bool HistoryDB::AddHistory(FMSObjects::RevisionHistoryEntry &History) {
return CreateRecord(History);
}
bool HistoryDB::AddHistory(std::string &SerialNumber, std::string &DeviceType, std::string &PreviousRevision,
std::string &NewVersion) {
FMSObjects::RevisionHistoryEntry History{
.id = MicroService::CreateUUID(),
.serialNumber = SerialNumber,
.fromRelease = PreviousRevision,
.toRelease = NewVersion,
.upgraded = (uint64_t) std::time(nullptr)};
FMSObjects::Firmware F;
if (StorageService()->FirmwaresDB().GetFirmwareByRevision(NewVersion, DeviceType, F)) {
History.revisionId = F.id;
} else {
History.revisionId = "unknown";
}
return AddHistory(History);
}
bool HistoryDB::DeleteHistory(std::string &SerialNumber, std::string &Id) {
return DeleteRecord("id", Id);
}
bool HistoryDB::DeleteHistory(std::string &SerialNumber) {
std::string WhereClause{" serialNumber='" + SerialNumber + "' "};
return DeleteRecords(WhereClause);
}
}
template<> void ORM::DB<OpenWifi::HistoryRecordTuple, OpenWifi::FMSObjects::RevisionHistoryEntry>::Convert(const OpenWifi::HistoryRecordTuple &T, OpenWifi::FMSObjects::RevisionHistoryEntry &F ) {
F.id = T.get<0>();
F.serialNumber = T.get<1>();
F.fromRelease = T.get<2>();
F.toRelease = T.get<3>();
F.commandUUID = T.get<4>();
F.revisionId = T.get<5>();
F.upgraded = T.get<6>();
}
template<> void ORM::DB<OpenWifi::HistoryRecordTuple, OpenWifi::FMSObjects::RevisionHistoryEntry>::Convert(const OpenWifi::FMSObjects::RevisionHistoryEntry &F, OpenWifi::HistoryRecordTuple &T ) {
T.set<0>(F.id);
T.set<1>(F.serialNumber);
T.set<2>(F.fromRelease);
T.set<3>(F.toRelease);
T.set<4>(F.commandUUID);
T.set<5>(F.revisionId);
T.set<6>(F.upgraded);
}

36
src/storage/orm_history.h Normal file
View File

@@ -0,0 +1,36 @@
//
// Created by stephane bourque on 2021-12-28.
//
#pragma once
#include "framework/orm.h"
#include "RESTObjects/RESTAPI_FMSObjects.h"
namespace OpenWifi {
typedef Poco::Tuple<
std::string,
std::string,
std::string,
std::string,
std::string,
std::string,
uint64_t> HistoryRecordTuple;
typedef std::vector<HistoryRecordTuple> HistoryRecordTupleList;
class HistoryDB : public ORM::DB<HistoryRecordTuple, FMSObjects::RevisionHistoryEntry> {
public:
HistoryDB(OpenWifi::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L);
bool GetHistory(const std::string &SerialNumber, uint64_t From, uint64_t HowMany,
FMSObjects::RevisionHistoryEntryVec &History);
bool AddHistory(FMSObjects::RevisionHistoryEntry &History);
bool AddHistory(std::string &SerialNumber, std::string &DeviceType, std::string &PreviousRevision,
std::string &NewVersion);
bool DeleteHistory(std::string &SerialNumber, std::string &Id);
bool DeleteHistory(std::string &SerialNumber);
private:
};
}

View File

@@ -1,236 +0,0 @@
//
// Created by stephane bourque on 2021-07-16.
//
#include "storage_deviceInfo.h"
#include "StorageService.h"
#include "Poco/Data/RecordSet.h"
#include "LatestFirmwareCache.h"
/*
"serialNumber=?, "
"revision=?, "
"deviceType=?, "
"endPoint=?, "
"lastUpdate=?, "
"status=?
*/
namespace OpenWifi {
bool Convert(const DevicesRecord &T, FMSObjects::DeviceConnectionInformation & F) {
F.serialNumber = T.get<0>();
F.revision = T.get<1>();
F.deviceType = T.get<2>();
F.endPoint = T.get<3>();
F.lastUpdate = T.get<4>();
F.status = T.get<5>();
return true;
}
bool Convert(const FMSObjects::DeviceConnectionInformation & F, DevicesRecord & T) {
T.set<0>(F.serialNumber);
T.set<1>(F.revision);
T.set<2>(F.deviceType);
T.set<3>(F.endPoint);
T.set<4>(F.lastUpdate);
T.set<5>(F.status);
return true;
}
bool Storage::SetDeviceRevision(std::string &SerialNumber, std::string & Revision, std::string & DeviceType, std::string &EndPoint) {
try {
Poco::Data::Session Sess = Pool_->get();
DevicesRecordList Records;
std::string PreviousVersion;
bool DeviceExists=false;
try {
Poco::Data::Statement Select(Sess);
std::string St{"select " + DBFIELDS_DEVICES_SELECT + " from " + DBNAME_DEVICES + " where serialNumber=?"};
Select << ConvertParams(St) ,
Poco::Data::Keywords::into(Records),
Poco::Data::Keywords::use(SerialNumber);
Select.execute();
if(!Records.empty()) {
PreviousVersion = Records[0].get<1>();
DeviceExists = true;
}
} catch (const Poco::Exception &E) {
}
std::string Status{"connected"};
if(!DeviceExists) {
std::string st{"INSERT INTO " + DBNAME_DEVICES + " (" +
DBFIELDS_DEVICES_SELECT +
") VALUES(?,?,?,?,?,?)"};
Logger_.information(Poco::format("New device '%s' connected", SerialNumber));
FMSObjects::DeviceConnectionInformation DI{
.serialNumber = SerialNumber,
.revision = Revision,
.deviceType = DeviceType,
.endPoint = EndPoint,
.lastUpdate = (uint64_t)std::time(nullptr),
.status = Status};
Poco::Data::Statement Insert(Sess);
DevicesRecordList InsertRecords;
DevicesRecord R;
Convert(DI, R);
InsertRecords.push_back(R);
Insert << ConvertParams(st),
Poco::Data::Keywords::use(InsertRecords);
Insert.execute();
} else {
Poco::Data::Statement Update(Sess);
auto Now = (uint64_t)std::time(nullptr);
// std::cout << "Updating device: " << SerialNumber << std::endl;
std::string st{"UPDATE " + DBNAME_DEVICES + " set revision=?, lastUpdate=?, endpoint=?, status=? " + " where serialNumber=?"};
Update << ConvertParams(st) ,
Poco::Data::Keywords::use(Revision),
Poco::Data::Keywords::use(Now),
Poco::Data::Keywords::use(EndPoint),
Poco::Data::Keywords::use(Status),
Poco::Data::Keywords::use(SerialNumber);
Update.execute();
if(PreviousVersion!=Revision) {
AddHistory(SerialNumber, DeviceType, PreviousVersion, Revision);
}
}
return true;
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
return false;
}
bool Storage::SetDeviceDisconnected(std::string &SerialNumber, std::string &EndPoint) {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Update(Sess);
uint64_t Now = (uint64_t)std::time(nullptr);
std::string Status{"not connected"};
// std::cout << "Updating device: " << SerialNumber << std::endl;
std::string st{"UPDATE " + DBNAME_DEVICES + " set lastUpdate=?, endpoint=?, status=? " + " where serialNumber=?"};
Update << ConvertParams(st) ,
Poco::Data::Keywords::use(Now),
Poco::Data::Keywords::use(EndPoint),
Poco::Data::Keywords::use(Status),
Poco::Data::Keywords::use(SerialNumber);
Update.execute();
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
return false;
}
bool Storage::GetDevices(uint64_t From, uint64_t HowMany, std::vector<FMSObjects::DeviceConnectionInformation> & Devices) {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Select(Sess);
DevicesRecordList Records;
std::string St{"select " + DBFIELDS_DEVICES_SELECT + " from " + DBNAME_DEVICES + " ORDER BY SerialNumber ASC "};
Select << ConvertParams(St) + ComputeRange(From, HowMany),
Poco::Data::Keywords::into(Records);
Select.execute();
for(const auto &i:Records) {
FMSObjects::DeviceConnectionInformation DI;
Convert(i,DI);
Devices.push_back(DI);
}
return true;
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
return false;
}
bool Storage::GetDevice(std::string &SerialNumber, FMSObjects::DeviceConnectionInformation & Device) {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Select(Sess);
DevicesRecordList Records;
std::string St{"select " + DBFIELDS_DEVICES_SELECT + " from " + DBNAME_DEVICES + " where serialNumber=?"};
Select << ConvertParams(St) ,
Poco::Data::Keywords::into(Records),
Poco::Data::Keywords::use(SerialNumber);
Select.execute();
if(!Records.empty()) {
Convert(Records[0],Device);
return true;
}
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
return false;
}
/*
"serialNumber, "
"revision, "
"deviceType, "
"endPoint, "
"lastUpdate, "
"status "
*/
bool Storage::GenerateDeviceReport(FMSObjects::DeviceReport &Report) {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Select(Sess);
Report.reset();
Select << "SELECT " + DBFIELDS_DEVICES_SELECT + " from " + DBNAME_DEVICES;
Select.execute();
Poco::Data::RecordSet RSet(Select);
bool More = RSet.moveFirst();
while(More) {
Report.numberOfDevices++;
auto SerialNumber = RSet[0].convert<std::string>();
auto Revision = RSet[1].convert<std::string>();
auto DeviceType = RSet[2].convert<std::string>();
auto EndPoint = RSet[3].convert<std::string>();
auto Status = RSet[5].convert<std::string>();
// find the real revision for this device...
Types::UpdateCountedMap(Report.DeviceTypes_, DeviceType);
Types::UpdateCountedMap(Report.Revisions_, Revision);
Types::UpdateCountedMap(Report.Status_, Status);
Types::UpdateCountedMap(Report.EndPoints_, EndPoint);
Types::UpdateCountedMap(Report.OUI_, SerialNumber.substr(0, 6));
FMSObjects::FirmwareAgeDetails Age;
if (ComputeFirmwareAge(DeviceType, Revision, Age)) {
if (Age.latest) {
Types::UpdateCountedMap(Report.UsingLatest_, Revision);
} else if (Age.age == 0) {
Types::UpdateCountedMap(Report.UnknownFirmwares_, Revision);
} else {
Types::UpdateCountedMap(Report.totalSecondsOld_,"total_seconds", Age.age);
}
}
More = RSet.moveNext();
}
return true;
} catch( const Poco::Exception &E) {
Logger_.log(E);
}
return false;
}
}

View File

@@ -1,51 +0,0 @@
//
// Created by stephane bourque on 2021-07-16.
//
#ifndef UCENTRALFMS_STORAGE_DEVICEINFO_H
#define UCENTRALFMS_STORAGE_DEVICEINFO_H
#include "StorageService.h"
namespace OpenWifi {
static const std::string DBNAME_DEVICES{"devices"};
static const std::string DBFIELDS_DEVICES_CREATION {
"serialNumber varchar(36) UNIQUE PRIMARY KEY, "
"revision varchar, "
"deviceType varchar, "
"endPoint varchar, "
"lastUpdate bigint, "
"status varchar "
};
static const std::string DBFIELDS_DEVICES_SELECT{
"serialNumber, "
"revision, "
"deviceType, "
"endPoint, "
"lastUpdate, "
"status "
};
static const std::string DBFIELDS_DEVICES_UPDATE {
"serialNumber=?, "
"revision=?, "
"deviceType=?, "
"endPoint=?, "
"lastUpdate=?, "
"status=? "
};
typedef Poco::Tuple<
std::string,
std::string,
std::string,
std::string,
uint64_t,
std::string> DevicesRecord;
typedef std::vector<DevicesRecord> DevicesRecordList;
}
#endif //UCENTRALFMS_STORAGE_DEVICEINFO_H

View File

@@ -1,5 +0,0 @@
//
// Created by stephane bourque on 2021-07-12.
//
#include "storage_deviceTypes.h"

View File

@@ -1,47 +0,0 @@
//
// Created by stephane bourque on 2021-07-12.
//
#ifndef UCENTRALFMS_STORAGE_DEVICETYPES_H
#define UCENTRALFMS_STORAGE_DEVICETYPES_H
#include <string>
namespace OpenWifi {
static const std::string DBNAME_DEVICETYPES{"deviceTypes"};
static const std::string DBFIELDS_DEVICETYPES_CREATION {
" id varchar(36) UNIQUE PRIMARY KEY, "
"deviceType varchar, "
"manufacturer varchar, "
"model varchar, "
"policy varchar, "
"notes varchar, "
"lastUpdate bigint, "
"created bigint "
};
static const std::string DBFIELDS_DEVICETYPES_SELECT{
" id, "
"deviceType, "
"manufacturer, "
"model, "
"policy, "
"notes, "
"lastUpdate, "
"created "
};
static const std::string DBFIELDS_DEVICETYPES_UPDATE {
" id=?, "
"deviceType=?, "
"manufacturer=?, "
"model=?, "
"policy=?, "
"notes=?, "
"lastUpdate=?, "
"created=? "
};
}
#endif //UCENTRALFMS_STORAGE_DEVICETYPES_H

View File

@@ -1,356 +0,0 @@
//
// Created by stephane bourque on 2021-05-09.
//
#include <limits>
#include "StorageService.h"
#include "RESTObjects/RESTAPI_FMSObjects.h"
#include "LatestFirmwareCache.h"
#include "ManifestCreator.h"
namespace OpenWifi {
bool Convert(const FirmwaresRecord &T, FMSObjects::Firmware & F) {
F.id = T.get<0>();
F.release = T.get<1>();
F.deviceType = T.get<2>();
F.description = T.get<3>();
F.revision = T.get<4>();
F.uri = T.get<5>();
F.image = T.get<6>();
F.imageDate = T.get<7>();
F.size = T.get<8>();
F.downloadCount = T.get<9>();
F.firmwareHash = T.get<10>();
F.owner = T.get<11>();
F.location = T.get<12>();
F.uploader = T.get<13>();
F.digest = T.get<14>();
F.latest = T.get<15>();
F.notes = RESTAPI_utils::to_object_array<SecurityObjects::NoteInfo>(T.get<16>());
F.created = T.get<17>();
return true;
}
bool Convert(const FMSObjects::Firmware & F, FirmwaresRecord & T) {
T.set<0>(F.id);
T.set<1>(F.release);
T.set<2>(F.deviceType);
T.set<3>(F.description);
T.set<4>(F.revision);
T.set<5>(F.uri);
T.set<6>(F.image);
T.set<7>(F.imageDate);
T.set<8>(F.size);
T.set<9>(F.downloadCount);
T.set<10>(F.firmwareHash);
T.set<11>(F.owner);
T.set<12>(F.location);
T.set<13>(F.uploader);
T.set<14>(F.digest);
T.set<15>(F.latest);
T.set<16>(RESTAPI_utils::to_string(F.notes));
T.set<17>(F.created);
return true;
}
bool Storage::AddFirmware(FMSObjects::Firmware & F) {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Insert(Sess);
// find the older software and change to latest = 0
F.id = MicroService::CreateUUID();
if(LatestFirmwareCache()->AddToCache(F.deviceType,F.revision,F.id,F.imageDate)) {
F.latest = true ;
Poco::Data::Statement Update(Sess);
std::string st{"UPDATE " + DBNAME_FIRMWARES + " SET latest=0 WHERE deviceType=? AND Latest=1"};
Update << ConvertParams(st),
Poco::Data::Keywords::use(F.deviceType);
Update.execute();
} else {
F.latest = false;
}
auto Notes = RESTAPI_utils::to_string(F.notes);
std::string st{"INSERT INTO " + DBNAME_FIRMWARES + " (" +
DBFIELDS_FIRMWARES_SELECT +
") VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"};
Insert << ConvertParams(st),
Poco::Data::Keywords::use(F.id),
Poco::Data::Keywords::use(F.release),
Poco::Data::Keywords::use(F.deviceType),
Poco::Data::Keywords::use(F.description),
Poco::Data::Keywords::use(F.revision),
Poco::Data::Keywords::use(F.uri),
Poco::Data::Keywords::use(F.image),
Poco::Data::Keywords::use(F.imageDate),
Poco::Data::Keywords::use(F.size),
Poco::Data::Keywords::use(F.downloadCount),
Poco::Data::Keywords::use(F.firmwareHash),
Poco::Data::Keywords::use(F.owner),
Poco::Data::Keywords::use(F.location),
Poco::Data::Keywords::use(F.uploader),
Poco::Data::Keywords::use(F.digest),
Poco::Data::Keywords::use(F.latest),
Poco::Data::Keywords::use(Notes),
Poco::Data::Keywords::use(F.created);
Insert.execute();
return true;
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
return false;
}
bool Storage::UpdateFirmware(std::string & ID, FMSObjects::Firmware & F) {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Update(Sess);
std::string st{"UPDATE " + DBNAME_FIRMWARES + " set " + DBFIELDS_FIRMWARES_UPDATE +
" WHERE id=?"};
auto Notes = RESTAPI_utils::to_string(F.notes);
Update << ConvertParams(st),
Poco::Data::Keywords::use(F.id),
Poco::Data::Keywords::use(F.release),
Poco::Data::Keywords::use(F.deviceType),
Poco::Data::Keywords::use(F.description),
Poco::Data::Keywords::use(F.revision),
Poco::Data::Keywords::use(F.uri),
Poco::Data::Keywords::use(F.image),
Poco::Data::Keywords::use(F.imageDate),
Poco::Data::Keywords::use(F.size),
Poco::Data::Keywords::use(F.downloadCount),
Poco::Data::Keywords::use(F.firmwareHash),
Poco::Data::Keywords::use(F.owner),
Poco::Data::Keywords::use(F.location),
Poco::Data::Keywords::use(F.uploader),
Poco::Data::Keywords::use(F.digest),
Poco::Data::Keywords::use(F.latest),
Poco::Data::Keywords::use(Notes),
Poco::Data::Keywords::use(F.created),
Poco::Data::Keywords::use(ID);
Update.execute();
return true;
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
return false;
}
bool Storage::DeleteFirmware(std::string & ID) {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Delete(Sess);
std::string st{"DELETE FROM " + DBNAME_FIRMWARES + " WHERE id=?"};
Delete << ConvertParams(st),
Poco::Data::Keywords::use(ID);
Delete.execute();
return true;
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
return false;
}
void Storage::RemoveOldFirmware() {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Delete(Sess);
std::cout << "Removing old firmware..." << std::endl;
uint64_t Limit = std::time(nullptr) - ManifestCreator()->MaxAge();
std::string st{"DELETE FROM " + DBNAME_FIRMWARES + " WHERE imageDate<?"};
Delete << ConvertParams(st),
Poco::Data::Keywords::use(Limit);
Delete.execute();
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
}
bool Storage::GetFirmware(std::string & ID, FMSObjects::Firmware & F) {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Select(Sess);
std::string st{"SELECT " + DBFIELDS_FIRMWARES_SELECT +
" FROM " + DBNAME_FIRMWARES + " WHERE id=?"};
FirmwaresRecordList Records;
Select << ConvertParams(st),
Poco::Data::Keywords::into(Records),
Poco::Data::Keywords::use(ID);
Select.execute();
if(Records.empty())
return false;
Convert(Records[0],F);
return true;
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
return false;
}
bool Storage::GetFirmwareByName( std::string & Release, std::string &DeviceType, FMSObjects::Firmware & Firmware ) {
try {
FirmwaresRecordList Records;
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Select(Sess);
std::string st{"SELECT " + DBFIELDS_FIRMWARES_SELECT +
" FROM " + DBNAME_FIRMWARES + " where release=? and DeviceType=?"};
Select << ConvertParams(st),
Poco::Data::Keywords::into(Records),
Poco::Data::Keywords::use(Release),
Poco::Data::Keywords::use(DeviceType);
Select.execute();
if(Records.empty())
return false;
Convert(Records[0],Firmware);
return true;
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
return false;
}
bool Storage::GetFirmwareByRevision(std::string & Revision, std::string &DeviceType,FMSObjects::Firmware & Firmware ) {
try {
FirmwaresRecordList Records;
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Select(Sess);
std::string st{"SELECT " + DBFIELDS_FIRMWARES_SELECT +
" FROM " + DBNAME_FIRMWARES + " where Revision=? and DeviceType=?"};
Select << ConvertParams(st),
Poco::Data::Keywords::into(Records),
Poco::Data::Keywords::use(Revision),
Poco::Data::Keywords::use(DeviceType);
Select.execute();
if (Records.empty())
return false;
Convert(Records[0], Firmware);
return true;
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
return false;
}
bool Storage::GetFirmwares(uint64_t From, uint64_t HowMany, std::string & Compatible, FMSObjects::FirmwareVec & Firmwares) {
try {
FirmwaresRecordList Records;
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Select(Sess);
std::string st;
if(Compatible.empty()) {
st = "SELECT " + DBFIELDS_FIRMWARES_SELECT + " FROM " + DBNAME_FIRMWARES + " ORDER BY Id ASC ";
Select << ConvertParams(st) + ComputeRange(From, HowMany),
Poco::Data::Keywords::into(Records);
} else {
st = "SELECT " + DBFIELDS_FIRMWARES_SELECT + " FROM " + DBNAME_FIRMWARES + " where DeviceType=? ORDER BY Id ASC ";
Select << ConvertParams(st) + ComputeRange(From, HowMany),
Poco::Data::Keywords::into(Records),
Poco::Data::Keywords::use(Compatible);
}
Select.execute();
for(const auto &R:Records) {
FMSObjects::Firmware F;
Convert(R,F);
Firmwares.push_back(F);
}
return true;
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
return false;
}
void Storage::PopulateLatestFirmwareCache() {
try {
typedef Poco::Tuple<
std::string,
std::string,
uint64_t,
std::string> FCE;
typedef std::vector<FCE> FCEList;
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Select(Sess);
std::string st{"SELECT Id, DeviceType, ImageDate, Revision FROM " + DBNAME_FIRMWARES};
FCEList Records;
Select << ConvertParams(st),
Poco::Data::Keywords::into(Records);
Select.execute();
for(const auto &R:Records) {
LatestFirmwareCache()->AddToCache(R.get<1>(), R.get<3>(), R.get<0>(), R.get<2>());
}
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
}
bool Storage::ComputeFirmwareAge(std::string & DeviceType, std::string & Revision, FMSObjects::FirmwareAgeDetails &AgeDetails) {
try {
FMSObjects::Firmware CurrentFirmware;
FMSObjects::Firmware LatestFirmware;
bool CurrentFirmwareExists = false;
if(GetFirmwareByRevision(Revision,DeviceType,CurrentFirmware)) {
CurrentFirmwareExists = true;
}
LatestFirmwareCacheEntry LE;
if(LatestFirmwareCache()->FindLatestFirmware(DeviceType,LE)) {
// std::cout << "LE.id" << LE.Id << std::endl;
if(GetFirmware(LE.Id, LatestFirmware)) {
AgeDetails.imageDate = LatestFirmware.imageDate;
AgeDetails.uri = LatestFirmware.uri;
AgeDetails.image = LatestFirmware.image;
AgeDetails.revision = LatestFirmware.revision;
AgeDetails.latestId = LatestFirmware.id;
// std::cout << " Revision='" << Revision << "'" << std::endl;
// std::cout << "LF Revision='" << LatestFirmware.revision << "'" << std::endl;
AgeDetails.latest = (Revision == LatestFirmware.revision);
// std::cout << "Latest=" << AgeDetails.latest << std::endl;
AgeDetails.age = CurrentFirmwareExists ? (LatestFirmware.imageDate - CurrentFirmware.imageDate) : 0;
//std::cout << "Revision: '" << Revision << "' vs '" << LatestFirmware.revision << "'" << std::endl;
//if (AgeDetails.latest)
// std::cout << "Found latest firmware" << std::endl;
return true;
} else {
// std::cout << "Cannot find firmware: " << LE.Id << std::endl;
}
}
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
return false;
}
}

View File

@@ -1,97 +0,0 @@
//
// Created by stephane bourque on 2021-07-12.
//
#ifndef UCENTRALFMS_STORAGE_FIRMWARES_H
#define UCENTRALFMS_STORAGE_FIRMWARES_H
#include "Poco/Tuple.h"
namespace OpenWifi {
static const std::string DBNAME_FIRMWARES{"firmwares"};
static const std::string DBFIELDS_FIRMWARES_CREATION {
"Id varchar(36) UNIQUE PRIMARY KEY, "
"release varchar, "
"deviceType varchar, "
"description varchar, "
"revision varchar, "
"uri varchar, "
"image varchar, "
"imageDate bigint, "
"size bigint, "
"downloadCount bigint, "
"firmwareHash varchar, "
"owner varchar, "
"location varchar, "
"uploader varchar, "
"digest varchar, "
"latest int, "
"notes text, "
"created bigint"
};
static const std::string DBFIELDS_FIRMWARES_SELECT{
" Id, "
"release, "
"deviceType, "
"description, "
"revision, "
"uri, "
"image, "
"imageDate, "
"size, "
"downloadCount, "
"firmwareHash, "
"owner, "
"location, "
"uploader, "
"digest, "
"latest, "
"notes, "
"created "
};
static const std::string DBFIELDS_FIRMWARES_UPDATE {
" Id=?, "
"release=?, "
"deviceType=?, "
"description=?, "
"revision=?, "
"uri=?, "
"image=?, "
"imageDate=?, "
"size=?, "
"downloadCount=?, "
"firmwareHash=?, "
"owner=?, "
"location=?, "
"uploader=?, "
"digest=?, "
"latest=?, "
"notes=?, "
"created=? "
};
typedef Poco::Tuple<
std::string,
std::string,
std::string,
std::string,
std::string,
std::string,
std::string,
uint64_t,
uint64_t,
uint64_t,
std::string,
std::string,
std::string,
std::string,
std::string,
uint64_t,
std::string,
uint64_t> FirmwaresRecord;
typedef std::vector<FirmwaresRecord> FirmwaresRecordList;
}
#endif //UCENTRALFMS_STORAGE_FIRMWARES_H

View File

@@ -1,130 +0,0 @@
//
// Created by stephane bourque on 2021-07-12.
//
#include "StorageService.h"
#include "storage_history.h"
#include "RESTObjects/RESTAPI_FMSObjects.h"
#include "Daemon.h"
namespace OpenWifi {
/*
* " id, "
"serialNumber, "
"fromRelease, "
"toRelease, "
"commandUUID, "
"revisionId, "
"upgraded "
*/
bool Convert(const HistoryRecord &T, FMSObjects::RevisionHistoryEntry & F) {
F.id = T.get<0>();
F.serialNumber = T.get<1>();
F.fromRelease = T.get<2>();
F.toRelease = T.get<3>();
F.commandUUID = T.get<4>();
F.revisionId = T.get<5>();
F.upgraded = T.get<6>();
return true;
}
bool Convert(const FMSObjects::RevisionHistoryEntry & F, HistoryRecord & T) {
T.set<0>(F.id);
T.set<1>(F.serialNumber);
T.set<2>(F.fromRelease);
T.set<3>(F.toRelease);
T.set<4>(F.commandUUID);
T.set<5>(F.revisionId);
T.set<6>(F.upgraded);
return true;
}
bool Storage::GetHistory(std::string &SerialNumber,uint64_t From, uint64_t HowMany,FMSObjects::RevisionHistoryEntryVec &History) {
try {
HistoryRecordList Records;
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Select(Sess);
std::string st{"SELECT " + DBFIELDS_HISTORY_SELECT +
" FROM " + DBNAME_HISTORY + " where SerialNumber=? ORDER BY Upgraded DESC " };
Select << ConvertParams(st) + ComputeRange(From, HowMany),
Poco::Data::Keywords::into(Records),
Poco::Data::Keywords::use(SerialNumber);
Select.execute();
for(const auto &R:Records) {
FMSObjects::RevisionHistoryEntry F;
Convert(R,F);
History.push_back(F);
}
return true;
} catch(const Poco::Exception &E) {
Logger_.log(E);
}
return false;
}
bool Storage::AddHistory(FMSObjects::RevisionHistoryEntry &History) {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Insert(Sess);
std::string st{"INSERT INTO " + DBNAME_HISTORY + " (" + DBFIELDS_HISTORY_SELECT +
" ) values(?,?,?,?,?,?,?)" };
std::cout << "Adding history for " << History.serialNumber << std::endl;
HistoryRecordList RL;
HistoryRecord R;
Convert(History, R);
RL.push_back(R);
Insert << ConvertParams(st),
Poco::Data::Keywords::use(RL);
Insert.execute();
return true;
} catch(const Poco::Exception &E) {
Logger_.log(E);
}
return false;
}
bool Storage::AddHistory( std::string & SerialNumber, std::string &DeviceType, std::string & PreviousRevision, std::string & NewVersion) {
FMSObjects::RevisionHistoryEntry History{
.id = MicroService::CreateUUID(),
.serialNumber = SerialNumber,
.fromRelease = PreviousRevision,
.toRelease = NewVersion,
.upgraded = (uint64_t)std::time(nullptr)};
FMSObjects::Firmware F;
if(GetFirmwareByRevision(NewVersion,DeviceType,F)) {
History.revisionId = F.id;
} else {
History.revisionId = "unknown";
}
return AddHistory(History);
}
bool Storage::DeleteHistory( std::string & SerialNumber, std::string &Id) {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Delete(Sess);
std::string st{"DELETE FROM " + DBNAME_HISTORY + " where id=? and serialnumber=?"};
Delete << ConvertParams(st),
Poco::Data::Keywords::use(Id),
Poco::Data::Keywords::use(SerialNumber);
Delete.execute();
return true;
} catch(const Poco::Exception &E) {
Logger_.log(E);
}
return false;
}
}

View File

@@ -1,56 +0,0 @@
//
// Created by stephane bourque on 2021-07-12.
//
#ifndef UCENTRALFMS_STORAGE_HISTORY_H
#define UCENTRALFMS_STORAGE_HISTORY_H
#include <string>
#include "Poco/Tuple.h"
namespace OpenWifi {
static const std::string DBNAME_HISTORY{"history"};
static const std::string DBFIELDS_HISTORY_CREATION {
" id varchar(36) UNIQUE PRIMARY KEY, "
"serialNumber varchar, "
"fromRelease varchar, "
"toRelease varchar, "
"commandUUID varchar, "
"revisionId varchar, "
"upgraded bigint "
};
static const std::string DBFIELDS_HISTORY_SELECT{
" id, "
"serialNumber, "
"fromRelease, "
"toRelease, "
"commandUUID, "
"revisionId, "
"upgraded "
};
static const std::string DBFIELDS_HISTORY_UPDATE {
" id=?, "
"serialNumber=?, "
"fromRelease=?, "
"toRelease=?, "
"commandUUID=?, "
"revisionId=?, "
"upgraded=? "
};
typedef Poco::Tuple<
std::string,
std::string,
std::string,
std::string,
std::string,
std::string,
uint64_t> HistoryRecord;
typedef std::vector<HistoryRecord> HistoryRecordList;
}
#endif //UCENTRALFMS_STORAGE_HISTORY_H

View File

@@ -1,106 +0,0 @@
//
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#include "StorageService.h"
namespace OpenWifi {
int Storage::Create_Tables() {
Create_Firmwares();
Create_History();
Create_DeviceTypes();
Create_DeviceInfo();
return 0;
}
int Storage::Create_Firmwares() {
try {
Poco::Data::Session Sess = Pool_->get();
if(dbType_==mysql) {
Sess << "CREATE TABLE IF NOT EXISTS " + DBNAME_FIRMWARES + " (" +
DBFIELDS_FIRMWARES_CREATION +
")",
Poco::Data::Keywords::now;
} else {
Sess << "CREATE TABLE IF NOT EXISTS " + DBNAME_FIRMWARES + " (" +
DBFIELDS_FIRMWARES_CREATION +
")",
Poco::Data::Keywords::now;
}
return 0;
} catch(const Poco::Exception &E) {
Logger_.log(E);
}
return -1;
}
int Storage::Create_History() {
try {
Poco::Data::Session Sess = Pool_->get();
if(dbType_==mysql) {
Sess << "CREATE TABLE IF NOT EXISTS " + DBNAME_HISTORY + " (" +
DBFIELDS_HISTORY_CREATION +
",INDEX Serial (SerialNumber ASC, upgraded ASC))"
, Poco::Data::Keywords::now;
} else {
Sess << "CREATE TABLE IF NOT EXISTS " + DBNAME_HISTORY + " (" +
DBFIELDS_HISTORY_CREATION +
")",
Poco::Data::Keywords::now;
Sess << "CREATE INDEX IF NOT EXISTS Serial ON " + DBNAME_HISTORY + " (SerialNumber ASC, upgraded ASC)", Poco::Data::Keywords::now;
}
return 0;
} catch(const Poco::Exception &E) {
Logger_.log(E);
}
return -1;
}
int Storage::Create_DeviceTypes() {
try {
Poco::Data::Session Sess = Pool_->get();
if(dbType_==mysql) {
Sess << "CREATE TABLE IF NOT EXISTS " + DBNAME_DEVICETYPES + " (" +
DBFIELDS_DEVICETYPES_CREATION +
")",
Poco::Data::Keywords::now;
} else {
Sess << "CREATE TABLE IF NOT EXISTS " + DBNAME_DEVICETYPES + " (" +
DBFIELDS_DEVICETYPES_CREATION +
")",
Poco::Data::Keywords::now;
}
return 0;
} catch(const Poco::Exception &E) {
Logger_.log(E);
}
return -1;
}
int Storage::Create_DeviceInfo() {
try {
Poco::Data::Session Sess = Pool_->get();
Sess << "CREATE TABLE IF NOT EXISTS " + DBNAME_DEVICES + " (" +
DBFIELDS_DEVICES_CREATION +
")",
Poco::Data::Keywords::now;
return 0;
} catch(const Poco::Exception &E) {
Logger_.log(E);
}
return -1;
}
}

View File

@@ -34,11 +34,20 @@ fi
token="" token=""
result_file=result.json result_file=result.json
username="tip@ucentral.com"
password="openwifi"
browser_list=(firefox sensible-browser xdg-open w3m links links2 lynx youtube-dl) browser_list=(firefox sensible-browser xdg-open w3m links links2 lynx youtube-dl)
browser="" browser=""
if [ -z ${OWSEC_USERNAME+x} ]; then
username="script.runner@arilia.com"
else
username=${OWSEC_USERNAME}
fi
if [ -z ${OWSEC_PASSWORD+x} ]; then
password="Snoopy99!!!"
else
password=${OWSEC_PASSWORD}
fi
login() { login() {
payload="{ \"userId\" : \"$username\" , \"password\" : \"$password\" }" payload="{ \"userId\" : \"$username\" , \"password\" : \"$password\" }"
token=$(curl ${FLAGS} -X POST -H "Content-Type: application/json" -d "$payload" "https://${OWSEC}/api/v1/oauth2" | jq -r '.access_token') token=$(curl ${FLAGS} -X POST -H "Content-Type: application/json" -d "$payload" "https://${OWSEC}/api/v1/oauth2" | jq -r '.access_token')
@@ -73,17 +82,12 @@ findbrowser() {
} }
setfms() { setfms() {
if [ -z ${OWFMS_OVERRIDE+x} ]; then
curl ${FLAGS} -X GET "https://${OWSEC}/api/v1/systemEndpoints" \ curl ${FLAGS} -X GET "https://${OWSEC}/api/v1/systemEndpoints" \
-H "accept: application/json" \ -H "accept: application/json" \
-H "Authorization: Bearer ${token}" > ${result_file} -H "Authorization: Bearer ${token}" > ${result_file}
# jq < ${result_file} rawurl="$(cat ${result_file} | jq -r '.endpoints[] | select( .type == "owfms" ) | .uri')"
if [[ ! -z "${rawurl}" ]]; then
for index in {0..10}
do
endpointlocation=".endpoints[${index}].uri"
endpointlocationtype=".endpoints[${index}].type"
rawurl="$(cat ${result_file} | jq -r ${endpointlocation})"
svctype="$(cat ${result_file} | jq -r ${endpointlocationtype})"
proto="$(echo $rawurl | grep :// | sed -e's,^\(.*://\).*,\1,g')" proto="$(echo $rawurl | grep :// | sed -e's,^\(.*://\).*,\1,g')"
url="$(echo ${rawurl/$proto/})" url="$(echo ${rawurl/$proto/})"
user="$(echo $url | grep @ | cut -d@ -f1)" user="$(echo $url | grep @ | cut -d@ -f1)"
@@ -91,22 +95,18 @@ setfms() {
host="$(echo $hostport | sed -e 's,:.*,,g')" host="$(echo $hostport | sed -e 's,:.*,,g')"
port="$(echo $hostport | sed -e 's,^.*:,:,g' -e 's,.*:\([0-9]*\).*,\1,g' -e 's,[^0-9],,g')" port="$(echo $hostport | sed -e 's,^.*:,:,g' -e 's,.*:\([0-9]*\).*,\1,g' -e 's,[^0-9],,g')"
path="$(echo $url | grep / | cut -d/ -f2-)" path="$(echo $url | grep / | cut -d/ -f2-)"
if [[ ${url} != "null" ]] export OWFMS=${url}
then
if [[ ${svctype} == "owfms" ]]
then
# echo "url: $url"
# echo " proto: $proto"
# echo " user: $user"
# echo " host: $host"
# echo " port: $port"
# echo " path: $path"
OWFMS="${url}"
break
fi
fi
done
echo "Using ${OWFMS}..." echo "Using ${OWFMS}..."
else
echo "OWFMS endpoint is not found:"
jq < ${result_file}
exit 1
fi
else
export OWFMS=${OWFMS_OVERRIDE}
fi
} }
logout() { logout() {

File diff suppressed because one or more lines are too long

26
wait-for-postgres.sh Executable file
View File

@@ -0,0 +1,26 @@
#!/bin/sh
# wait-for-postgres.sh
set -e
host="$1"
shift
export PGUSER=$(grep 'storage.type.postgresql.username' $OWFMS_CONFIG/owfms.properties | awk -F '= ' '{print $2}')
export PGPASSWORD=$(grep 'storage.type.postgresql.password' $OWFMS_CONFIG/owfms.properties | awk -F '= ' '{print $2}')
until psql -h "$host" -c '\q'; do
>&2 echo "Postgres is unavailable - sleeping"
sleep 1
done
>&2 echo "Postgres is up - executing command"
if [ "$1" = '/openwifi/owfms' -a "$(id -u)" = '0' ]; then
if [ "$RUN_CHOWN" = 'true' ]; then
chown -R "$OWFMS_USER": "$OWFMS_ROOT" "$OWFMS_CONFIG"
fi
exec su-exec "$OWFMS_USER" "$@"
fi
exec "$@"