mirror of
				https://github.com/Telecominfraproject/wlan-cloud-ucentralsec.git
				synced 2025-10-31 02:37:56 +00:00 
			
		
		
		
	Compare commits
	
		
			1 Commits
		
	
	
		
			release/v2
			...
			v2.0.0
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 1de35630e9 | 
							
								
								
									
										6
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							| @@ -28,7 +28,7 @@ jobs: | |||||||
|     - uses: actions/checkout@v2 |     - uses: actions/checkout@v2 | ||||||
|  |  | ||||||
|     - name: Build Docker image |     - name: Build Docker image | ||||||
|       run: docker build -t wlan-cloud-owsec:${{ github.sha }} . |       run: docker build -t wlan-cloud-ucentralsec:${{ github.sha }} . | ||||||
|  |  | ||||||
|     - name: Tag Docker image |     - name: Tag Docker image | ||||||
|       run: | |       run: | | ||||||
| @@ -52,7 +52,7 @@ jobs: | |||||||
|         echo "Result tags: $TAGS" |         echo "Result tags: $TAGS" | ||||||
|  |  | ||||||
|         for tag in $TAGS; do |         for tag in $TAGS; do | ||||||
|           docker tag wlan-cloud-owsec:${{ github.sha }} ${{ env.DOCKER_REGISTRY_URL }}/owsec:$tag |           docker tag wlan-cloud-ucentralsec:${{ github.sha }} ${{ env.DOCKER_REGISTRY_URL }}/ucentralsec:$tag | ||||||
|         done |         done | ||||||
|  |  | ||||||
|     - name: Log into Docker registry |     - name: Log into Docker registry | ||||||
| @@ -66,4 +66,4 @@ jobs: | |||||||
|     - name: Push Docker images |     - name: Push Docker images | ||||||
|       if: startsWith(github.ref, 'refs/tags/') || startsWith(github.ref, 'refs/pull/') || github.ref == 'refs/heads/main' |       if: startsWith(github.ref, 'refs/tags/') || startsWith(github.ref, 'refs/pull/') || github.ref == 'refs/heads/main' | ||||||
|       run: | |       run: | | ||||||
|         docker images | grep ${{ env.DOCKER_REGISTRY_URL }}/owsec | awk -F ' ' '{print $1":"$2}' | xargs -I {} docker push {} |         docker images | grep ${{ env.DOCKER_REGISTRY_URL }}/ucentralsec | awk -F ' ' '{print $1":"$2}' | xargs -I {} docker push {} | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								.github/workflows/cleanup.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/cleanup.yml
									
									
									
									
										vendored
									
									
								
							| @@ -16,4 +16,4 @@ jobs: | |||||||
|     steps: |     steps: | ||||||
|       - run: | |       - run: | | ||||||
|           export PR_BRANCH_TAG=$(echo ${GITHUB_HEAD_REF#refs/heads/} | tr '/' '-') |           export PR_BRANCH_TAG=$(echo ${GITHUB_HEAD_REF#refs/heads/} | tr '/' '-') | ||||||
|           curl -uucentral:${{ secrets.DOCKER_REGISTRY_PASSWORD }} -X DELETE "https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral/owsec/$PR_BRANCH_TAG" |           curl -uucentral:${{ secrets.DOCKER_REGISTRY_PASSWORD }} -X DELETE "https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral/ucentralsec/$PR_BRANCH_TAG" | ||||||
|   | |||||||
							
								
								
									
										87
									
								
								CLI.md
									
									
									
									
									
								
							
							
						
						
									
										87
									
								
								CLI.md
									
									
									
									
									
								
							| @@ -1,9 +1,9 @@ | |||||||
| # Security Service CLI Documentation | # Security Service CLI Documentation | ||||||
|  |  | ||||||
| ## Before using the CLI | ## Before using the CLI | ||||||
| You must set the environment variable `OWSEC`. You must specify the host and port for the security service. Here is an example | You must set the environment variable `UCENTRALSEC`. You must specify the host and port for the security service. Here is an example | ||||||
| ```csh | ```csh | ||||||
| export OWSEC=mysecurityservice,example.com:16001 | export UCENTRALSEC=mysecurityservice,example.com:16001 | ||||||
| ``` | ``` | ||||||
| Once set, you can start using the `CLI`. | Once set, you can start using the `CLI`. | ||||||
|  |  | ||||||
| @@ -12,59 +12,64 @@ Most commands will take from 0 to 2 parameters. You should include all parameter | |||||||
|  |  | ||||||
| ## The commands | ## The commands | ||||||
|  |  | ||||||
| ### listendpoints                           | ### `cli createuser <email> <initial password>` | ||||||
| Get all the system endpoints. | This will create a simple user as admin using the email as login ID and setting the initial password. | ||||||
|  |  | ||||||
| ### emailtest                               | ### `cli createuser_v <email> <initial password>` | ||||||
| Generate a forgot Password e-amil to the logged in user. | This will create a simple user and force email verification.  | ||||||
|  |  | ||||||
| ### me | ### `cli deleteuser <id>` | ||||||
| Show information about the logged user. | Delete the specified user using the user's UUID. | ||||||
|  |  | ||||||
| ### createuser <email> <password>           | ### `cli getuser <id>` | ||||||
| Create a user with an initial password and force the user to change password. | Get the specified user using the user's UUID. | ||||||
|  |  | ||||||
| ### createuser_v <email> <password>         | ### `cli listusers` | ||||||
| Same as create user but also force an e-mail verification. | Get a list of users. | ||||||
|  |  | ||||||
| ### deleteuser <user UUID>                  | ### `cli policies` | ||||||
| Delete the user. | List the link used to display password and usage policies for the management site. | ||||||
|      |  | ||||||
| ### getuser <user UUID>                     |  | ||||||
| Get the user information. |  | ||||||
|  |  | ||||||
| ### listusers | ### `cli setavatar <id> <filename>` | ||||||
| List users. | Sets the avatar for the user with ID. The file should be gif, png, svg. | ||||||
|  |  | ||||||
| ### policies | ### `cli deleteavatar <id>` | ||||||
| List the login and access policies. | Remove the avatar fort the specified user ID. | ||||||
|  |  | ||||||
| ### setavatar <user UUID> <filename>        | ### `cli secversion` | ||||||
| Sets the avatar for user to the image in filename. | Get the vewrsion of the secufiry service. | ||||||
|  |  | ||||||
| ### getavatar <user UUID>                   | ### `cli sectimes` | ||||||
| Get the avatar for the user. | Get the starttime and uptime for the security service. | ||||||
|  |  | ||||||
| ### deleteavatar <user UUID>                |  | ||||||
| Remove the avatar for a user. |  | ||||||
|  |  | ||||||
| ### sendemail <recipient> <from>            |  | ||||||
| Sends a test email to see if the e-mail system is working. |  | ||||||
|  |  | ||||||
| ### setloglevel <subsystem> <loglevel> |  | ||||||
| Set the log level for s specific subsystem. |  | ||||||
|  |  | ||||||
| ### getloglevels | ### `cli revisions` | ||||||
| Get the current log levels for all subsystems. | Get the list of currently available revisions. | ||||||
|  |  | ||||||
| ### getloglevelnames | ### `cli devicetypes` | ||||||
| Get the log level names available. | Retrieve the list of known `device_types` | ||||||
|  |  | ||||||
| ### getsubsystemnames | ### `cli firmwareage <device_type> <revision>` | ||||||
| Get the list of subsystems. | If you specify your `device_type` and `revision`, the system will do its best to estimate how | ||||||
|  | far in the past you `revision` is compared to the latest revision. | ||||||
|  |  | ||||||
| ### systeminfo | ### `cli gethistory <serialNumber>` | ||||||
| Get basic system information. | Get the revision history for a given device. | ||||||
|  |  | ||||||
|  | ### `cli connecteddevices` | ||||||
|  | Get a list of the currently known devices and the last connection information we have about the, | ||||||
|  |  | ||||||
|  | ### `cli connecteddevice <serialNumber>` | ||||||
|  | Get the information relevant to a specific device. | ||||||
|  |  | ||||||
|  | ### `cli devicereport` | ||||||
|  | Give a simplified dashboard report of the data in the service. | ||||||
|  |  | ||||||
|  | ### `cli fmsversion` | ||||||
|  | Display the version of the service. | ||||||
|  |  | ||||||
|  | ### `cli fmstimes` | ||||||
|  | Display the uptime and start time of the service. | ||||||
|  |  | ||||||
| ### reloadsubsystem <subsystem name> |  | ||||||
| Reload the configuration for a subsystem. |  | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| cmake_minimum_required(VERSION 3.13) | cmake_minimum_required(VERSION 3.13) | ||||||
| project(owsec VERSION 2.2.0) | project(ucentralsec VERSION 2.0.0) | ||||||
|  |  | ||||||
| set(CMAKE_CXX_STANDARD 17) | set(CMAKE_CXX_STANDARD 17) | ||||||
|  |  | ||||||
| @@ -47,7 +47,7 @@ find_package(PostgreSQL REQUIRED) | |||||||
| find_package(MySQL REQUIRED) | find_package(MySQL REQUIRED) | ||||||
| find_package(Poco REQUIRED COMPONENTS JSON Crypto JWT Net Util NetSSL Data DataSQLite DataPostgreSQL DataMySQL) | find_package(Poco REQUIRED COMPONENTS JSON Crypto JWT Net Util NetSSL Data DataSQLite DataPostgreSQL DataMySQL) | ||||||
|  |  | ||||||
| add_executable( owsec | add_executable( ucentralsec | ||||||
|                 build |                 build | ||||||
|                 src/Daemon.h src/Daemon.cpp |                 src/Daemon.h src/Daemon.cpp | ||||||
|                 src/MicroService.cpp src/MicroService.h |                 src/MicroService.cpp src/MicroService.h | ||||||
| @@ -62,29 +62,21 @@ add_executable( owsec | |||||||
|                 src/KafkaManager.h src/KafkaManager.cpp |                 src/KafkaManager.h src/KafkaManager.cpp | ||||||
|                 src/StorageService.cpp src/StorageService.h |                 src/StorageService.cpp src/StorageService.h | ||||||
|                 src/Utils.cpp src/Utils.h |                 src/Utils.cpp src/Utils.h | ||||||
|                 src/storage_setup.cpp |                 src/storage_sqlite.cpp src/storage_sqlite.cpp src/storage_pgql.cpp src/storage_mysql.cpp | ||||||
|                 src/storage_tables.cpp src/SMTPMailerService.cpp src/SMTPMailerService.h |                 src/storage_tables.cpp src/SMTPMailerService.cpp src/SMTPMailerService.h | ||||||
|                 src/RESTAPI_users_handler.cpp src/RESTAPI_users_handler.h |                 src/RESTAPI_users_handler.cpp src/RESTAPI_users_handler.h | ||||||
|                 src/RESTAPI_user_handler.cpp src/RESTAPI_user_handler.h |                 src/RESTAPI_user_handler.cpp src/RESTAPI_user_handler.h | ||||||
|                 src/RESTAPI_action_links.cpp src/RESTAPI_action_links.h src/storage_users.cpp |                 src/RESTAPI_action_links.cpp src/RESTAPI_action_links.h src/storage_users.cpp | ||||||
|                 src/RESTAPI_InternalServer.cpp src/RESTAPI_InternalServer.h |                 src/RESTAPI_InternalServer.cpp src/RESTAPI_InternalServer.h | ||||||
|                 src/RESTAPI_validateToken_handler.cpp src/RESTAPI_validateToken_handler.h |                 src/RESTAPI_validateToken_handler.cpp src/RESTAPI_validateToken_handler.h | ||||||
|                 src/RESTAPI_systemEndpoints_handler.cpp src/RESTAPI_systemEndpoints_handler.h |                 src/RESTAPI_systemEndpoints_handler.cpp src/RESTAPI_systemEndpoints_handler.h src/RESTAPI_AssetServer.cpp src/RESTAPI_AssetServer.h src/RESTAPI_avatarHandler.cpp src/RESTAPI_avatarHandler.h src/storage_avatar.cpp src/storage_avatar.h src/storage_users.h) | ||||||
|                 src/RESTAPI_AssetServer.cpp src/RESTAPI_AssetServer.h |  | ||||||
|                 src/RESTAPI_avatarHandler.cpp src/RESTAPI_avatarHandler.h |  | ||||||
|                 src/storage_avatar.cpp src/storage_avatar.h src/storage_users.h |  | ||||||
|                 src/OpenWifiTypes.h src/RESTAPI_email_handler.cpp src/RESTAPI_email_handler.h |  | ||||||
|                 src/storage_tokens.cpp |  | ||||||
|                 src/RESTAPI_GenericServer.h src/RESTAPI_GenericServer.cpp |  | ||||||
|                 src/RESTAPI_errors.h |  | ||||||
|                 ) |  | ||||||
|  |  | ||||||
| if(NOT SMALL_BUILD) | if(NOT SMALL_BUILD) | ||||||
|     target_link_libraries(owsec PUBLIC |     target_link_libraries(ucentralsec PUBLIC | ||||||
|             ${Poco_LIBRARIES} ${Boost_LIBRARIES} ${MySQL_LIBRARIES}  ${ZLIB_LIBRARIES} |             ${Poco_LIBRARIES} ${Boost_LIBRARIES} ${MySQL_LIBRARIES}  ${ZLIB_LIBRARIES} | ||||||
|             CppKafka::cppkafka |             CppKafka::cppkafka | ||||||
|             ) |             ) | ||||||
|     if(UNIX AND NOT APPLE) |     if(UNIX AND NOT APPLE) | ||||||
|         target_link_libraries(owsec PUBLIC PocoJSON) |         target_link_libraries(ucentralsec PUBLIC PocoJSON) | ||||||
|     endif() |     endif() | ||||||
| endif() | endif() | ||||||
							
								
								
									
										36
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								Dockerfile
									
									
									
									
									
								
							| @@ -26,39 +26,35 @@ RUN cmake .. | |||||||
| RUN cmake --build . --config Release -j8 | RUN cmake --build . --config Release -j8 | ||||||
| RUN cmake --build . --target install | RUN cmake --build . --target install | ||||||
|  |  | ||||||
| ADD CMakeLists.txt build /owsec/ | ADD CMakeLists.txt build /ucentralsec/ | ||||||
| ADD cmake /owsec/cmake | ADD cmake /ucentralsec/cmake | ||||||
| ADD src /owsec/src | ADD src /ucentralsec/src | ||||||
|  |  | ||||||
| WORKDIR /owsec | WORKDIR /ucentralsec | ||||||
| RUN mkdir cmake-build | RUN mkdir cmake-build | ||||||
| WORKDIR /owsec/cmake-build | WORKDIR /ucentralsec/cmake-build | ||||||
| RUN cmake .. | RUN cmake .. | ||||||
| RUN cmake --build . --config Release -j8 | RUN cmake --build . --config Release -j8 | ||||||
|  |  | ||||||
| FROM alpine | FROM alpine | ||||||
|  |  | ||||||
| ENV OWSEC_USER=owsec \ | ENV UCENTRALSEC_USER=ucentralsec \ | ||||||
|     OWSEC_ROOT=/owsec-data \ |     UCENTRALSEC_ROOT=/ucentralsec-data \ | ||||||
|     OWSEC_CONFIG=/owsec-data |     UCENTRALSEC_CONFIG=/ucentralsec-data | ||||||
|  |  | ||||||
| RUN addgroup -S "$OWSEC_USER" && \ | RUN addgroup -S "$UCENTRALSEC_USER" && \ | ||||||
|     adduser -S -G "$OWSEC_USER" "$OWSEC_USER" |     adduser -S -G "$UCENTRALSEC_USER" "$UCENTRALSEC_USER" | ||||||
|  |  | ||||||
| RUN mkdir /openwifi | RUN mkdir /ucentral | ||||||
| RUN mkdir -p "$OWSEC_ROOT" "$OWSEC_CONFIG" && \ | RUN mkdir -p "$UCENTRALSEC_ROOT" "$UCENTRALSEC_CONFIG" | ||||||
|     chown "$OWSEC_USER": "$OWSEC_ROOT" "$OWSEC_CONFIG" | RUN apk add --update --no-cache librdkafka mariadb-connector-c libpq unixodbc su-exec | ||||||
| RUN apk add --update --no-cache librdkafka mariadb-connector-c libpq unixodbc su-exec gettext ca-certificates |  | ||||||
| COPY --from=builder /owsec/cmake-build/owsec /openwifi/owsec | COPY --from=builder /ucentralsec/cmake-build/ucentralsec /ucentral/ucentralsec | ||||||
| COPY --from=builder /cppkafka/cmake-build/src/lib/* /lib/ | COPY --from=builder /cppkafka/cmake-build/src/lib/* /lib/ | ||||||
| COPY --from=builder /poco/cmake-build/lib/* /lib/ | COPY --from=builder /poco/cmake-build/lib/* /lib/ | ||||||
|  |  | ||||||
| COPY owsec.properties.tmpl ${OWSEC_CONFIG}/ |  | ||||||
| COPY docker-entrypoint.sh / | COPY docker-entrypoint.sh / | ||||||
| RUN wget https://raw.githubusercontent.com/Telecominfraproject/wlan-cloud-ucentral-deploy/main/docker-compose/certs/restapi-ca.pem \ |  | ||||||
|     -O /usr/local/share/ca-certificates/restapi-ca-selfsigned.pem |  | ||||||
|  |  | ||||||
| EXPOSE 16001 17001 16101 | EXPOSE 16001 17001 16101 | ||||||
|  |  | ||||||
| ENTRYPOINT ["/docker-entrypoint.sh"] | ENTRYPOINT ["/docker-entrypoint.sh"] | ||||||
| CMD ["/openwifi/owsec"] | CMD ["/ucentral/ucentralsec"] | ||||||
|   | |||||||
							
								
								
									
										72
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										72
									
								
								README.md
									
									
									
									
									
								
							| @@ -21,7 +21,7 @@ The entire uCentral systems uses several MicroServices. In order for the whole s | |||||||
| access | access | ||||||
|  |  | ||||||
| - Security | - Security | ||||||
|   - Properties file: owsec.properties |   - Properties file: ucentralsec.properties | ||||||
|   - Ports |   - Ports | ||||||
|     - Public: 16001 |     - Public: 16001 | ||||||
|     - Private: 17001 |     - Private: 17001 | ||||||
| @@ -42,7 +42,7 @@ access | |||||||
|     - ALB: 16104 |     - ALB: 16104 | ||||||
|  |  | ||||||
| ## Security Configuration | ## Security Configuration | ||||||
| The service relies on a properties configuration file called `owsec.properties`. In this file, you should configure several entries. Many values are optional  | The service relies on a properties configuration file called `ucentralsec.properties`. In this file, you should configure several entries. Many values are optional  | ||||||
| and you can rely on the defaults. Here are some values of note: | and you can rely on the defaults. Here are some values of note: | ||||||
|  |  | ||||||
| ### `authentication.default.password` | ### `authentication.default.password` | ||||||
| @@ -52,7 +52,7 @@ Set the hash of the default username and password. Please look below on how to d | |||||||
| Set the default username to use to login. | Set the default username to use to login. | ||||||
|  |  | ||||||
| ### Default username and password | ### Default username and password | ||||||
| The default username and password are set in `owsec.properties` file. The following entries manage the username and password | The default username and password are set in `ucentralsec.properties` file. The following entries manage the username and password | ||||||
| ```text | ```text | ||||||
| authentication.default.username = tip@ucentral.com | authentication.default.username = tip@ucentral.com | ||||||
| authentication.default.password = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX | authentication.default.password = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX | ||||||
| @@ -97,19 +97,19 @@ This security service uses Kafka to coordinate security with other services that | |||||||
| in order to use this. You can find several examples of Kafka services available with Docker. Here are the values you need to configure. | in order to use this. You can find several examples of Kafka services available with Docker. Here are the values you need to configure. | ||||||
|  |  | ||||||
| ```asm | ```asm | ||||||
| openwifi.kafka.group.id = security | ucentral.kafka.group.id = security | ||||||
| openwifi.kafka.client.id = security1 | ucentral.kafka.client.id = security1 | ||||||
| openwifi.kafka.enable = true | ucentral.kafka.enable = true | ||||||
| openwifi.kafka.brokerlist = my.kafkaserver.arilia.com:9092 | ucentral.kafka.brokerlist = my.kafkaserver.arilia.com:9092 | ||||||
| openwifi.kafka.auto.commit = false | ucentral.kafka.auto.commit = false | ||||||
| openwifi.kafka.queue.buffering.max.ms = 50 | ucentral.kafka.queue.buffering.max.ms = 50 | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| #### `openwifi.kafka.brokerlist` | #### `ucentral.kafka.brokerlist` | ||||||
| This is the list of your kafka brokers. This is a comma separated list. You should use IP addresses or FQDNs and the relevant ports, usually 9092 is the  | This is the list of your kafka brokers. This is a comma separated list. You should use IP addresses or FQDNs and the relevant ports, usually 9092 is the  | ||||||
| default. | default. | ||||||
|  |  | ||||||
| #### `openwifi.kafka.group.id` | #### `ucentral.kafka.group.id` | ||||||
| Every service on the Kafka bux must have a unique value (at least in our case). This should be a string. We suggest using a name corresponding to the  | Every service on the Kafka bux must have a unique value (at least in our case). This should be a string. We suggest using a name corresponding to the  | ||||||
| function provided. In this case, security. | function provided. In this case, security. | ||||||
|  |  | ||||||
| @@ -124,17 +124,17 @@ Here are the parameters for the public interface. The important files are: | |||||||
| - `restapi-ca.pem` : the CA of your certificate | - `restapi-ca.pem` : the CA of your certificate | ||||||
| - `restapi-cert.pem` : the certificate for the public interface | - `restapi-cert.pem` : the certificate for the public interface | ||||||
| - `restapi-key.pem` : the key associated with this certificate | - `restapi-key.pem` : the key associated with this certificate | ||||||
| - `openwifi.restapi.host.0.key.password` : if you key is password protected, you may supply that password here. | - `ucentral.restapi.host.0.key.password` : if you key is password protected, you may supply that password here. | ||||||
|  |  | ||||||
| ```asm | ```asm | ||||||
| openwifi.restapi.host.0.backlog = 100 | ucentral.restapi.host.0.backlog = 100 | ||||||
| openwifi.restapi.host.0.security = relaxed | ucentral.restapi.host.0.security = relaxed | ||||||
| openwifi.restapi.host.0.rootca = $OWSEC_ROOT/certs/restapi-ca.pem | ucentral.restapi.host.0.rootca = $UCENTRALSEC_ROOT/certs/restapi-ca.pem | ||||||
| openwifi.restapi.host.0.address = * | ucentral.restapi.host.0.address = * | ||||||
| openwifi.restapi.host.0.port = 16001 | ucentral.restapi.host.0.port = 16001 | ||||||
| openwifi.restapi.host.0.cert = $OWSEC_ROOT/certs/restapi-cert.pem | ucentral.restapi.host.0.cert = $UCENTRALSEC_ROOT/certs/restapi-cert.pem | ||||||
| openwifi.restapi.host.0.key = $OWSEC_ROOT/certs/restapi-key.pem | ucentral.restapi.host.0.key = $UCENTRALSEC_ROOT/certs/restapi-key.pem | ||||||
| openwifi.restapi.host.0.key.password = mypassword | ucentral.restapi.host.0.key.password = mypassword | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| #### The private interface | #### The private interface | ||||||
| @@ -142,14 +142,14 @@ The private interface is used for service-to-service communication. You can use | |||||||
| to the filenames used in the previous section. | to the filenames used in the previous section. | ||||||
|  |  | ||||||
| ```asm | ```asm | ||||||
| openwifi.internal.restapi.host.0.backlog = 100 | ucentral.internal.restapi.host.0.backlog = 100 | ||||||
| openwifi.internal.restapi.host.0.security = relaxed | ucentral.internal.restapi.host.0.security = relaxed | ||||||
| openwifi.internal.restapi.host.0.rootca = $OWSEC_ROOT/certs/restapi-ca.pem | ucentral.internal.restapi.host.0.rootca = $UCENTRALSEC_ROOT/certs/restapi-ca.pem | ||||||
| openwifi.internal.restapi.host.0.address = * | ucentral.internal.restapi.host.0.address = * | ||||||
| openwifi.internal.restapi.host.0.port = 17001 | ucentral.internal.restapi.host.0.port = 17001 | ||||||
| openwifi.internal.restapi.host.0.cert = $OWSEC_ROOT/certs/restapi-cert.pem | ucentral.internal.restapi.host.0.cert = $UCENTRALSEC_ROOT/certs/restapi-cert.pem | ||||||
| openwifi.internal.restapi.host.0.key = $OWSEC_ROOT/certs/restapi-key.pem | ucentral.internal.restapi.host.0.key = $UCENTRALSEC_ROOT/certs/restapi-key.pem | ||||||
| openwifi.internal.restapi.host.0.key.password = mypassword | ucentral.internal.restapi.host.0.key.password = mypassword | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| ### Other important values | ### Other important values | ||||||
| @@ -157,19 +157,19 @@ Here are other important values you must set. | |||||||
|  |  | ||||||
|  |  | ||||||
| ```asm | ```asm | ||||||
| openwifi.system.data = $OWSEC_ROOT/data | ucentral.system.data = $UCENTRALSEC_ROOT/data | ||||||
| openwifi.system.uri.private = https://localhost:17001 | ucentral.system.uri.private = https://localhost:17001 | ||||||
| openwifi.system.uri.public = https://openwifi.dpaas.arilia.com:16001 | ucentral.system.uri.public = https://ucentral.dpaas.arilia.com:16001 | ||||||
| openwifi.system.commandchannel = /tmp/app.ucentralsec | ucentral.system.commandchannel = /tmp/app.ucentralsec | ||||||
| openwifi.service.key = $OWSEC_ROOT/certs/restapi-key.pem | ucentral.service.key = $UCENTRALSEC_ROOT/certs/restapi-key.pem | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| #### `openwifi.system.data` | #### `ucentral.system.data` | ||||||
| The location of some important data files including the user name database. | The location of some important data files including the user name database. | ||||||
|  |  | ||||||
| #### `openwifi.system.uri.private` | #### `ucentral.system.uri.private` | ||||||
| This is the FQDN used internally between services. | This is the FQDN used internally between services. | ||||||
|  |  | ||||||
| #### `openwifi.system.uri.public` | #### `ucentral.system.uri.public` | ||||||
| This is the FQDN used externally serving the OpenAPI interface. | This is the FQDN used externally serving the OpenAPI interface. | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,56 +1,11 @@ | |||||||
| #!/bin/sh | #!/bin/sh | ||||||
| set -e | set -e | ||||||
|  |  | ||||||
| if [ "$SELFSIGNED_CERTS" = 'true' ]; then | if [ "$1" = '/ucentral/ucentralsec' -a "$(id -u)" = '0' ]; then | ||||||
|     update-ca-certificates |  | ||||||
| fi |  | ||||||
|  |  | ||||||
| if [[ "$TEMPLATE_CONFIG" = 'true' && ! -f "$OWSEC_CONFIG"/owsec.properties ]]; then |  | ||||||
|   RESTAPI_HOST_ROOTCA=${RESTAPI_HOST_ROOTCA:-"\$OWSEC_ROOT/certs/restapi-ca.pem"} \ |  | ||||||
|   RESTAPI_HOST_PORT=${RESTAPI_HOST_PORT:-"16001"} \ |  | ||||||
|   RESTAPI_HOST_CERT=${RESTAPI_HOST_CERT:-"\$OWSEC_ROOT/certs/restapi-cert.pem"} \ |  | ||||||
|   RESTAPI_HOST_KEY=${RESTAPI_HOST_KEY:-"\$OWSEC_ROOT/certs/restapi-key.pem"} \ |  | ||||||
|   RESTAPI_HOST_KEY_PASSWORD=${RESTAPI_HOST_KEY_PASSWORD:-"mypassword"} \ |  | ||||||
|   RESTAPI_WWWASSETS=${RESTAPI_WWWASSETS:-"\$OWSEC_ROOT/wwwassets"} \ |  | ||||||
|   INTERNAL_RESTAPI_HOST_ROOTCA=${INTERNAL_RESTAPI_HOST_ROOTCA:-"\$OWSEC_ROOT/certs/restapi-ca.pem"} \ |  | ||||||
|   INTERNAL_RESTAPI_HOST_PORT=${INTERNAL_RESTAPI_HOST_PORT:-"17001"} \ |  | ||||||
|   INTERNAL_RESTAPI_HOST_CERT=${INTERNAL_RESTAPI_HOST_CERT:-"\$OWSEC_ROOT/certs/restapi-cert.pem"} \ |  | ||||||
|   INTERNAL_RESTAPI_HOST_KEY=${INTERNAL_RESTAPI_HOST_KEY:-"\$OWSEC_ROOT/certs/restapi-key.pem"} \ |  | ||||||
|   INTERNAL_RESTAPI_HOST_KEY_PASSWORD=${INTERNAL_RESTAPI_HOST_KEY_PASSWORD:-"mypassword"} \ |  | ||||||
|   AUTHENTICATION_DEFAULT_USERNAME=${AUTHENTICATION_DEFAULT_USERNAME:-"tip@ucentral.com"} \ |  | ||||||
|   AUTHENTICATION_DEFAULT_PASSWORD=${AUTHENTICATION_DEFAULT_PASSWORD:-"13268b7daa751240369d125e79c873bd8dd3bef7981bdfd38ea03dbb1fbe7dcf"} \ |  | ||||||
|   SYSTEM_DATA=${SYSTEM_DATA:-"\$OWSEC_ROOT/data"} \ |  | ||||||
|   SYSTEM_URI_PRIVATE=${SYSTEM_URI_PRIVATE:-"https://localhost:17001"} \ |  | ||||||
|   SYSTEM_URI_PUBLIC=${SYSTEM_URI_PUBLIC:-"https://localhost:16001"} \ |  | ||||||
|   SYSTEM_URI_UI=${SYSTEM_URI_UI:-"http://localhost"} \ |  | ||||||
|   SERVICE_KEY=${SERVICE_KEY:-"\$OWSEC_ROOT/certs/restapi-key.pem"} \ |  | ||||||
|   SERVICE_KEY_PASSWORD=${SERVICE_KEY_PASSWORD:-"mypassword"} \ |  | ||||||
|   MAILER_HOSTNAME=${MAILER_HOSTNAME:-"smtp.gmail.com"} \ |  | ||||||
|   MAILER_USERNAME=${MAILER_USERNAME:-"************************"} \ |  | ||||||
|   MAILER_PASSWORD=${MAILER_PASSWORD:-"************************"} \ |  | ||||||
|   MAILER_SENDER=${MAILER_SENDER:-"OpenWIFI"} \ |  | ||||||
|   MAILER_PORT=${MAILER_PORT:-"587"} \ |  | ||||||
|   KAFKA_ENABLE=${KAFKA_ENABLE:-"true"} \ |  | ||||||
|   KAFKA_BROKERLIST=${KAFKA_BROKERLIST:-"localhost:9092"} \ |  | ||||||
|   STORAGE_TYPE=${STORAGE_TYPE:-"sqlite"} \ |  | ||||||
|   STORAGE_TYPE_POSTGRESQL_HOST=${STORAGE_TYPE_POSTGRESQL_HOST:-"localhost"} \ |  | ||||||
|   STORAGE_TYPE_POSTGRESQL_USERNAME=${STORAGE_TYPE_POSTGRESQL_USERNAME:-"owsec"} \ |  | ||||||
|   STORAGE_TYPE_POSTGRESQL_PASSWORD=${STORAGE_TYPE_POSTGRESQL_PASSWORD:-"owsec"} \ |  | ||||||
|   STORAGE_TYPE_POSTGRESQL_DATABASE=${STORAGE_TYPE_POSTGRESQL_DATABASE:-"owsec"} \ |  | ||||||
|   STORAGE_TYPE_POSTGRESQL_PORT=${STORAGE_TYPE_POSTGRESQL_PORT:-"5432"} \ |  | ||||||
|   STORAGE_TYPE_MYSQL_HOST=${STORAGE_TYPE_MYSQL_HOST:-"localhost"} \ |  | ||||||
|   STORAGE_TYPE_MYSQL_USERNAME=${STORAGE_TYPE_MYSQL_USERNAME:-"owsec"} \ |  | ||||||
|   STORAGE_TYPE_MYSQL_PASSWORD=${STORAGE_TYPE_MYSQL_PASSWORD:-"owsec"} \ |  | ||||||
|   STORAGE_TYPE_MYSQL_DATABASE=${STORAGE_TYPE_MYSQL_DATABASE:-"owsec"} \ |  | ||||||
|   STORAGE_TYPE_MYSQL_PORT=${STORAGE_TYPE_MYSQL_PORT:-"3306"} \ |  | ||||||
|   envsubst < $OWSEC_CONFIG/owsec.properties.tmpl > $OWSEC_CONFIG/owsec.properties |  | ||||||
| fi |  | ||||||
|  |  | ||||||
| if [ "$1" = '/openwifi/owsec' -a "$(id -u)" = '0' ]; then |  | ||||||
|     if [ "$RUN_CHOWN" = 'true' ]; then |     if [ "$RUN_CHOWN" = 'true' ]; then | ||||||
|       chown -R "$OWSEC_USER": "$OWSEC_ROOT" "$OWSEC_CONFIG" |       chown -R "$UCENTRALSEC_USER": "$UCENTRALSEC_ROOT" "$UCENTRALSEC_CONFIG" | ||||||
|     fi |     fi | ||||||
|     exec su-exec "$OWSEC_USER" "$@" |     exec su-exec "$UCENTRALSEC_USER" "$@" | ||||||
| fi | fi | ||||||
|  |  | ||||||
| exec "$@" | exec "$@" | ||||||
|   | |||||||
| @@ -1,18 +1,5 @@ | |||||||
| apiVersion: v2 | apiVersion: v1 | ||||||
| appVersion: "1.0" | appVersion: "1.0" | ||||||
| description: A Helm chart for Kubernetes | description: A Helm chart for Kubernetes | ||||||
| name: owsec | name: ucentralsec | ||||||
| version: 0.1.0 | version: 0.1.0 | ||||||
| dependencies: |  | ||||||
| - name: postgresql |  | ||||||
|   repository: https://charts.bitnami.com/bitnami |  | ||||||
|   version: 10.9.2 |  | ||||||
|   condition: postgresql.enabled |  | ||||||
| - name: mysql |  | ||||||
|   repository: https://charts.bitnami.com/bitnami |  | ||||||
|   version: 8.8.3 |  | ||||||
|   condition: mysql.enabled |  | ||||||
| - name: mariadb |  | ||||||
|   repository: https://charts.bitnami.com/bitnami |  | ||||||
|   version: 9.4.2 |  | ||||||
|   condition: mariadb.enabled |  | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| # owsec | # ucentralsec | ||||||
|  |  | ||||||
| This Helm chart helps to deploy OpenWIFI Security (further on refered as __Security__) to the Kubernetes clusters. It is mainly used in [assembly chart](https://github.com/Telecominfraproject/wlan-cloud-ucentral-deploy/tree/main/chart) as Security requires other services as dependencies that are considered in that Helm chart. This chart is purposed to define deployment logic close to the application code itself and define default values that could be overriden during deployment. | This Helm chart helps to deploy uCentralSec to the Kubernetes clusters. It is mainly used in [assembly chart](https://github.com/Telecominfraproject/wlan-cloud-ucentral-deploy/tree/main/chart) as uCentralSec requires other services as dependencies that are considered in that Helm chart. This chart is purposed to define deployment logic close to the application code itself and define default values that could be overriden during deployment. | ||||||
|  |  | ||||||
|  |  | ||||||
| ## TL;DR; | ## TL;DR; | ||||||
| @@ -11,7 +11,7 @@ $ helm install . | |||||||
|  |  | ||||||
| ## Introduction | ## Introduction | ||||||
|  |  | ||||||
| This chart bootstraps the Security on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. | This chart bootstraps an ucentralsec on a [Kubernetes](http://kubernetes.io) cluster using the [Helm](https://helm.sh) package manager. | ||||||
|  |  | ||||||
| ## Installing the Chart | ## Installing the Chart | ||||||
|  |  | ||||||
| @@ -23,7 +23,7 @@ To install the chart with the release name `my-release`: | |||||||
| $ helm install --name my-release git+https://github.com/Telecominfraproject/wlan-cloud-ucentralsec@helm?ref=main | $ helm install --name my-release git+https://github.com/Telecominfraproject/wlan-cloud-ucentralsec@helm?ref=main | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| The command deploys the Security on the Kubernetes cluster in the default configuration. The [configuration](#configuration) section lists the parameters that can be configured during installation. | The command deploys ucentralsec on the Kubernetes cluster in the default configuration. The [configuration](#configuration) section lists the parameters that can be configured during installation. | ||||||
|  |  | ||||||
| > **Tip**: List all releases using `helm list` | > **Tip**: List all releases using `helm list` | ||||||
|  |  | ||||||
| @@ -47,30 +47,30 @@ The following table lists the configurable parameters of the chart and their def | |||||||
| | strategyType | string | Application deployment strategy | `'Recreate'` | | | strategyType | string | Application deployment strategy | `'Recreate'` | | ||||||
| | nameOverride | string | Override to be used for application deployment |  | | | nameOverride | string | Override to be used for application deployment |  | | ||||||
| | fullnameOverride | string | Override to be used for application deployment (has priority over nameOverride) |  | | | fullnameOverride | string | Override to be used for application deployment (has priority over nameOverride) |  | | ||||||
| | images.owsec.repository | string | Docker image repository |  | | | images.ucentralsec.repository | string | Docker image repository |  | | ||||||
| | images.owsec.tag | string | Docker image tag | `'master'` | | | images.ucentralsec.tag | string | Docker image tag | `'master'` | | ||||||
| | images.owsec.pullPolicy | string | Docker image pull policy | `'Always'` | | | images.ucentralsec.pullPolicy | string | Docker image pull policy | `'Always'` | | ||||||
| | services.owsec.type | string | OpenWIFI Security service type | `'LoadBalancer'` | | | services.ucentralsec.type | string | uCentralSec service type | `'LoadBalancer'` | | ||||||
| | services.owsec.ports.restapi.servicePort | number | REST API endpoint port to be exposed on service | `16001` | | | services.ucentralsec.ports.restapi.servicePort | number | REST API endpoint port to be exposed on service | `16001` | | ||||||
| | services.owsec.ports.restapi.targetPort | number | REST API endpoint port to be targeted by service | `16001` | | | services.ucentralsec.ports.restapi.targetPort | number | REST API endpoint port to be targeted by service | `16001` | | ||||||
| | services.owsec.ports.restapi.protocol | string | REST API endpoint protocol | `'TCP'` | | | services.ucentralsec.ports.restapi.protocol | string | REST API endpoint protocol | `'TCP'` | | ||||||
| | services.owsec.ports.restapiinternal.servicePort | string | Internal REST API endpoint port to be exposed on service | `17001` | | | services.ucentralsec.ports.restapiinternal.servicePort | string | Internal REST API endpoint port to be exposed on service | `17001` | | ||||||
| | services.owsec.ports.restapiinternal.targetPort | number | Internal REST API endpoint port to be targeted by service | `17001` | | | services.ucentralsec.ports.restapiinternal.targetPort | number | Internal REST API endpoint port to be targeted by service | `17001` | | ||||||
| | services.owsec.ports.restapiinternal.protocol | string | Internal REST API endpoint protocol | `'TCP'` | | | services.ucentralsec.ports.restapiinternal.protocol | string | Internal REST API endpoint protocol | `'TCP'` | | ||||||
| | checks.owsec.liveness.httpGet.path | string | Liveness check path to be used | `'/'` | | | checks.ucentralsec.liveness.httpGet.path | string | Liveness check path to be used | `'/'` | | ||||||
| | checks.owsec.liveness.httpGet.port | number | Liveness check port to be used (should be pointint to ALB endpoint) | `16101` | | | checks.ucentralsec.liveness.httpGet.port | number | Liveness check port to be used (should be pointint to ALB endpoint) | `16101` | | ||||||
| | checks.owsec.readiness.httpGet.path | string | Readiness check path to be used | `'/'` | | | checks.ucentralsec.readiness.httpGet.path | string | Readiness check path to be used | `'/'` | | ||||||
| | checks.owsec.readiness.httpGet.port | number | Readiness check port to be used (should be pointint to ALB endpoint) | `16101` | | | checks.ucentralsec.readiness.httpGet.port | number | Readiness check port to be used (should be pointint to ALB endpoint) | `16101` | | ||||||
| | ingresses.restapi.enabled | boolean | Defines if REST API endpoint should be exposed via Ingress controller | `False` | | | ingresses.restapi.enabled | boolean | Defines if REST API endpoint should be exposed via Ingress controller | `False` | | ||||||
| | ingresses.restapi.hosts | array | List of hosts for exposed REST API |  | | | ingresses.restapi.hosts | array | List of hosts for exposed REST API |  | | ||||||
| | ingresses.restapi.paths | array | List of paths to be exposed for REST API |  | | | ingresses.restapi.paths | array | List of paths to be exposed for REST API |  | | ||||||
| | volumes.owsec | array | Defines list of volumes to be attached to the Security |  | | | volumes.ucentralsec | array | Defines list of volumes to be attached to uCentralSec |  | | ||||||
| | persistence.enabled | boolean | Defines if Security requires Persistent Volume (required for permanent files storage and SQLite DB if enabled) | `True` | | | persistence.enabled | boolean | Defines if uCentralSec requires Persistent Volume (required for permanent files storage and SQLite DB if enabled) | `True` | | ||||||
| | persistence.accessModes | array | Defines PV access modes |  | | | persistence.accessModes | array | Defines PV access modes |  | | ||||||
| | persistence.size | string | Defines PV size | `'10Gi'` | | | persistence.size | string | Defines PV size | `'10Gi'` | | ||||||
| | public_env_variables | hash | Defines list of environment variables to be passed to the Security | | | | public_env_variables | hash | Defines list of environment variables to be passed to uCentralSec | | | ||||||
| | configProperties | hash | Configuration properties that should be passed to the application in `owsec.properties`. May be passed by key in set (i.e. `configProperties."rtty\.token"`) | | | | configProperties | hash | Configuration properties that should be passed to the application in `ucentralsec.properties`. May be passed by key in set (i.e. `configProperties."rtty\.token"`) | | | ||||||
| | certs | hash | Defines files (keys and certificates) that should be passed to the Security (PEM format is adviced to be used) (see `volumes.owsec` on where it is mounted) |  | | | certs | hash | Defines files (keys and certificates) that should be passed to uCentralSec (PEM format is adviced to be used) (see `volumes.ucentralsec` on where it is mounted) |  | | ||||||
|  |  | ||||||
|  |  | ||||||
| Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, | Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| {{- define "owsec.config" -}} | {{- define "ucentralsec.config" -}} | ||||||
| {{- range $key, $value := .Values.configProperties }} | {{- range $key, $value := .Values.configProperties }} | ||||||
| {{ $key }} = {{ $value }} | {{ $key }} = {{ $value }} | ||||||
| {{- end }} | {{- end }} | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ | |||||||
| {{/* | {{/* | ||||||
| Expand the name of the chart. | Expand the name of the chart. | ||||||
| */}} | */}} | ||||||
| {{- define "owsec.name" -}} | {{- define "ucentralsec.name" -}} | ||||||
| {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} | ||||||
| {{- end -}} | {{- end -}} | ||||||
|  |  | ||||||
| @@ -11,7 +11,7 @@ Create a default fully qualified app name. | |||||||
| We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). | ||||||
| If release name contains chart name it will be used as a full name. | If release name contains chart name it will be used as a full name. | ||||||
| */}} | */}} | ||||||
| {{- define "owsec.fullname" -}} | {{- define "ucentralsec.fullname" -}} | ||||||
| {{- if .Values.fullnameOverride -}} | {{- if .Values.fullnameOverride -}} | ||||||
| {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} | ||||||
| {{- else -}} | {{- else -}} | ||||||
| @@ -27,6 +27,6 @@ If release name contains chart name it will be used as a full name. | |||||||
| {{/* | {{/* | ||||||
| Create chart name and version as used by the chart label. | Create chart name and version as used by the chart label. | ||||||
| */}} | */}} | ||||||
| {{- define "owsec.chart" -}} | {{- define "ucentralsec.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 -}} | ||||||
|   | |||||||
| @@ -3,10 +3,10 @@ | |||||||
| apiVersion: apps/v1 | apiVersion: apps/v1 | ||||||
| kind: Deployment | kind: Deployment | ||||||
| metadata: | metadata: | ||||||
|   name: {{ include "owsec.fullname" . }} |   name: {{ include "ucentralsec.fullname" . }} | ||||||
|   labels: |   labels: | ||||||
|     app.kubernetes.io/name: {{ include "owsec.name" . }} |     app.kubernetes.io/name: {{ include "ucentralsec.name" . }} | ||||||
|     helm.sh/chart: {{ include "owsec.chart" . }} |     helm.sh/chart: {{ include "ucentralsec.chart" . }} | ||||||
|     app.kubernetes.io/instance: {{ .Release.Name }} |     app.kubernetes.io/instance: {{ .Release.Name }} | ||||||
|     app.kubernetes.io/managed-by: {{ .Release.Service }} |     app.kubernetes.io/managed-by: {{ .Release.Service }} | ||||||
| spec: | spec: | ||||||
| @@ -15,28 +15,28 @@ spec: | |||||||
|     type: {{ .Values.strategyType }} |     type: {{ .Values.strategyType }} | ||||||
|   selector: |   selector: | ||||||
|     matchLabels: |     matchLabels: | ||||||
|       app.kubernetes.io/name: {{ include "owsec.name" . }} |       app.kubernetes.io/name: {{ include "ucentralsec.name" . }} | ||||||
|       app.kubernetes.io/instance: {{ .Release.Name }} |       app.kubernetes.io/instance: {{ .Release.Name }} | ||||||
|       {{- with .Values.services.owsec.labels }} |       {{- with .Values.services.ucentralsec.labels }} | ||||||
|       {{- toYaml . | nindent 6 }} |       {{- toYaml . | nindent 6 }} | ||||||
|       {{- end }} |       {{- end }} | ||||||
|   template: |   template: | ||||||
|     metadata: |     metadata: | ||||||
|       annotations: |       annotations: | ||||||
|         checksum/config: {{ include "owsec.config" . | sha256sum }} |         checksum/config: {{ include "ucentralsec.config" . | sha256sum }} | ||||||
|       labels: |       labels: | ||||||
|         app.kubernetes.io/name: {{ include "owsec.name" . }} |         app.kubernetes.io/name: {{ include "ucentralsec.name" . }} | ||||||
|         app.kubernetes.io/instance: {{ .Release.Name }} |         app.kubernetes.io/instance: {{ .Release.Name }} | ||||||
|         {{- with .Values.services.owsec.labels }} |         {{- with .Values.services.ucentralsec.labels }} | ||||||
|         {{- toYaml . | nindent 8 }} |         {{- toYaml . | nindent 8 }} | ||||||
|         {{- end }} |         {{- end }} | ||||||
|     spec: |     spec: | ||||||
|  |  | ||||||
|       containers: |       containers: | ||||||
|  |  | ||||||
|         - name: owsec |         - name: ucentralsec | ||||||
|           image: "{{ .Values.images.owsec.repository }}:{{ .Values.images.owsec.tag }}" |           image: "{{ .Values.images.ucentralsec.repository }}:{{ .Values.images.ucentralsec.tag }}" | ||||||
|           imagePullPolicy: {{ .Values.images.owsec.pullPolicy }} |           imagePullPolicy: {{ .Values.images.ucentralsec.pullPolicy }} | ||||||
|  |  | ||||||
|           env: |           env: | ||||||
|             - name: KUBERNETES_DEPLOYED |             - name: KUBERNETES_DEPLOYED | ||||||
| @@ -49,19 +49,19 @@ spec: | |||||||
|             - name: {{ $key }} |             - name: {{ $key }} | ||||||
|               valueFrom: |               valueFrom: | ||||||
|                 secretKeyRef: |                 secretKeyRef: | ||||||
|                   name: {{ include "owsec.fullname" $root }}-env |                   name: {{ include "ucentralsec.fullname" $root }}-env | ||||||
|                   key: {{ $key }} |                   key: {{ $key }} | ||||||
|           {{- end }} |           {{- end }} | ||||||
|  |  | ||||||
|           ports: |           ports: | ||||||
|           {{- range $port, $portValue := .Values.services.owsec.ports }} |           {{- range $port, $portValue := .Values.services.ucentralsec.ports }} | ||||||
|             - name: {{ $port }} |             - name: {{ $port }} | ||||||
|               containerPort: {{ $portValue.targetPort }} |               containerPort: {{ $portValue.targetPort }} | ||||||
|               protocol: {{ $portValue.protocol }} |               protocol: {{ $portValue.protocol }} | ||||||
|           {{- end }} |           {{- end }} | ||||||
|  |  | ||||||
|           volumeMounts: |           volumeMounts: | ||||||
|           {{- range .Values.volumes.owsec }} |           {{- range .Values.volumes.ucentralsec }} | ||||||
|           - name: {{ .name }} |           - name: {{ .name }} | ||||||
|             mountPath: {{ .mountPath }} |             mountPath: {{ .mountPath }} | ||||||
|             {{- if .subPath }} |             {{- if .subPath }} | ||||||
| @@ -69,13 +69,13 @@ spec: | |||||||
|             {{- end }} |             {{- end }} | ||||||
|           {{- end }} |           {{- end }} | ||||||
|  |  | ||||||
|           {{- if .Values.checks.owsec.liveness }} |           {{- if .Values.checks.ucentralsec.liveness }} | ||||||
|           livenessProbe: |           livenessProbe: | ||||||
|             {{- toYaml .Values.checks.owsec.liveness | nindent 12 }} |             {{- toYaml .Values.checks.ucentralsec.liveness | nindent 12 }} | ||||||
|           {{- end }} |           {{- end }} | ||||||
|           {{- if .Values.checks.owsec.readiness }} |           {{- if .Values.checks.ucentralsec.readiness }} | ||||||
|           readinessProbe: |           readinessProbe: | ||||||
|             {{- toYaml .Values.checks.owsec.readiness | nindent 12 }} |             {{- toYaml .Values.checks.ucentralsec.readiness | nindent 12 }} | ||||||
|           {{- end }} |           {{- end }} | ||||||
|  |  | ||||||
|           {{- with .Values.resources }} |           {{- with .Values.resources }} | ||||||
| @@ -83,15 +83,10 @@ spec: | |||||||
|             {{- toYaml . | nindent 12 }} |             {{- toYaml . | nindent 12 }} | ||||||
|           {{- end }} |           {{- end }} | ||||||
|  |  | ||||||
|       {{- with .Values.securityContext }} |  | ||||||
|       securityContext: |  | ||||||
|         {{- toYaml . | nindent 8 }} |  | ||||||
|       {{- end }} |  | ||||||
|  |  | ||||||
|       imagePullSecrets: |       imagePullSecrets: | ||||||
|       {{- range $image, $imageValue := .Values.images }} |       {{- range $image, $imageValue := .Values.images }} | ||||||
|         {{- if $imageValue.regcred }} |         {{- if $imageValue.regcred }} | ||||||
|       - name: {{ include "owsec.fullname" $root }}-{{ $image }}-regcred |       - name: {{ include "ucentralsec.fullname" $root }}-{{ $image }}-regcred | ||||||
|         {{- end }} |         {{- end }} | ||||||
|       {{- end }} |       {{- end }} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -5,10 +5,10 @@ | |||||||
| apiVersion: extensions/v1beta1 | apiVersion: extensions/v1beta1 | ||||||
| kind: Ingress | kind: Ingress | ||||||
| metadata: | metadata: | ||||||
|   name: {{ include "owsec.fullname" $root }}-{{ $ingress }} |   name: {{ include "ucentralsec.fullname" $root }}-{{ $ingress }} | ||||||
|   labels: |   labels: | ||||||
|     app.kubernetes.io/name: {{ include "owsec.name" $root }} |     app.kubernetes.io/name: {{ include "ucentralsec.name" $root }} | ||||||
|     helm.sh/chart: {{ include "owsec.chart" $root }} |     helm.sh/chart: {{ include "ucentralsec.chart" $root }} | ||||||
|     app.kubernetes.io/instance: {{ $root.Release.Name }} |     app.kubernetes.io/instance: {{ $root.Release.Name }} | ||||||
|     app.kubernetes.io/managed-by: {{ $root.Release.Service }} |     app.kubernetes.io/managed-by: {{ $root.Release.Service }} | ||||||
|   {{- with $ingressValue.annotations }} |   {{- with $ingressValue.annotations }} | ||||||
| @@ -37,7 +37,7 @@ spec: | |||||||
|       {{- range $ingressValue.paths }} |       {{- range $ingressValue.paths }} | ||||||
|         - path: {{ .path }} |         - path: {{ .path }} | ||||||
|           backend: |           backend: | ||||||
|             serviceName: {{ include "owsec.fullname" $root }}-{{ .serviceName }} |             serviceName: {{ include "ucentralsec.fullname" $root }}-{{ .serviceName }} | ||||||
|             servicePort: {{ .servicePort }} |             servicePort: {{ .servicePort }} | ||||||
|       {{- end }} |       {{- end }} | ||||||
|   {{- end }} |   {{- end }} | ||||||
|   | |||||||
| @@ -3,10 +3,10 @@ | |||||||
| apiVersion: v1 | apiVersion: v1 | ||||||
| kind: PersistentVolumeClaim | kind: PersistentVolumeClaim | ||||||
| metadata: | metadata: | ||||||
|   name: {{ template "owsec.fullname" . }}-pvc |   name: {{ template "ucentralsec.fullname" . }}-pvc | ||||||
|   labels: |   labels: | ||||||
|     app.kubernetes.io/name: {{ include "owsec.name" . }} |     app.kubernetes.io/name: {{ include "ucentralsec.name" . }} | ||||||
|     helm.sh/chart: {{ include "owsec.chart" . }} |     helm.sh/chart: {{ include "ucentralsec.chart" . }} | ||||||
|     app.kubernetes.io/instance: {{ .Release.Name }} |     app.kubernetes.io/instance: {{ .Release.Name }} | ||||||
|     app.kubernetes.io/managed-by: {{ .Release.Service }} |     app.kubernetes.io/managed-by: {{ .Release.Service }} | ||||||
|   {{- with .Values.persistence.annotations  }} |   {{- with .Values.persistence.annotations  }} | ||||||
|   | |||||||
| @@ -2,11 +2,11 @@ | |||||||
| apiVersion: v1 | apiVersion: v1 | ||||||
| metadata: | metadata: | ||||||
|   labels: |   labels: | ||||||
|     app.kuberentes.io/name: {{ include "owsec.name" . }} |     app.kuberentes.io/name: {{ include "ucentralsec.name" . }} | ||||||
|     helm.sh/chart: {{ include "owsec.chart" . }} |     helm.sh/chart: {{ include "ucentralsec.chart" . }} | ||||||
|     app.kubernetes.io/instance: {{ .Release.Name }} |     app.kubernetes.io/instance: {{ .Release.Name }} | ||||||
|     app.kubernetes.io/managed-by: {{ .Release.Service }} |     app.kubernetes.io/managed-by: {{ .Release.Service }} | ||||||
|   name: {{ include "owsec.fullname" . }}-certs |   name: {{ include "ucentralsec.fullname" . }}-certs | ||||||
| kind: Secret | kind: Secret | ||||||
| type: Opaque | type: Opaque | ||||||
| data: | data: | ||||||
|   | |||||||
| @@ -2,12 +2,12 @@ | |||||||
| apiVersion: v1 | apiVersion: v1 | ||||||
| metadata: | metadata: | ||||||
|   labels: |   labels: | ||||||
|     app.kuberentes.io/name: {{ include "owsec.name" . }} |     app.kuberentes.io/name: {{ include "ucentralsec.name" . }} | ||||||
|     helm.sh/chart: {{ include "owsec.chart" . }} |     helm.sh/chart: {{ include "ucentralsec.chart" . }} | ||||||
|     app.kubernetes.io/instance: {{ .Release.Name }} |     app.kubernetes.io/instance: {{ .Release.Name }} | ||||||
|     app.kubernetes.io/managed-by: {{ .Release.Service }} |     app.kubernetes.io/managed-by: {{ .Release.Service }} | ||||||
|   name: {{ include "owsec.fullname" . }}-config |   name: {{ include "ucentralsec.fullname" . }}-config | ||||||
| kind: Secret | kind: Secret | ||||||
| type: Opaque | type: Opaque | ||||||
| data: | data: | ||||||
|   owsec.properties: {{ include "owsec.config" . | b64enc }} |   ucentralsec.properties: {{ include "ucentralsec.config" . | b64enc }} | ||||||
|   | |||||||
| @@ -2,11 +2,11 @@ | |||||||
| apiVersion: v1 | apiVersion: v1 | ||||||
| metadata: | metadata: | ||||||
|   labels: |   labels: | ||||||
|     app.kuberentes.io/name: {{ include "owsec.name" . }} |     app.kuberentes.io/name: {{ include "ucentralsec.name" . }} | ||||||
|     helm.sh/chart: {{ include "owsec.chart" . }} |     helm.sh/chart: {{ include "ucentralsec.chart" . }} | ||||||
|     app.kubernetes.io/instance: {{ .Release.Name }} |     app.kubernetes.io/instance: {{ .Release.Name }} | ||||||
|     app.kubernetes.io/managed-by: {{ .Release.Service }} |     app.kubernetes.io/managed-by: {{ .Release.Service }} | ||||||
|   name: {{ include "owsec.fullname" . }}-env |   name: {{ include "ucentralsec.fullname" . }}-env | ||||||
| kind: Secret | kind: Secret | ||||||
| type: Opaque | type: Opaque | ||||||
| data: | data: | ||||||
|   | |||||||
| @@ -10,11 +10,11 @@ kind: Secret | |||||||
| type: kubernetes.io/dockerconfigjson | type: kubernetes.io/dockerconfigjson | ||||||
| metadata: | metadata: | ||||||
|   labels: |   labels: | ||||||
|     app.kuberentes.io/name: {{ include "owsec.name" $root }} |     app.kuberentes.io/name: {{ include "ucentralsec.name" $root }} | ||||||
|     helm.sh/chart: {{ include "owsec.chart" $root }} |     helm.sh/chart: {{ include "ucentralsec.chart" $root }} | ||||||
|     app.kubernetes.io/instance: {{ $root.Release.Name }} |     app.kubernetes.io/instance: {{ $root.Release.Name }} | ||||||
|     app.kubernetes.io/managed-by: {{ $root.Release.Service }} |     app.kubernetes.io/managed-by: {{ $root.Release.Service }} | ||||||
|   name: {{ include "owsec.fullname" $root }}-{{ $image }}-regcred |   name: {{ include "ucentralsec.fullname" $root }}-{{ $image }}-regcred | ||||||
| data: | data: | ||||||
|   .dockerconfigjson: {{ template "imagePullSecret" $imageValue.regcred }} |   .dockerconfigjson: {{ template "imagePullSecret" $imageValue.regcred }} | ||||||
| {{- end }} | {{- end }} | ||||||
|   | |||||||
| @@ -4,14 +4,14 @@ | |||||||
| apiVersion: v1 | apiVersion: v1 | ||||||
| kind: Service | kind: Service | ||||||
| metadata: | metadata: | ||||||
|   name: {{ include "owsec.fullname" $root }}-{{ $service }} |   name: {{ include "ucentralsec.fullname" $root }}-{{ $service }} | ||||||
|   {{- with $serviceValue.annotations }} |   {{- with $serviceValue.annotations }} | ||||||
|   annotations: |   annotations: | ||||||
|     {{- toYaml . | nindent 4 }} |     {{- toYaml . | nindent 4 }} | ||||||
|   {{- end }} |   {{- end }} | ||||||
|   labels: |   labels: | ||||||
|     app.kubernetes.io/name: {{ include "owsec.name" $root }} |     app.kubernetes.io/name: {{ include "ucentralsec.name" $root }} | ||||||
|     helm.sh/chart: {{ include "owsec.chart" $root }} |     helm.sh/chart: {{ include "ucentralsec.chart" $root }} | ||||||
|     app.kubernetes.io/instance: {{ $root.Release.Name }} |     app.kubernetes.io/instance: {{ $root.Release.Name }} | ||||||
|     app.kubernetes.io/managed-by: {{ $root.Release.Service }} |     app.kubernetes.io/managed-by: {{ $root.Release.Service }} | ||||||
|  |  | ||||||
| @@ -39,7 +39,7 @@ spec: | |||||||
|       {{- end }} |       {{- end }} | ||||||
|   {{- end }} |   {{- end }} | ||||||
|   selector: |   selector: | ||||||
|     app.kubernetes.io/name: {{ include "owsec.name" $root }} |     app.kubernetes.io/name: {{ include "ucentralsec.name" $root }} | ||||||
|     app.kubernetes.io/instance: {{ $root.Release.Name }} |     app.kubernetes.io/instance: {{ $root.Release.Name }} | ||||||
|     {{- with $serviceValue.labels }} |     {{- with $serviceValue.labels }} | ||||||
|     {{- toYaml . | nindent 4 }} |     {{- toYaml . | nindent 4 }} | ||||||
|   | |||||||
							
								
								
									
										169
									
								
								helm/values.yaml
									
									
									
									
									
								
							
							
						
						
									
										169
									
								
								helm/values.yaml
									
									
									
									
									
								
							| @@ -6,9 +6,9 @@ nameOverride: "" | |||||||
| fullnameOverride: "" | fullnameOverride: "" | ||||||
|  |  | ||||||
| images: | images: | ||||||
|   owsec: |   ucentralsec: | ||||||
|     repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owsec |     repository: tip-tip-wlan-cloud-ucentral.jfrog.io/ucentralsec | ||||||
|     tag: v2.2.0-RC1 |     tag: v2.0.0-RC1 | ||||||
|     pullPolicy: Always |     pullPolicy: Always | ||||||
| #    regcred: | #    regcred: | ||||||
| #      registry: tip-tip-wlan-cloud-ucentral.jfrog.io | #      registry: tip-tip-wlan-cloud-ucentral.jfrog.io | ||||||
| @@ -16,7 +16,7 @@ images: | |||||||
| #      password: password | #      password: password | ||||||
|  |  | ||||||
| services: | services: | ||||||
|   owsec: |   ucentralsec: | ||||||
|     type: LoadBalancer |     type: LoadBalancer | ||||||
|     ports: |     ports: | ||||||
|       restapi: |       restapi: | ||||||
| @@ -29,7 +29,7 @@ services: | |||||||
|         protocol: TCP |         protocol: TCP | ||||||
|  |  | ||||||
| checks: | checks: | ||||||
|   owsec: |   ucentralsec: | ||||||
|     liveness: |     liveness: | ||||||
|       httpGet: |       httpGet: | ||||||
|         path: / |         path: / | ||||||
| @@ -49,29 +49,29 @@ ingresses: | |||||||
|     - restapi.chart-example.local |     - restapi.chart-example.local | ||||||
|     paths: |     paths: | ||||||
|     - path: / |     - path: / | ||||||
|       serviceName: owsec |       serviceName: ucentralsec | ||||||
|       servicePort: restapi |       servicePort: restapi | ||||||
|  |  | ||||||
| volumes: | volumes: | ||||||
|   owsec: |   ucentralsec: | ||||||
|     - name: config |     - name: config | ||||||
|       mountPath: /owsec-data/owsec.properties |       mountPath: /ucentralsec-data/ucentralsec.properties | ||||||
|       subPath: owsec.properties |       subPath: ucentralsec.properties | ||||||
|       # Template below will be rendered in template |       # Template below will be rendered in template | ||||||
|       volumeDefinition: | |       volumeDefinition: | | ||||||
|         secret: |         secret: | ||||||
|           secretName: {{ include "owsec.fullname" . }}-config |           secretName: {{ include "ucentralsec.fullname" . }}-config | ||||||
|     - name: certs |     - name: certs | ||||||
|       mountPath: /owsec-data/certs |       mountPath: /ucentralsec-data/certs | ||||||
|       volumeDefinition: | |       volumeDefinition: | | ||||||
|         secret: |         secret: | ||||||
|           secretName: {{ include "owsec.fullname" . }}-certs |           secretName: {{ include "ucentralsec.fullname" . }}-certs | ||||||
|     # Change this if you want to use another volume type |     # Change this if you want to use another volume type | ||||||
|     - name: persist |     - name: persist | ||||||
|       mountPath: /owsec-data/persist |       mountPath: /ucentralsec-data/persist | ||||||
|       volumeDefinition: | |       volumeDefinition: | | ||||||
|         persistentVolumeClaim: |         persistentVolumeClaim: | ||||||
|           claimName: {{ template "owsec.fullname" . }}-pvc |           claimName: {{ template "ucentralsec.fullname" . }}-pvc | ||||||
|  |  | ||||||
| resources: {} | resources: {} | ||||||
|   # We usually recommend not to specify default resources and to leave this as a conscious |   # We usually recommend not to specify default resources and to leave this as a conscious | ||||||
| @@ -85,9 +85,6 @@ resources: {} | |||||||
|   #  cpu: 100m |   #  cpu: 100m | ||||||
|   #  memory: 128Mi |   #  memory: 128Mi | ||||||
|  |  | ||||||
| securityContext: |  | ||||||
|   fsGroup: 101 |  | ||||||
|  |  | ||||||
| nodeSelector: {} | nodeSelector: {} | ||||||
|  |  | ||||||
| tolerations: [] | tolerations: [] | ||||||
| @@ -104,49 +101,48 @@ persistence: | |||||||
|  |  | ||||||
| # Application | # Application | ||||||
| public_env_variables: | public_env_variables: | ||||||
|   OWSEC_ROOT: /owsec-data |   UCENTRALSEC_ROOT: /ucentralsec-data | ||||||
|   OWSEC_CONFIG: /owsec-data |   UCENTRALSEC_CONFIG: /ucentralsec-data | ||||||
|  |  | ||||||
| secret_env_variables: {} | secret_env_variables: {} | ||||||
|  |  | ||||||
| configProperties: | configProperties: | ||||||
|   # -> Public part |   # -> Public part | ||||||
|   # REST API |   # REST API | ||||||
|   openwifi.restapi.host.0.backlog: 100 |   ucentral.restapi.host.0.backlog: 100 | ||||||
|   openwifi.restapi.host.0.security: relaxed |   ucentral.restapi.host.0.security: relaxed | ||||||
|   openwifi.restapi.host.0.rootca: $OWSEC_ROOT/certs/restapi-ca.pem |   ucentral.restapi.host.0.rootca: $UCENTRALSEC_ROOT/certs/restapi-ca.pem | ||||||
|   openwifi.restapi.host.0.address: "*" |   ucentral.restapi.host.0.address: "*" | ||||||
|   openwifi.restapi.host.0.port: 16001 |   ucentral.restapi.host.0.port: 16001 | ||||||
|   openwifi.restapi.host.0.cert: $OWSEC_ROOT/certs/restapi-cert.pem |   ucentral.restapi.host.0.cert: $UCENTRALSEC_ROOT/certs/restapi-cert.pem | ||||||
|   openwifi.restapi.host.0.key: $OWSEC_ROOT/certs/restapi-key.pem |   ucentral.restapi.host.0.key: $UCENTRALSEC_ROOT/certs/restapi-key.pem | ||||||
|   openwifi.restapi.wwwassets: $OWSEC_ROOT/wwwassets |   ucentral.restapi.wwwassets: $UCENTRALSEC_ROOT/wwwassets | ||||||
|   openwifi.internal.restapi.host.0.backlog: 100 |   ucentral.internal.restapi.host.0.backlog: 100 | ||||||
|   openwifi.internal.restapi.host.0.security: relaxed |   ucentral.internal.restapi.host.0.security: relaxed | ||||||
|   openwifi.internal.restapi.host.0.rootca: $OWSEC_ROOT/certs/restapi-ca.pem |   ucentral.internal.restapi.host.0.rootca: $UCENTRALSEC_ROOT/certs/restapi-ca.pem | ||||||
|   openwifi.internal.restapi.host.0.address: "*" |   ucentral.internal.restapi.host.0.address: "*" | ||||||
|   openwifi.internal.restapi.host.0.port: 17001 |   ucentral.internal.restapi.host.0.port: 17001 | ||||||
|   openwifi.internal.restapi.host.0.cert: $OWSEC_ROOT/certs/restapi-cert.pem |   ucentral.internal.restapi.host.0.cert: $UCENTRALSEC_ROOT/certs/restapi-cert.pem | ||||||
|   openwifi.internal.restapi.host.0.key: $OWSEC_ROOT/certs/restapi-key.pem |   ucentral.internal.restapi.host.0.key: $UCENTRALSEC_ROOT/certs/restapi-key.pem | ||||||
|   # Authentication |   # Authentication | ||||||
|   authentication.enabled: true |   authentication.enabled: true | ||||||
|   authentication.default.access: master |   authentication.default.access: master | ||||||
|   authentication.service.type: internal |   authentication.service.type: internal | ||||||
|   # Mailer |   # Mailer | ||||||
|   mailer.hostname: smtp.gmail.com |   mailer.hostname: smtp.gmail.com | ||||||
|   mailer.sender: OpenWIFI |  | ||||||
|   mailer.loginmethod: login |   mailer.loginmethod: login | ||||||
|   mailer.port: 587 |   mailer.port: 587 | ||||||
|   mailer.templates: $OWSEC_ROOT/templates |   mailer.templates: $UCENTRALSEC_ROOT/templates | ||||||
|   # ALB |   # ALB | ||||||
|   alb.enable: "true" |   alb.enable: "true" | ||||||
|   alb.port: 16101 |   alb.port: 16101 | ||||||
|   # Kafka |   # Kafka | ||||||
|   openwifi.kafka.enable: "false" |   ucentral.kafka.enable: "false" | ||||||
|   openwifi.kafka.group.id: security |   ucentral.kafka.group.id: security | ||||||
|   openwifi.kafka.client.id: security1 |   ucentral.kafka.client.id: security1 | ||||||
|   openwifi.kafka.brokerlist: localhost:9092 |   ucentral.kafka.brokerlist: localhost:9092 | ||||||
|   openwifi.kafka.auto.commit: false |   ucentral.kafka.auto.commit: false | ||||||
|   openwifi.kafka.queue.buffering.max.ms: 50 |   ucentral.kafka.queue.buffering.max.ms: 50 | ||||||
|   # Storage |   # Storage | ||||||
|   storage.type: sqlite # (sqlite|postgresql|mysql|odbc) |   storage.type: sqlite # (sqlite|postgresql|mysql|odbc) | ||||||
|   ## SQLite |   ## SQLite | ||||||
| @@ -157,32 +153,32 @@ configProperties: | |||||||
|   storage.type.postgresql.maxsessions: 64 |   storage.type.postgresql.maxsessions: 64 | ||||||
|   storage.type.postgresql.idletime: 60 |   storage.type.postgresql.idletime: 60 | ||||||
|   storage.type.postgresql.host: localhost |   storage.type.postgresql.host: localhost | ||||||
|   storage.type.postgresql.database: owsec |   storage.type.postgresql.database: ucentral | ||||||
|   storage.type.postgresql.port: 5432 |   storage.type.postgresql.port: 5432 | ||||||
|   storage.type.postgresql.connectiontimeout: 60 |   storage.type.postgresql.connectiontimeout: 60 | ||||||
|   ## MySQL |   ## MySQL | ||||||
|   storage.type.mysql.maxsessions: 64 |   storage.type.mysql.maxsessions: 64 | ||||||
|   storage.type.mysql.idletime: 60 |   storage.type.mysql.idletime: 60 | ||||||
|   storage.type.mysql.host: localhost |   storage.type.mysql.host: localhost | ||||||
|   storage.type.mysql.database: owsec |   storage.type.mysql.database: ucentral | ||||||
|   storage.type.mysql.port: 3306 |   storage.type.mysql.port: 3306 | ||||||
|   storage.type.mysql.connectiontimeout: 60 |   storage.type.mysql.connectiontimeout: 60 | ||||||
|   # System |   # System | ||||||
|   openwifi.service.key: $OWSEC_ROOT/certs/restapi-key.pem |   ucentral.service.key: $UCENTRALSEC_ROOT/certs/restapi-key.pem | ||||||
|   openwifi.system.data: $OWSEC_ROOT/persist |   ucentral.system.data: $UCENTRALSEC_ROOT/persist | ||||||
|   openwifi.system.debug: "true" |   ucentral.system.debug: "true" | ||||||
|   openwifi.system.uri.private: https://localhost:17001 |   ucentral.system.uri.private: https://localhost:17001 | ||||||
|   openwifi.system.uri.public: https://localhost:16001 |   ucentral.system.uri.public: https://localhost:16001 | ||||||
|   openwifi.system.uri.ui: https://localhost |   ucentral.system.uri.ui: https://localhost | ||||||
|   openwifi.system.commandchannel: /tmp/app_owsec |   ucentral.system.commandchannel: /tmp/app_ucentralsec | ||||||
|   # Logging |   # Logging | ||||||
|   logging.formatters.f1.class: PatternFormatter |   logging.formatters.f1.class: PatternFormatter | ||||||
|   logging.formatters.f1.pattern: "%Y-%m-%d %H:%M:%S %s: [%p] %t" |   logging.formatters.f1.pattern: "%s: [%p] %t" | ||||||
|   logging.formatters.f1.times: UTC |   logging.formatters.f1.times: UTC | ||||||
|   logging.channels.c1.class: ConsoleChannel |   logging.channels.c1.class: ConsoleChannel | ||||||
|   logging.channels.c1.formatter: f1 |   logging.channels.c1.formatter: f1 | ||||||
|   logging.channels.c2.class: FileChannel |   logging.channels.c2.class: FileChannel | ||||||
|   logging.channels.c2.path: /tmp/log_owsec |   logging.channels.c2.path: /tmp/log_ucentralsec | ||||||
|   logging.channels.c2.formatter.class: PatternFormatter |   logging.channels.c2.formatter.class: PatternFormatter | ||||||
|   logging.channels.c2.formatter.pattern: "%Y-%m-%d %H:%M:%S %s: [%p] %t" |   logging.channels.c2.formatter.pattern: "%Y-%m-%d %H:%M:%S %s: [%p] %t" | ||||||
|   logging.channels.c2.rotation: "20 M" |   logging.channels.c2.rotation: "20 M" | ||||||
| @@ -190,13 +186,13 @@ configProperties: | |||||||
|   logging.channels.c2.purgeCount: 20 |   logging.channels.c2.purgeCount: 20 | ||||||
|   logging.channels.c3.class: ConsoleChannel |   logging.channels.c3.class: ConsoleChannel | ||||||
|   logging.channels.c3.pattern: "%s: [%p] %t" |   logging.channels.c3.pattern: "%s: [%p] %t" | ||||||
|   logging.loggers.root.channel: c1 |   logging.loggers.root.channel: c2 | ||||||
|   logging.loggers.root.level: debug |   logging.loggers.root.level: debug | ||||||
|  |  | ||||||
|   # -> Secret part |   # -> Secret part | ||||||
|   # REST API |   # REST API | ||||||
|   openwifi.restapi.host.0.key.password: mypassword |   ucentral.restapi.host.0.key.password: mypassword | ||||||
|   openwifi.internal.restapi.host.0.key.password: mypassword |   ucentral.internal.restapi.host.0.key.password: mypassword | ||||||
|   # Authentication |   # Authentication | ||||||
|   authentication.default.username: tip@ucentral.com |   authentication.default.username: tip@ucentral.com | ||||||
|   authentication.default.password: 13268b7daa751240369d125e79c873bd8dd3bef7981bdfd38ea03dbb1fbe7dcf |   authentication.default.password: 13268b7daa751240369d125e79c873bd8dd3bef7981bdfd38ea03dbb1fbe7dcf | ||||||
| @@ -215,64 +211,3 @@ certs: | |||||||
|   # restapi-ca.pem: "" |   # restapi-ca.pem: "" | ||||||
|   # restapi-cert.pem: "" |   # restapi-cert.pem: "" | ||||||
|   # restapi-key.pem: "" |   # restapi-key.pem: "" | ||||||
|  |  | ||||||
| # PostgreSQL (https://github.com/bitnami/charts/tree/master/bitnami/postgresql) |  | ||||||
| postgresql: |  | ||||||
|   enabled: false |  | ||||||
|  |  | ||||||
|   image: |  | ||||||
|     registry: docker.io |  | ||||||
|     repository: bitnami/postgresql |  | ||||||
|     tag: 11.13.0-debian-10-r0 |  | ||||||
|  |  | ||||||
|   postgresqlPostgresPassword: "rootPassword" |  | ||||||
|   postgresqlUsername: stephb |  | ||||||
|   postgresqlPassword: snoopy99 |  | ||||||
|   postgresqlDatabase: owgw |  | ||||||
|  |  | ||||||
|   persistence: |  | ||||||
|     enabled: true |  | ||||||
|     storageClass: "" |  | ||||||
|     size: 8Gi |  | ||||||
|  |  | ||||||
| # MySQL (https://github.com/bitnami/charts/tree/master/bitnami/mysql) |  | ||||||
| mysql: |  | ||||||
|   enabled: false |  | ||||||
|  |  | ||||||
|   image: |  | ||||||
|     registry: docker.io |  | ||||||
|     repository: bitnami/mysql |  | ||||||
|     tag: 8.0.26-debian-10-r10 |  | ||||||
|  |  | ||||||
|   auth: |  | ||||||
|     rootPassword: rootPassword |  | ||||||
|     database: owgw |  | ||||||
|     username: stephb |  | ||||||
|     password: snoopy99 |  | ||||||
|  |  | ||||||
|   primary: |  | ||||||
|     persistence: |  | ||||||
|       enabled: true |  | ||||||
|       storageClass: "" |  | ||||||
|       size: 8Gi |  | ||||||
|  |  | ||||||
| # MariaDB (https://github.com/bitnami/charts/tree/master/bitnami/mariadb) |  | ||||||
| mariadb: |  | ||||||
|   enabled: false |  | ||||||
|  |  | ||||||
|   image: |  | ||||||
|     registry: docker.io |  | ||||||
|     repository: bitnami/mariadb |  | ||||||
|     tag: 10.5.12-debian-10-r0 |  | ||||||
|  |  | ||||||
|   auth: |  | ||||||
|     rootPassword: rootPassword |  | ||||||
|     database: owgw |  | ||||||
|     username: stephb |  | ||||||
|     password: snoopy99 |  | ||||||
|  |  | ||||||
|   primary: |  | ||||||
|     persistence: |  | ||||||
|       enabled: true |  | ||||||
|       storageClass: "" |  | ||||||
|       size: 8Gi |  | ||||||
|   | |||||||
| @@ -287,8 +287,6 @@ components: | |||||||
|         securityPolicyChange: |         securityPolicyChange: | ||||||
|           type: integer |           type: integer | ||||||
|           format: int64 |           format: int64 | ||||||
|         userTypeProprietaryInfo: |  | ||||||
|           type: string |  | ||||||
| 
 | 
 | ||||||
|     UserList: |     UserList: | ||||||
|       type: object |       type: object | ||||||
| @@ -298,21 +296,6 @@ components: | |||||||
|           items: |           items: | ||||||
|             $ref: '#/components/schemas/UserInfo' |             $ref: '#/components/schemas/UserInfo' | ||||||
| 
 | 
 | ||||||
|     EMailInfo: |  | ||||||
|       type: object |  | ||||||
|       properties: |  | ||||||
|         from: |  | ||||||
|           type: string |  | ||||||
|           format: email |  | ||||||
|         subject: |  | ||||||
|           type: string |  | ||||||
|         recipients: |  | ||||||
|           type: array |  | ||||||
|           items: |  | ||||||
|             type: string |  | ||||||
|             format: email |  | ||||||
|         text: |  | ||||||
|           type: string |  | ||||||
| 
 | 
 | ||||||
|     ######################################################################################### |     ######################################################################################### | ||||||
|     ## |     ## | ||||||
| @@ -382,34 +365,6 @@ components: | |||||||
|         - $ref: '#/components/schemas/StringList' |         - $ref: '#/components/schemas/StringList' | ||||||
|         - $ref: '#/components/schemas/TagValuePairList' |         - $ref: '#/components/schemas/TagValuePairList' | ||||||
| 
 | 
 | ||||||
|     SystemInfoResults: |  | ||||||
|       type: object |  | ||||||
|       properties: |  | ||||||
|         version: |  | ||||||
|           type: string |  | ||||||
|         uptime: |  | ||||||
|           type: integer |  | ||||||
|           format: integer64 |  | ||||||
|         start: |  | ||||||
|           type: integer |  | ||||||
|           format: integer64 |  | ||||||
|         os: |  | ||||||
|           type: string |  | ||||||
|         processors: |  | ||||||
|           type: integer |  | ||||||
|         hostname: |  | ||||||
|           type: string |  | ||||||
|         certificates: |  | ||||||
|           type: array |  | ||||||
|           items: |  | ||||||
|             type: object |  | ||||||
|             properties: |  | ||||||
|               filename: |  | ||||||
|                 type: string |  | ||||||
|               expires: |  | ||||||
|                 type: integer |  | ||||||
|                 format: int64 |  | ||||||
| 
 |  | ||||||
|     ProfileAction: |     ProfileAction: | ||||||
|       type: object |       type: object | ||||||
|       properties: |       properties: | ||||||
| @@ -484,80 +439,6 @@ components: | |||||||
|           $ref: '#/components/schemas/UserInfo' |           $ref: '#/components/schemas/UserInfo' | ||||||
|         tokenInfo: |         tokenInfo: | ||||||
|           $ref: '#/components/schemas/WebTokenResult' |           $ref: '#/components/schemas/WebTokenResult' | ||||||
| 
 |  | ||||||
|     SystemCommandSetLogLevel: |  | ||||||
|       type: object |  | ||||||
|       properties: |  | ||||||
|         command: |  | ||||||
|           type: string |  | ||||||
|           enum: |  | ||||||
|             - setloglevel |  | ||||||
|         subsystems: |  | ||||||
|           type: array |  | ||||||
|           items: |  | ||||||
|             $ref: '#/components/schemas/TagValuePair' |  | ||||||
| 
 |  | ||||||
|     SystemCommandReload: |  | ||||||
|       type: object |  | ||||||
|       properties: |  | ||||||
|         command: |  | ||||||
|           type: string |  | ||||||
|           enum: |  | ||||||
|             - reload |  | ||||||
|         subsystems: |  | ||||||
|           type: array |  | ||||||
|           items: |  | ||||||
|             type: string |  | ||||||
|             example: these are the SubSystems names retrieve with the GetSubSystemsNamesResult. |  | ||||||
| 
 |  | ||||||
|     SystemCommandGetLogLevels: |  | ||||||
|       type: object |  | ||||||
|       properties: |  | ||||||
|         command: |  | ||||||
|           type: string |  | ||||||
|           enum: |  | ||||||
|             - getloglevels |  | ||||||
| 
 |  | ||||||
|     SystemGetLogLevelsResult: |  | ||||||
|       type: object |  | ||||||
|       properties: |  | ||||||
|         taglist: |  | ||||||
|           type: array |  | ||||||
|           items: |  | ||||||
|             $ref: '#/components/schemas/TagValuePair' |  | ||||||
| 
 |  | ||||||
|     SystemCommandGetLogLevelNames: |  | ||||||
|       type: object |  | ||||||
|       properties: |  | ||||||
|         command: |  | ||||||
|           type: string |  | ||||||
|           enum: |  | ||||||
|             - getloglevelnames |  | ||||||
| 
 |  | ||||||
|     SystemCommandGetSubsystemNames: |  | ||||||
|       type: object |  | ||||||
|       properties: |  | ||||||
|         command: |  | ||||||
|           type: string |  | ||||||
|           enum: |  | ||||||
|             - getsubsystemnames |  | ||||||
| 
 |  | ||||||
|     SystemCommandGetLogLevelNamesResult: |  | ||||||
|       type: object |  | ||||||
|       properties: |  | ||||||
|         list: |  | ||||||
|           type: array |  | ||||||
|           items: |  | ||||||
|             type: string |  | ||||||
| 
 |  | ||||||
|     SystemGetSubSystemNemesResult: |  | ||||||
|       type: object |  | ||||||
|       properties: |  | ||||||
|         taglist: |  | ||||||
|           type: array |  | ||||||
|           items: |  | ||||||
|             $ref: '#/components/schemas/TagValuePair' |  | ||||||
| 
 |  | ||||||
|     ######################################################################################### |     ######################################################################################### | ||||||
|     ## |     ## | ||||||
|     ## End of uCentral system wide values |     ## End of uCentral system wide values | ||||||
| @@ -623,7 +504,7 @@ paths: | |||||||
|               string |               string | ||||||
|           required: true |           required: true | ||||||
|       responses: |       responses: | ||||||
|         204: |         200: | ||||||
|           description: successful operation |           description: successful operation | ||||||
|           content: |           content: | ||||||
|             application/json: |             application/json: | ||||||
| @@ -732,7 +613,7 @@ paths: | |||||||
|             format: int64 |             format: int64 | ||||||
|           required: true |           required: true | ||||||
|       responses: |       responses: | ||||||
|         204: |         200: | ||||||
|           $ref: '#/components/responses/Success' |           $ref: '#/components/responses/Success' | ||||||
|         403: |         403: | ||||||
|           $ref: '#/components/responses/Unauthorized' |           $ref: '#/components/responses/Unauthorized' | ||||||
| @@ -850,7 +731,7 @@ paths: | |||||||
|             format: uuid |             format: uuid | ||||||
|           required: true |           required: true | ||||||
|       responses: |       responses: | ||||||
|         204: |         200: | ||||||
|           $ref: '#/components/responses/Success' |           $ref: '#/components/responses/Success' | ||||||
|         403: |         403: | ||||||
|           $ref: '#/components/responses/Unauthorized' |           $ref: '#/components/responses/Unauthorized' | ||||||
| @@ -894,42 +775,63 @@ paths: | |||||||
|         404: |         404: | ||||||
|           $ref: '#/components/responses/NotFound' |           $ref: '#/components/responses/NotFound' | ||||||
| 
 | 
 | ||||||
|   /email: |  | ||||||
|     post: |  | ||||||
|       tags: |  | ||||||
|         - EMail |  | ||||||
|       summary: Send test email with the system |  | ||||||
|       operationId: Send a test email |  | ||||||
|       requestBody: |  | ||||||
|         description: The requested message |  | ||||||
|         content: |  | ||||||
|           application/json: |  | ||||||
|             schema: |  | ||||||
|               $ref: '#/components/schemas/EMailInfo' |  | ||||||
|       responses: |  | ||||||
|         200: |  | ||||||
|           $ref: '#/components/responses/Success' |  | ||||||
|         403: |  | ||||||
|           $ref: '#/components/responses/Unauthorized' |  | ||||||
|         404: |  | ||||||
|           $ref: '#/components/responses/NotFound' |  | ||||||
|         500: |  | ||||||
|           description: Error description |  | ||||||
|           content: |  | ||||||
|             application/json: |  | ||||||
|               schema: |  | ||||||
|                 type: object |  | ||||||
|                 properties: |  | ||||||
|                   errors: |  | ||||||
|                     type: array |  | ||||||
|                     items: |  | ||||||
|                       type: string |  | ||||||
| 
 |  | ||||||
|   ######################################################################################### |   ######################################################################################### | ||||||
|   ## |   ## | ||||||
|   ## These are endpoints that all services in the uCentral stack must provide |   ## These are endpoints that all services in the uCentral stack must provide | ||||||
|   ## |   ## | ||||||
|   ######################################################################################### |   ######################################################################################### | ||||||
|  | 
 | ||||||
|  |   /system: | ||||||
|  |     post: | ||||||
|  |       tags: | ||||||
|  |         - System Commands | ||||||
|  |       summary: Perform some systeme wide commands | ||||||
|  |       operationId: systemCommand | ||||||
|  |       requestBody: | ||||||
|  |         description: Command details | ||||||
|  |         content: | ||||||
|  |           application/json: | ||||||
|  |             schema: | ||||||
|  |               $ref: '#/components/schemas/SystemCommandDetails' | ||||||
|  |       responses: | ||||||
|  |         200: | ||||||
|  |           description: Successfull command execution | ||||||
|  |           content: | ||||||
|  |             application/json: | ||||||
|  |               schema: | ||||||
|  |                 $ref: '#/components/schemas/SystemCommandResults' | ||||||
|  |         403: | ||||||
|  |           $ref: '#/components/responses/Unauthorized' | ||||||
|  |         404: | ||||||
|  |           $ref: '#/components/responses/NotFound' | ||||||
|  |     get: | ||||||
|  |       tags: | ||||||
|  |         - System Commands | ||||||
|  |       summary: Retrieve different values from the running service. | ||||||
|  |       operationId: getSystemCommand | ||||||
|  |       parameters: | ||||||
|  |         - in: query | ||||||
|  |           description: Get a value | ||||||
|  |           name: command | ||||||
|  |           schema: | ||||||
|  |             type: string | ||||||
|  |             enum: | ||||||
|  |               - version | ||||||
|  |               - times | ||||||
|  |         required: true | ||||||
|  | 
 | ||||||
|  |       responses: | ||||||
|  |         200: | ||||||
|  |           description: Successfull command execution | ||||||
|  |           content: | ||||||
|  |             application/json: | ||||||
|  |               schema: | ||||||
|  |                 $ref: '#/components/schemas/TagValuePair' | ||||||
|  |         403: | ||||||
|  |           $ref: '#/components/responses/Unauthorized' | ||||||
|  |         404: | ||||||
|  |           $ref: '#/components/responses/NotFound' | ||||||
|  | 
 | ||||||
|   /securityProfiles: |   /securityProfiles: | ||||||
|     get: |     get: | ||||||
|       tags: |       tags: | ||||||
| @@ -1000,65 +902,6 @@ paths: | |||||||
|         404: |         404: | ||||||
|           $ref: '#/components/responses/NotFound' |           $ref: '#/components/responses/NotFound' | ||||||
| 
 | 
 | ||||||
|   /system: |  | ||||||
|     post: |  | ||||||
|       tags: |  | ||||||
|         - System Commands |  | ||||||
|       summary: Perform some systeme wide commands |  | ||||||
|       operationId: systemCommand |  | ||||||
|       requestBody: |  | ||||||
|         description: Command details |  | ||||||
|         content: |  | ||||||
|           application/json: |  | ||||||
|             schema: |  | ||||||
|               oneOf: |  | ||||||
|                 - $ref: '#/components/schemas/SystemCommandSetLogLevel' |  | ||||||
|                 - $ref: '#/components/schemas/SystemCommandReload' |  | ||||||
|                 - $ref: '#/components/schemas/SystemCommandGetLogLevels' |  | ||||||
|                 - $ref: '#/components/schemas/SystemCommandGetLogLevelNames' |  | ||||||
|                 - $ref: '#/components/schemas/SystemCommandGetSubsystemNames' |  | ||||||
|       responses: |  | ||||||
|         200: |  | ||||||
|           description: Successfull command execution |  | ||||||
|           content: |  | ||||||
|             application/json: |  | ||||||
|               schema: |  | ||||||
|                 oneOf: |  | ||||||
|                   - $ref: '#/components/schemas/SystemGetLogLevelsResult' |  | ||||||
|                   - $ref: '#/components/schemas/SystemCommandGetLogLevelNamesResult' |  | ||||||
|                   - $ref: '#/components/schemas/SystemGetSubSystemNemesResult' |  | ||||||
|         403: |  | ||||||
|           $ref: '#/components/responses/Unauthorized' |  | ||||||
|         404: |  | ||||||
|           $ref: '#/components/responses/NotFound' |  | ||||||
|     get: |  | ||||||
|       tags: |  | ||||||
|         - System Commands |  | ||||||
|       summary: Retrieve different values from the running service. |  | ||||||
|       operationId: getSystemCommand |  | ||||||
|       parameters: |  | ||||||
|         - in: query |  | ||||||
|           description: Get a value |  | ||||||
|           name: command |  | ||||||
|           schema: |  | ||||||
|             type: string |  | ||||||
|             enum: |  | ||||||
|               - info |  | ||||||
|           required: true |  | ||||||
| 
 |  | ||||||
|       responses: |  | ||||||
|         200: |  | ||||||
|           description: Successfull command execution |  | ||||||
|           content: |  | ||||||
|             application/json: |  | ||||||
|               schema: |  | ||||||
|                 oneOf: |  | ||||||
|                   - $ref: '#/components/schemas/SystemInfoResults' |  | ||||||
|         403: |  | ||||||
|           $ref: '#/components/responses/Unauthorized' |  | ||||||
|         404: |  | ||||||
|           $ref: '#/components/responses/NotFound' |  | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
| ######################################################################################### | ######################################################################################### | ||||||
| ## | ## | ||||||
| @@ -1,146 +0,0 @@ | |||||||
| # |  | ||||||
| # uCentral protocol server for devices. This is where you point |  | ||||||
| # all your devices. You can replace the * for address by the specific |  | ||||||
| # address of one of your interfaces |  | ||||||
| # |  | ||||||
|  |  | ||||||
| # |  | ||||||
| # REST API access |  | ||||||
| # |  | ||||||
| openwifi.restapi.host.0.backlog = 100 |  | ||||||
| openwifi.restapi.host.0.security = relaxed |  | ||||||
| openwifi.restapi.host.0.rootca = ${RESTAPI_HOST_ROOTCA} |  | ||||||
| openwifi.restapi.host.0.address = * |  | ||||||
| openwifi.restapi.host.0.port = ${RESTAPI_HOST_PORT} |  | ||||||
| openwifi.restapi.host.0.cert = ${RESTAPI_HOST_CERT} |  | ||||||
| openwifi.restapi.host.0.key = ${RESTAPI_HOST_KEY} |  | ||||||
| openwifi.restapi.host.0.key.password = ${RESTAPI_HOST_KEY_PASSWORD} |  | ||||||
| openwifi.restapi.wwwassets = ${RESTAPI_WWWASSETS} |  | ||||||
|  |  | ||||||
| openwifi.internal.restapi.host.0.backlog = 100 |  | ||||||
| openwifi.internal.restapi.host.0.security = relaxed |  | ||||||
| openwifi.internal.restapi.host.0.rootca = ${INTERNAL_RESTAPI_HOST_ROOTCA} |  | ||||||
| openwifi.internal.restapi.host.0.address = * |  | ||||||
| openwifi.internal.restapi.host.0.port = ${INTERNAL_RESTAPI_HOST_PORT} |  | ||||||
| openwifi.internal.restapi.host.0.cert = ${INTERNAL_RESTAPI_HOST_CERT} |  | ||||||
| openwifi.internal.restapi.host.0.key = ${INTERNAL_RESTAPI_HOST_KEY} |  | ||||||
| openwifi.internal.restapi.host.0.key.password = ${INTERNAL_RESTAPI_HOST_KEY_PASSWORD} |  | ||||||
|  |  | ||||||
| # |  | ||||||
| # Generic section that all microservices must have |  | ||||||
| # |  | ||||||
| authentication.enabled = true |  | ||||||
| authentication.default.username = ${AUTHENTICATION_DEFAULT_USERNAME} |  | ||||||
| authentication.default.password = ${AUTHENTICATION_DEFAULT_PASSWORD} |  | ||||||
| openwifi.system.data = ${SYSTEM_DATA} |  | ||||||
| openwifi.system.uri.private = ${SYSTEM_URI_PRIVATE} |  | ||||||
| openwifi.system.uri.public = ${SYSTEM_URI_PUBLIC} |  | ||||||
| openwifi.system.uri.ui = ${SYSTEM_URI_UI} |  | ||||||
| openwifi.system.commandchannel = /tmp/app.ucentralsec |  | ||||||
| openwifi.service.key = ${SERVICE_KEY} |  | ||||||
| openwifi.service.key.password = ${SERVICE_KEY_PASSWORD} |  | ||||||
|  |  | ||||||
| # |  | ||||||
| # Security Microservice Specific Section |  | ||||||
| # |  | ||||||
| mailer.hostname = ${MAILER_HOSTNAME} |  | ||||||
| mailer.username = ${MAILER_USERNAME} |  | ||||||
| mailer.password = ${MAILER_PASSWORD} |  | ||||||
| mailer.sender = ${MAILER_SENDER} |  | ||||||
| mailer.loginmethod = login |  | ||||||
| mailer.port = ${MAILER_PORT} |  | ||||||
| mailer.templates = $UCENTRALSEC_ROOT/templates |  | ||||||
|  |  | ||||||
|  |  | ||||||
| ############################# |  | ||||||
| # Generic information for all micro services |  | ||||||
| ############################# |  | ||||||
| # |  | ||||||
| # NLB Support |  | ||||||
| # |  | ||||||
| alb.enable = true |  | ||||||
| alb.port = 16101 |  | ||||||
|  |  | ||||||
| # |  | ||||||
| # Kafka |  | ||||||
| # |  | ||||||
| openwifi.kafka.group.id = security |  | ||||||
| openwifi.kafka.client.id = security1 |  | ||||||
| openwifi.kafka.enable = ${KAFKA_ENABLE} |  | ||||||
| openwifi.kafka.brokerlist = ${KAFKA_BROKERLIST} |  | ||||||
| openwifi.kafka.auto.commit = false |  | ||||||
| openwifi.kafka.queue.buffering.max.ms = 50 |  | ||||||
|  |  | ||||||
| openwifi.document.policy.access = /wwwassets/access_policy.html |  | ||||||
| openwifi.document.policy.password = /wwwassets/password_policy.html |  | ||||||
| openwifi.avatar.maxsize = 2000000 |  | ||||||
| # |  | ||||||
| # This section select which form of persistence you need |  | ||||||
| # Only one selected at a time. If you select multiple, this service will die if a horrible |  | ||||||
| # death and might make your beer flat. |  | ||||||
| # |  | ||||||
| storage.type = ${STORAGE_TYPE} |  | ||||||
|  |  | ||||||
| storage.type.sqlite.db = security.db |  | ||||||
| storage.type.sqlite.idletime = 120 |  | ||||||
| storage.type.sqlite.maxsessions = 128 |  | ||||||
|  |  | ||||||
| storage.type.postgresql.maxsessions = 64 |  | ||||||
| storage.type.postgresql.idletime = 60 |  | ||||||
| storage.type.postgresql.host = ${STORAGE_TYPE_POSTGRESQL_HOST} |  | ||||||
| storage.type.postgresql.username = ${STORAGE_TYPE_POSTGRESQL_USERNAME} |  | ||||||
| storage.type.postgresql.password = ${STORAGE_TYPE_POSTGRESQL_PASSWORD} |  | ||||||
| storage.type.postgresql.database = ${STORAGE_TYPE_POSTGRESQL_DATABASE} |  | ||||||
| storage.type.postgresql.port = ${STORAGE_TYPE_POSTGRESQL_PORT} |  | ||||||
| storage.type.postgresql.connectiontimeout = 60 |  | ||||||
|  |  | ||||||
| storage.type.mysql.maxsessions = 64 |  | ||||||
| storage.type.mysql.idletime = 60 |  | ||||||
| storage.type.mysql.host = ${STORAGE_TYPE_MYSQL_HOST} |  | ||||||
| storage.type.mysql.username = ${STORAGE_TYPE_MYSQL_USERNAME} |  | ||||||
| storage.type.mysql.password = ${STORAGE_TYPE_MYSQL_PASSWORD} |  | ||||||
| storage.type.mysql.database = ${STORAGE_TYPE_MYSQL_DATABASE} |  | ||||||
| storage.type.mysql.port = ${STORAGE_TYPE_MYSQL_PORT} |  | ||||||
| storage.type.mysql.connectiontimeout = 60 |  | ||||||
|  |  | ||||||
|  |  | ||||||
| ######################################################################## |  | ||||||
| ######################################################################## |  | ||||||
| # |  | ||||||
| # Logging: please leave as is for now. |  | ||||||
| # |  | ||||||
| ######################################################################## |  | ||||||
| logging.formatters.f1.class = PatternFormatter |  | ||||||
| logging.formatters.f1.pattern = %Y-%m-%d %H:%M:%S %s: [%p] %t |  | ||||||
| logging.formatters.f1.times = UTC |  | ||||||
| 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 = $UCENTRALSEC_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 |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -1,22 +0,0 @@ | |||||||
| [Unit] |  | ||||||
| Description=OpenWiFi Security Service |  | ||||||
| After=network-online.target docker.service |  | ||||||
| Wants=network-online.target |  | ||||||
|  |  | ||||||
| [Service] |  | ||||||
| Type=simple |  | ||||||
| Environment="OWSEC_ROOT=/home/admin/dev/wlan-cloud-ucentralsec" |  | ||||||
| ExecStart=/home/admin/dev/wlan-cloud-ucentralsec/cmake-build/owsec |  | ||||||
| WorkingDirectory=/home/admin/dev/wlan-cloud-ucentralsec |  | ||||||
| # ExecReload=/bin/kill -s HUP $MAINPID |  | ||||||
| User=admin |  | ||||||
| # TimeoutSec=0 |  | ||||||
| RestartSec=2 |  | ||||||
| Restart=always |  | ||||||
| StartLimitBurst=3 |  | ||||||
| # KillMode=process |  | ||||||
| LimitNOFILE=500000 |  | ||||||
| LimitNPROC=500000 |  | ||||||
|  |  | ||||||
| [Install] |  | ||||||
| WantedBy=multi-user.target |  | ||||||
| @@ -1,4 +1,4 @@ | |||||||
| #!/bin/bash | #!/bin/bash | ||||||
|  |  | ||||||
| export OWSEC_CONFIG=`pwd` | export UCENTRALSEC_CONFIG=`pwd` | ||||||
| export OWSEC_ROOT=`pwd` | export UCENTRALSEC_ROOT=`pwd` | ||||||
|   | |||||||
| @@ -24,18 +24,18 @@ | |||||||
| #include "Daemon.h" | #include "Daemon.h" | ||||||
| #include "SubSystemServer.h" | #include "SubSystemServer.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|  |  | ||||||
| 	class ALBRequestHandler: public Poco::Net::HTTPRequestHandler | 	class ALBRequestHandler: public Poco::Net::HTTPRequestHandler | ||||||
| 			/// Return a HTML document with the current date and time. | 			/// Return a HTML document with the current date and time. | ||||||
| 		{ | 		{ | ||||||
| 		  public: | 		  public: | ||||||
| 			explicit ALBRequestHandler(Poco::Logger & L) | 			ALBRequestHandler(Poco::Logger & L) | ||||||
| 				: Logger_(L) | 				: Logger_(L) | ||||||
| 			{ | 			{ | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			void handleRequest(Poco::Net::HTTPServerRequest& Request, Poco::Net::HTTPServerResponse& Response) override | 			void handleRequest(Poco::Net::HTTPServerRequest& Request, Poco::Net::HTTPServerResponse& Response) | ||||||
| 			{ | 			{ | ||||||
| 				Logger_.information(Poco::format("ALB-REQUEST(%s): New ALB request.",Request.clientAddress().toString())); | 				Logger_.information(Poco::format("ALB-REQUEST(%s): New ALB request.",Request.clientAddress().toString())); | ||||||
| 				Response.setChunkedTransferEncoding(true); | 				Response.setChunkedTransferEncoding(true); | ||||||
| @@ -87,9 +87,9 @@ namespace OpenWifi { | |||||||
|                 return instance_; |                 return instance_; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             int Start() override { |             int Start() { | ||||||
|                 if(Daemon()->ConfigGetBool("alb.enable",false)) { |                 if(Daemon()->ConfigGetBool("alb.enable",false)) { | ||||||
|                     Port_ = (int)Daemon()->ConfigGetInt("alb.port",15015); |                     Port_ = (int)Daemon()->ConfigGetInt("alb.port",15017); | ||||||
|                     Socket_ = std::make_unique<Poco::Net::ServerSocket>(Port_); |                     Socket_ = std::make_unique<Poco::Net::ServerSocket>(Port_); | ||||||
|                     auto Params = new Poco::Net::HTTPServerParams; |                     auto Params = new Poco::Net::HTTPServerParams; | ||||||
|                     Server_ = std::make_unique<Poco::Net::HTTPServer>(new ALBRequestHandlerFactory(Logger_), *Socket_, Params); |                     Server_ = std::make_unique<Poco::Net::HTTPServer>(new ALBRequestHandlerFactory(Logger_), *Socket_, Params); | ||||||
| @@ -99,7 +99,7 @@ namespace OpenWifi { | |||||||
|                 return 0; |                 return 0; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             void Stop() override { |             void Stop() { | ||||||
|                 if(Server_) |                 if(Server_) | ||||||
|                     Server_->stop(); |                     Server_->stop(); | ||||||
|             } |             } | ||||||
|   | |||||||
| @@ -1,93 +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 <utility> |  | ||||||
|  |  | ||||||
| #include "AuthClient.h" |  | ||||||
| #include "RESTAPI_SecurityObjects.h" |  | ||||||
| #include "Daemon.h" |  | ||||||
| #include "OpenAPIRequest.h" |  | ||||||
|  |  | ||||||
| namespace OpenWifi { |  | ||||||
| 	class AuthClient * AuthClient::instance_ = nullptr; |  | ||||||
|  |  | ||||||
| 	int AuthClient::Start() { |  | ||||||
| 		return 0; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	void AuthClient::Stop() { |  | ||||||
|  |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	void AuthClient::RemovedCachedToken(const std::string &Token) { |  | ||||||
| 		std::lock_guard	G(Mutex_); |  | ||||||
| 		UserCache_.erase(Token); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	bool IsTokenExpired(const SecurityObjects::WebToken &T) { |  | ||||||
| 		return ((T.expires_in_+T.created_)<std::time(nullptr)); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	bool AuthClient::IsAuthorized(Poco::Net::HTTPServerRequest & Request, std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo ) { |  | ||||||
| 		std::lock_guard G(Mutex_); |  | ||||||
|  |  | ||||||
| 		auto User = UserCache_.find(SessionToken); |  | ||||||
| 		if(User != UserCache_.end() && !IsTokenExpired(User->second.webtoken)) { |  | ||||||
| 			UInfo = User->second; |  | ||||||
| 			return true; |  | ||||||
| 		} else { |  | ||||||
| 			Types::StringPairVec QueryData; |  | ||||||
| 			QueryData.push_back(std::make_pair("token",SessionToken)); |  | ||||||
| 			OpenAPIRequestGet	Req(    uSERVICE_SECURITY, |  | ||||||
| 								  	"/api/v1/validateToken", |  | ||||||
| 									 QueryData, |  | ||||||
| 								  5000); |  | ||||||
| 			Poco::JSON::Object::Ptr Response; |  | ||||||
| 			if(Req.Do(Response)==Poco::Net::HTTPResponse::HTTP_OK) { |  | ||||||
| 				if(Response->has("tokenInfo") && Response->has("userInfo")) { |  | ||||||
| 					SecurityObjects::UserInfoAndPolicy	P; |  | ||||||
| 					P.from_json(Response); |  | ||||||
| 					UserCache_[SessionToken] = P; |  | ||||||
| 					UInfo = P; |  | ||||||
| 				} |  | ||||||
| 				return true; |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 		} |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	bool AuthClient::IsTokenAuthorized(const std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo) { |  | ||||||
| 		std::lock_guard G(Mutex_); |  | ||||||
|  |  | ||||||
| 		auto User = UserCache_.find(SessionToken); |  | ||||||
| 		if(User != UserCache_.end() && !IsTokenExpired(User->second.webtoken)) { |  | ||||||
| 			UInfo = User->second; |  | ||||||
| 			return true; |  | ||||||
| 		} else { |  | ||||||
| 			Types::StringPairVec QueryData; |  | ||||||
| 			QueryData.push_back(std::make_pair("token",SessionToken)); |  | ||||||
| 			OpenAPIRequestGet	Req(uSERVICE_SECURITY, |  | ||||||
| 									 "/api/v1/validateToken", |  | ||||||
| 									 QueryData, |  | ||||||
| 									 5000); |  | ||||||
| 			Poco::JSON::Object::Ptr Response; |  | ||||||
| 			if(Req.Do(Response)==Poco::Net::HTTPResponse::HTTP_OK) { |  | ||||||
| 				if(Response->has("tokenInfo") && Response->has("userInfo")) { |  | ||||||
| 					SecurityObjects::UserInfoAndPolicy	P; |  | ||||||
| 					P.from_json(Response); |  | ||||||
| 					UserCache_[SessionToken] = P; |  | ||||||
| 					UInfo = P; |  | ||||||
| 				} |  | ||||||
| 				return true; |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 		} |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @@ -1,45 +0,0 @@ | |||||||
| // |  | ||||||
| // Created by stephane bourque on 2021-06-30. |  | ||||||
| // |  | ||||||
|  |  | ||||||
| #ifndef UCENTRALGW_AUTHCLIENT_H |  | ||||||
| #define UCENTRALGW_AUTHCLIENT_H |  | ||||||
|  |  | ||||||
| #include "Poco/JSON/Object.h" |  | ||||||
| #include "Poco/Net/HTTPServerRequest.h" |  | ||||||
| #include "Poco/Net/HTTPServerResponse.h" |  | ||||||
| #include "Poco/JWT/Signer.h" |  | ||||||
| #include "Poco/SHA2Engine.h" |  | ||||||
| #include "RESTAPI_SecurityObjects.h" |  | ||||||
| #include "SubSystemServer.h" |  | ||||||
|  |  | ||||||
| namespace OpenWifi { |  | ||||||
|  |  | ||||||
| class AuthClient : public SubSystemServer { |  | ||||||
| 	  public: |  | ||||||
| 		explicit AuthClient() noexcept: |  | ||||||
| 			SubSystemServer("Authentication", "AUTH-CLNT", "authentication") |  | ||||||
| 		{ |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		static AuthClient *instance() { |  | ||||||
| 			if (instance_ == nullptr) { |  | ||||||
| 				instance_ = new AuthClient; |  | ||||||
| 			} |  | ||||||
| 			return instance_; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		int Start() override; |  | ||||||
| 		void Stop() override; |  | ||||||
| 		bool IsAuthorized(Poco::Net::HTTPServerRequest & Request, std::string &SessionToken, OpenWifi::SecurityObjects::UserInfoAndPolicy & UInfo ); |  | ||||||
| 		void RemovedCachedToken(const std::string &Token); |  | ||||||
| 		bool IsTokenAuthorized(const std::string &Token, SecurityObjects::UserInfoAndPolicy & UInfo); |  | ||||||
| 	  private: |  | ||||||
| 		static AuthClient 					*instance_; |  | ||||||
| 		OpenWifi::SecurityObjects::UserInfoCache 		UserCache_; |  | ||||||
| 	}; |  | ||||||
|  |  | ||||||
| 	inline AuthClient * AuthClient() { return AuthClient::instance(); } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #endif // UCENTRALGW_AUTHCLIENT_H |  | ||||||
| @@ -22,7 +22,7 @@ | |||||||
|  |  | ||||||
| #include "SMTPMailerService.h" | #include "SMTPMailerService.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|     class AuthService *AuthService::instance_ = nullptr; |     class AuthService *AuthService::instance_ = nullptr; | ||||||
|  |  | ||||||
|     AuthService::ACCESS_TYPE AuthService::IntToAccessType(int C) { |     AuthService::ACCESS_TYPE AuthService::IntToAccessType(int C) { | ||||||
| @@ -67,7 +67,7 @@ namespace OpenWifi { | |||||||
|         if(!Secure_) |         if(!Secure_) | ||||||
|             return true; |             return true; | ||||||
|  |  | ||||||
|         std::lock_guard		Guard(Mutex_); | 		SubMutexGuard		Guard(Mutex_); | ||||||
|  |  | ||||||
| 		std::string CallToken; | 		std::string CallToken; | ||||||
|  |  | ||||||
| @@ -80,48 +80,33 @@ namespace OpenWifi { | |||||||
| 		} catch(const Poco::Exception &E) { | 		} catch(const Poco::Exception &E) { | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if(!CallToken.empty()) { | 		if(CallToken.empty()) | ||||||
| 		    if(Storage()->IsTokenRevoked(CallToken)) | 			CallToken = Request.get("X-API-KEY ", ""); | ||||||
| 		        return false; |  | ||||||
| 		    auto Client = UserCache_.find(CallToken); |  | ||||||
| 		    if( Client == UserCache_.end() ) |  | ||||||
| 		        return ValidateToken(CallToken, CallToken, UInfo); |  | ||||||
|  |  | ||||||
| 		    if((Client->second.webtoken.created_ + Client->second.webtoken.expires_in_) > time(nullptr)) { | 		if(CallToken.empty()) | ||||||
| 		        SessionToken = CallToken; | 			return false; | ||||||
| 		        UInfo = Client->second ; |  | ||||||
| 		        return true; | 		auto Client = UserCache_.find(CallToken); | ||||||
| 		    } |  | ||||||
| 		    UserCache_.erase(CallToken); | 		if( Client == UserCache_.end() ) | ||||||
| 		    Storage()->RevokeToken(CallToken); | 			return ValidateToken(CallToken, CallToken, UInfo); | ||||||
| 		    return false; |  | ||||||
|  | 		if((Client->second.webtoken.created_ + Client->second.webtoken.expires_in_) > time(nullptr)) { | ||||||
|  | 			SessionToken = CallToken; | ||||||
|  |             UInfo = Client->second ; | ||||||
|  | 			return true; | ||||||
| 		} | 		} | ||||||
|  | 		UserCache_.erase(CallToken); | ||||||
| 		return false; | 		return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool AuthService::DeleteUserFromCache(const std::string &UserName) { |  | ||||||
|         std::lock_guard		Guard(Mutex_); |  | ||||||
|  |  | ||||||
|         for(auto i=UserCache_.begin();i!=UserCache_.end();) { |  | ||||||
|             if (i->second.userinfo.email==UserName) { |  | ||||||
|                 Logout(i->first); |  | ||||||
|                 i = UserCache_.erase(i); |  | ||||||
|             } else { |  | ||||||
|                 ++i; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         return true; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     bool AuthService::ValidatePassword(const std::string &Password) { |     bool AuthService::ValidatePassword(const std::string &Password) { | ||||||
|         return std::regex_match(Password, PasswordValidation_); |         return std::regex_match(Password, PasswordValidation_); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void AuthService::Logout(const std::string &token) { |     void AuthService::Logout(const std::string &token) { | ||||||
| 		std::lock_guard		Guard(Mutex_); | 		SubMutexGuard		Guard(Mutex_); | ||||||
|  |         UserCache_.erase(token); | ||||||
| 		UserCache_.erase(token); |  | ||||||
|  |  | ||||||
|         try { |         try { | ||||||
|             Poco::JSON::Object Obj; |             Poco::JSON::Object Obj; | ||||||
| @@ -130,8 +115,6 @@ namespace OpenWifi { | |||||||
|             Obj.set("token", token); |             Obj.set("token", token); | ||||||
|             std::stringstream ResultText; |             std::stringstream ResultText; | ||||||
|             Poco::JSON::Stringifier::stringify(Obj, ResultText); |             Poco::JSON::Stringifier::stringify(Obj, ResultText); | ||||||
|             std::string Tmp{token}; |  | ||||||
|             Storage()->RevokeToken(Tmp); |  | ||||||
|             KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS, Daemon()->PrivateEndPoint(), ResultText.str(), |             KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS, Daemon()->PrivateEndPoint(), ResultText.str(), | ||||||
|                                         false); |                                         false); | ||||||
|         } catch (const Poco::Exception &E) { |         } catch (const Poco::Exception &E) { | ||||||
| @@ -140,7 +123,7 @@ namespace OpenWifi { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     std::string AuthService::GenerateToken(const std::string & Identity, ACCESS_TYPE Type) { |     std::string AuthService::GenerateToken(const std::string & Identity, ACCESS_TYPE Type) { | ||||||
|         std::lock_guard		Guard(Mutex_); | 		SubMutexGuard		Guard(Mutex_); | ||||||
|  |  | ||||||
| 		Poco::JWT::Token	T; | 		Poco::JWT::Token	T; | ||||||
|  |  | ||||||
| @@ -160,22 +143,37 @@ namespace OpenWifi { | |||||||
|     } |     } | ||||||
|  |  | ||||||
| 	bool AuthService::ValidateToken(const std::string & Token, std::string & SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo  ) { | 	bool AuthService::ValidateToken(const std::string & Token, std::string & SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo  ) { | ||||||
|         std::lock_guard		Guard(Mutex_); | 		SubMutexGuard		Guard(Mutex_); | ||||||
| 		Poco::JWT::Token	DecryptedToken; | 		Poco::JWT::Token	DecryptedToken; | ||||||
|  |  | ||||||
| 		try { | 		try { | ||||||
|             auto E = UserCache_.find(SessionToken); |             auto E = UserCache_.find(SessionToken); | ||||||
|             if(E == UserCache_.end()) { |             if(E == UserCache_.end()) { | ||||||
|                 if(Storage()->GetToken(SessionToken,UInfo)) { |                 if (Signer_.tryVerify(Token, DecryptedToken)) { | ||||||
|                     if(Storage()->GetUserById(UInfo.userinfo.email,UInfo.userinfo)) { |                     auto Expires = DecryptedToken.getExpiration(); | ||||||
|                         UserCache_[UInfo.webtoken.access_token_] = UInfo; |                     if (Expires > Poco::Timestamp()) { | ||||||
|                         return true; |                         auto Identity = DecryptedToken.payload().get("identity").toString(); | ||||||
|  |                         if(Storage()->GetUserById(Identity,UInfo.userinfo)) { | ||||||
|  |                             auto IssuedAt = DecryptedToken.getIssuedAt(); | ||||||
|  |                             auto Subject = DecryptedToken.getSubject(); | ||||||
|  |                             UInfo.webtoken.access_token_ = Token; | ||||||
|  |                             UInfo.webtoken.refresh_token_ = Token; | ||||||
|  |                             UInfo.webtoken.username_ = Identity; | ||||||
|  |                             UInfo.webtoken.id_token_ = Token; | ||||||
|  |                             UInfo.webtoken.token_type_ = "Bearer"; | ||||||
|  |                             UInfo.webtoken.created_ = IssuedAt.epochTime(); | ||||||
|  |                             UInfo.webtoken.expires_in_ = Expires.epochTime() - IssuedAt.epochTime(); | ||||||
|  |                             UInfo.webtoken.idle_timeout_ = 5 * 60; | ||||||
|  |                             UserCache_[UInfo.webtoken.access_token_] = UInfo; | ||||||
|  |                             return true; | ||||||
|  |                         } | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } else { |             } else { | ||||||
|                 UInfo = E->second; |                 UInfo = E->second; | ||||||
|                 return true; |                 return true; | ||||||
|             } |             } | ||||||
|  |  | ||||||
| 		} catch (const Poco::Exception &E ) { | 		} catch (const Poco::Exception &E ) { | ||||||
| 			Logger_.log(E); | 			Logger_.log(E); | ||||||
| 		} | 		} | ||||||
| @@ -184,26 +182,24 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
|     void AuthService::CreateToken(const std::string & UserName, SecurityObjects::UserInfoAndPolicy &UInfo) |     void AuthService::CreateToken(const std::string & UserName, SecurityObjects::UserInfoAndPolicy &UInfo) | ||||||
|     { |     { | ||||||
|         std::lock_guard		Guard(Mutex_); | 		SubMutexGuard		Guard(Mutex_); | ||||||
|  |  | ||||||
|  | 		std::string Token = GenerateToken(UInfo.userinfo.Id,USERNAME); | ||||||
|         SecurityObjects::AclTemplate	ACL; |         SecurityObjects::AclTemplate	ACL; | ||||||
|         ACL.PortalLogin_ = ACL.Read_ = ACL.ReadWrite_ = ACL.ReadWriteCreate_ = ACL.Delete_ = true; |         ACL.PortalLogin_ = ACL.Read_ = ACL.ReadWrite_ = ACL.ReadWriteCreate_ = ACL.Delete_ = true; | ||||||
|         UInfo.webtoken.acl_template_ = ACL; |         UInfo.webtoken.acl_template_ = ACL; | ||||||
|         UInfo.webtoken.expires_in_ = TokenAging_ ; |         UInfo.webtoken.expires_in_ = TokenAging_ ; | ||||||
|         UInfo.webtoken.idle_timeout_ = 5 * 60; |         UInfo.webtoken.idle_timeout_ = 5 * 60; | ||||||
|         UInfo.webtoken.token_type_ = "Bearer"; |         UInfo.webtoken.token_type_ = "Bearer"; | ||||||
|         UInfo.webtoken.access_token_ = GenerateToken(UInfo.userinfo.Id,USERNAME); |         UInfo.webtoken.access_token_ = Token; | ||||||
|         UInfo.webtoken.id_token_ = GenerateToken(UInfo.userinfo.Id,USERNAME); |         UInfo.webtoken.id_token_ = Token; | ||||||
|         UInfo.webtoken.refresh_token_ = GenerateToken(UInfo.userinfo.Id,CUSTOM); |         UInfo.webtoken.refresh_token_ = Token; | ||||||
|         UInfo.webtoken.created_ = time(nullptr); |         UInfo.webtoken.created_ = time(nullptr); | ||||||
|         UInfo.webtoken.username_ = UserName; |         UInfo.webtoken.username_ = UserName; | ||||||
|         UInfo.webtoken.errorCode = 0; |         UInfo.webtoken.errorCode = 0; | ||||||
|         UInfo.webtoken.userMustChangePassword = false; |         UInfo.webtoken.userMustChangePassword = false; | ||||||
|         UserCache_[UInfo.webtoken.access_token_] = UInfo; |         UserCache_[Token] = UInfo; | ||||||
|         Storage()->SetLastLogin(UInfo.userinfo.Id); |         Storage()->SetLastLogin(UInfo.userinfo.Id); | ||||||
|         Storage()->AddToken(UInfo.webtoken.username_, UInfo.webtoken.access_token_, |  | ||||||
|                             UInfo.webtoken.refresh_token_, UInfo.webtoken.token_type_, |  | ||||||
|                                 UInfo.webtoken.expires_in_, UInfo.webtoken.idle_timeout_); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool AuthService::SetPassword(const std::string &NewPassword, SecurityObjects::UserInfo & UInfo) { |     bool AuthService::SetPassword(const std::string &NewPassword, SecurityObjects::UserInfo & UInfo) { | ||||||
| @@ -224,7 +220,7 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
|     AuthService::AUTH_ERROR AuthService::Authorize( std::string & UserName, const std::string & Password, const std::string & NewPassword, SecurityObjects::UserInfoAndPolicy & UInfo ) |     AuthService::AUTH_ERROR AuthService::Authorize( std::string & UserName, const std::string & Password, const std::string & NewPassword, SecurityObjects::UserInfoAndPolicy & UInfo ) | ||||||
|     { |     { | ||||||
|         std::lock_guard		Guard(Mutex_); | 		SubMutexGuard					Guard(Mutex_); | ||||||
|         SecurityObjects::AclTemplate	ACL; |         SecurityObjects::AclTemplate	ACL; | ||||||
|  |  | ||||||
|         Poco::toLowerInPlace(UserName); |         Poco::toLowerInPlace(UserName); | ||||||
| @@ -281,7 +277,7 @@ namespace OpenWifi { | |||||||
|     std::string AuthService::ComputePasswordHash(const std::string &UserName, const std::string &Password) { |     std::string AuthService::ComputePasswordHash(const std::string &UserName, const std::string &Password) { | ||||||
|         std::string UName = Poco::trim(Poco::toLower(UserName)); |         std::string UName = Poco::trim(Poco::toLower(UserName)); | ||||||
|         SHA2_.update(Password + UName); |         SHA2_.update(Password + UName); | ||||||
|         return Utils::ToHex(SHA2_.digest()); |         return uCentral::Utils::ToHex(SHA2_.digest()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool AuthService::SendEmailToUser(std::string &Email, EMAIL_REASON Reason) { |     bool AuthService::SendEmailToUser(std::string &Email, EMAIL_REASON Reason) { | ||||||
| @@ -335,13 +331,6 @@ namespace OpenWifi { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool AuthService::IsValidToken(const std::string &Token, SecurityObjects::WebToken &WebToken, SecurityObjects::UserInfo &UserInfo) { |     bool AuthService::IsValidToken(const std::string &Token, SecurityObjects::WebToken &WebToken, SecurityObjects::UserInfo &UserInfo) { | ||||||
|         std::lock_guard G(Mutex_); |  | ||||||
|         auto It = UserCache_.find(Token); |  | ||||||
|  |  | ||||||
|         if(It==UserCache_.end()) |  | ||||||
|             return false; |  | ||||||
|         WebToken = It->second.webtoken; |  | ||||||
|         UserInfo = It->second.userinfo; |  | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -21,7 +21,7 @@ | |||||||
|  |  | ||||||
| #include "RESTAPI_SecurityObjects.h" | #include "RESTAPI_SecurityObjects.h" | ||||||
|  |  | ||||||
| namespace OpenWifi{ | namespace uCentral{ | ||||||
|  |  | ||||||
|     static const std::string AUTHENTICATION_SYSTEM{"SYSTEM"}; |     static const std::string AUTHENTICATION_SYSTEM{"SYSTEM"}; | ||||||
|  |  | ||||||
| @@ -82,7 +82,6 @@ namespace OpenWifi{ | |||||||
|  |  | ||||||
|         [[nodiscard]] static bool VerifyEmail(SecurityObjects::UserInfo &UInfo); |         [[nodiscard]] static bool VerifyEmail(SecurityObjects::UserInfo &UInfo); | ||||||
|         [[nodiscard]] static bool SendEmailToUser(std::string &Email, EMAIL_REASON Reason); |         [[nodiscard]] static bool SendEmailToUser(std::string &Email, EMAIL_REASON Reason); | ||||||
|         [[nodiscard]] bool DeleteUserFromCache(const std::string &UserName); |  | ||||||
|  |  | ||||||
|     private: |     private: | ||||||
| 		static AuthService *instance_; | 		static AuthService *instance_; | ||||||
|   | |||||||
| @@ -27,7 +27,7 @@ | |||||||
| #include "RESTAPI_InternalServer.h" | #include "RESTAPI_InternalServer.h" | ||||||
| #include "AuthService.h" | #include "AuthService.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|     class Daemon *Daemon::instance_ = nullptr; |     class Daemon *Daemon::instance_ = nullptr; | ||||||
|  |  | ||||||
|     class Daemon *Daemon::instance() { |     class Daemon *Daemon::instance() { | ||||||
| @@ -55,7 +55,7 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
| int main(int argc, char **argv) { | int main(int argc, char **argv) { | ||||||
|     try { |     try { | ||||||
|         auto App = OpenWifi::Daemon::instance(); |         auto App = uCentral::Daemon::instance(); | ||||||
|         auto ExitCode =  App->run(argc, argv); |         auto ExitCode =  App->run(argc, argv); | ||||||
|         delete App; |         delete App; | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										24
									
								
								src/Daemon.h
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								src/Daemon.h
									
									
									
									
									
								
							| @@ -21,28 +21,28 @@ | |||||||
| #include "Poco/Crypto/Cipher.h" | #include "Poco/Crypto/Cipher.h" | ||||||
|  |  | ||||||
|  |  | ||||||
| #include "OpenWifiTypes.h" | #include "uCentralTypes.h" | ||||||
| #include "MicroService.h" | #include "MicroService.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|  |  | ||||||
|     static const char * vDAEMON_PROPERTIES_FILENAME = "owsec.properties"; |     static const char * vDAEMON_PROPERTIES_FILENAME = "ucentralsec.properties"; | ||||||
|     static const char * vDAEMON_ROOT_ENV_VAR = "OWSEC_ROOT"; |     static const char * vDAEMON_ROOT_ENV_VAR = "UCENTRALSEC_ROOT"; | ||||||
|     static const char * vDAEMON_CONFIG_ENV_VAR = "OWSEC_CONFIG"; |     static const char * vDAEMON_CONFIG_ENV_VAR = "UCENTRALSEC_CONFIG"; | ||||||
|     static const char * vDAEMON_APP_NAME = uSERVICE_SECURITY.c_str(); |     static const char * vDAEMON_APP_NAME = "uCentralSec"; | ||||||
|     static const uint64_t vDAEMON_BUS_TIMER = 5000; |     static const uint64_t vDAEMON_BUS_TIMER = 5000; | ||||||
|  |  | ||||||
|     class Daemon : public MicroService { |     class Daemon : public MicroService { | ||||||
|     public: |     public: | ||||||
|         explicit Daemon(const std::string & PropFile, |         explicit Daemon(std::string PropFile, | ||||||
|                         const std::string & RootEnv, |                         std::string RootEnv, | ||||||
|                         const std::string & ConfigEnv, |                         std::string ConfigEnv, | ||||||
|                         const std::string & AppName, |                         std::string AppName, | ||||||
|                         uint64_t BusTimer, |                         uint64_t BusTimer, | ||||||
|                         const Types::SubSystemVec & SubSystems) : |                         Types::SubSystemVec SubSystems) : | ||||||
|                 MicroService( PropFile, RootEnv, ConfigEnv, AppName, BusTimer, SubSystems) {}; |                 MicroService( PropFile, RootEnv, ConfigEnv, AppName, BusTimer, SubSystems) {}; | ||||||
|  |  | ||||||
|         void initialize(Poco::Util::Application &self) override; |         void initialize(Poco::Util::Application &self); | ||||||
|         static Daemon *instance(); |         static Daemon *instance(); | ||||||
|     private: |     private: | ||||||
|         static Daemon 				*instance_; |         static Daemon 				*instance_; | ||||||
|   | |||||||
| @@ -12,18 +12,18 @@ | |||||||
| #include "Daemon.h" | #include "Daemon.h" | ||||||
| #include "Utils.h" | #include "Utils.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|  |  | ||||||
| 	class KafkaManager *KafkaManager::instance_ = nullptr; | 	class KafkaManager *KafkaManager::instance_ = nullptr; | ||||||
|  |  | ||||||
| 	KafkaManager::KafkaManager() noexcept: | 	KafkaManager::KafkaManager() noexcept: | ||||||
| 		SubSystemServer("KafkaManager", "KAFKA-SVR", "openwifi.kafka") | 		SubSystemServer("KafkaManager", "KAFKA-SVR", "ucentral.kafka") | ||||||
| 	{ | 	{ | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	void KafkaManager::initialize(Poco::Util::Application & self) { | 	void KafkaManager::initialize(Poco::Util::Application & self) { | ||||||
| 		SubSystemServer::initialize(self); | 		SubSystemServer::initialize(self); | ||||||
| 		KafkaEnabled_ = Daemon()->ConfigGetBool("openwifi.kafka.enable",false); | 		KafkaEnabled_ = Daemon()->ConfigGetBool("ucentral.kafka.enable",false); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| #ifdef SMALL_BUILD | #ifdef SMALL_BUILD | ||||||
| @@ -55,8 +55,8 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
| 	void KafkaManager::ProducerThr() { | 	void KafkaManager::ProducerThr() { | ||||||
| 		cppkafka::Configuration Config({ | 		cppkafka::Configuration Config({ | ||||||
| 										   { "client.id", Daemon()->ConfigGetString("openwifi.kafka.client.id") }, | 										   { "client.id", Daemon()->ConfigGetString("ucentral.kafka.client.id") }, | ||||||
| 										   { "metadata.broker.list", Daemon()->ConfigGetString("openwifi.kafka.brokerlist") } | 										   { "metadata.broker.list", Daemon()->ConfigGetString("ucentral.kafka.brokerlist") } | ||||||
| 									   }); | 									   }); | ||||||
| 		SystemInfoWrapper_ = 	R"lit({ "system" : { "id" : )lit" + | 		SystemInfoWrapper_ = 	R"lit({ "system" : { "id" : )lit" + | ||||||
| 								  	std::to_string(Daemon()->ID()) + | 								  	std::to_string(Daemon()->ID()) + | ||||||
| @@ -68,7 +68,7 @@ namespace OpenWifi { | |||||||
| 			std::this_thread::sleep_for(std::chrono::milliseconds(200)); | 			std::this_thread::sleep_for(std::chrono::milliseconds(200)); | ||||||
| 			try | 			try | ||||||
| 			{ | 			{ | ||||||
| 				std::lock_guard G(ProducerMutex_); | 				SubMutexGuard G(ProducerMutex_); | ||||||
| 				auto Num=0; | 				auto Num=0; | ||||||
| 				while (!Queue_.empty()) { | 				while (!Queue_.empty()) { | ||||||
| 					const auto M = Queue_.front(); | 					const auto M = Queue_.front(); | ||||||
| @@ -96,10 +96,10 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
| 	void KafkaManager::ConsumerThr() { | 	void KafkaManager::ConsumerThr() { | ||||||
| 		cppkafka::Configuration Config({ | 		cppkafka::Configuration Config({ | ||||||
| 										   { "client.id", Daemon()->ConfigGetString("openwifi.kafka.client.id") }, | 										   { "client.id", Daemon()->ConfigGetString("ucentral.kafka.client.id") }, | ||||||
| 										   { "metadata.broker.list", Daemon()->ConfigGetString("openwifi.kafka.brokerlist") }, | 										   { "metadata.broker.list", Daemon()->ConfigGetString("ucentral.kafka.brokerlist") }, | ||||||
| 										   { "group.id", Daemon()->ConfigGetString("openwifi.kafka.group.id") }, | 										   { "group.id", Daemon()->ConfigGetString("ucentral.kafka.group.id") }, | ||||||
| 										   { "enable.auto.commit", Daemon()->ConfigGetBool("openwifi.kafka.auto.commit",false) }, | 										   { "enable.auto.commit", Daemon()->ConfigGetBool("ucentral.kafka.auto.commit",false) }, | ||||||
| 										   { "auto.offset.reset", "latest" } , | 										   { "auto.offset.reset", "latest" } , | ||||||
| 										   { "enable.partition.eof", false } | 										   { "enable.partition.eof", false } | ||||||
| 									   }); | 									   }); | ||||||
| @@ -125,8 +125,8 @@ namespace OpenWifi { | |||||||
| 			} | 			} | ||||||
| 		}); | 		}); | ||||||
|  |  | ||||||
|         bool AutoCommit = Daemon()->ConfigGetBool("openwifi.kafka.auto.commit",false); |         bool AutoCommit = Daemon()->ConfigGetBool("ucentral.kafka.auto.commit",false); | ||||||
|         auto BatchSize = Daemon()->ConfigGetInt("openwifi.kafka.consumer.batchsize",20); |         auto BatchSize = Daemon()->ConfigGetInt("ucentral.kafka.consumer.batchsize",20); | ||||||
|  |  | ||||||
|         Types::StringVec    Topics; |         Types::StringVec    Topics; | ||||||
| 		for(const auto &i:Notifiers_) | 		for(const auto &i:Notifiers_) | ||||||
| @@ -148,7 +148,7 @@ namespace OpenWifi { | |||||||
|                             Consumer.async_commit(Msg); |                             Consumer.async_commit(Msg); | ||||||
|                         continue; |                         continue; | ||||||
|                     } |                     } | ||||||
|                     std::lock_guard G(ConsumerMutex_); |                     SubMutexGuard G(ConsumerMutex_); | ||||||
|                     auto It = Notifiers_.find(Msg.get_topic()); |                     auto It = Notifiers_.find(Msg.get_topic()); | ||||||
|                     if (It != Notifiers_.end()) { |                     if (It != Notifiers_.end()) { | ||||||
|                         Types::TopicNotifyFunctionList &FL = It->second; |                         Types::TopicNotifyFunctionList &FL = It->second; | ||||||
| @@ -174,9 +174,9 @@ namespace OpenWifi { | |||||||
| 		return std::move( SystemInfoWrapper_ + PayLoad + "}"); | 		return std::move( SystemInfoWrapper_ + PayLoad + "}"); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	void KafkaManager::PostMessage(const std::string &topic, const std::string & key, const std::string &PayLoad, bool WrapMessage ) { | 	void KafkaManager::PostMessage(std::string topic, std::string key, std::string PayLoad, bool WrapMessage ) { | ||||||
| 		if(KafkaEnabled_) { | 		if(KafkaEnabled_) { | ||||||
| 			std::lock_guard G(Mutex_); | 			SubMutexGuard G(Mutex_); | ||||||
| 			KMessage M{ | 			KMessage M{ | ||||||
| 				.Topic = topic, | 				.Topic = topic, | ||||||
| 				.Key = key, | 				.Key = key, | ||||||
| @@ -187,7 +187,7 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
| 	int KafkaManager::RegisterTopicWatcher(const std::string &Topic, Types::TopicNotifyFunction &F) { | 	int KafkaManager::RegisterTopicWatcher(const std::string &Topic, Types::TopicNotifyFunction &F) { | ||||||
| 		if(KafkaEnabled_) { | 		if(KafkaEnabled_) { | ||||||
| 			std::lock_guard G(Mutex_); | 			SubMutexGuard G(Mutex_); | ||||||
| 			auto It = Notifiers_.find(Topic); | 			auto It = Notifiers_.find(Topic); | ||||||
| 			if(It == Notifiers_.end()) { | 			if(It == Notifiers_.end()) { | ||||||
| 				Types::TopicNotifyFunctionList L; | 				Types::TopicNotifyFunctionList L; | ||||||
| @@ -204,7 +204,7 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
| 	void KafkaManager::UnregisterTopicWatcher(const std::string &Topic, int Id) { | 	void KafkaManager::UnregisterTopicWatcher(const std::string &Topic, int Id) { | ||||||
| 		if(KafkaEnabled_) { | 		if(KafkaEnabled_) { | ||||||
| 			std::lock_guard G(Mutex_); | 			SubMutexGuard G(Mutex_); | ||||||
| 			auto It = Notifiers_.find(Topic); | 			auto It = Notifiers_.find(Topic); | ||||||
| 			if(It != Notifiers_.end()) { | 			if(It != Notifiers_.end()) { | ||||||
| 				Types::TopicNotifyFunctionList & L = It->second; | 				Types::TopicNotifyFunctionList & L = It->second; | ||||||
|   | |||||||
| @@ -13,11 +13,11 @@ | |||||||
| #include <thread> | #include <thread> | ||||||
|  |  | ||||||
| #include "SubSystemServer.h" | #include "SubSystemServer.h" | ||||||
| #include "OpenWifiTypes.h" | #include "uCentralTypes.h" | ||||||
|  |  | ||||||
| #include "cppkafka/cppkafka.h" | #include "cppkafka/cppkafka.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|  |  | ||||||
| 	class KafkaManager : public SubSystemServer { | 	class KafkaManager : public SubSystemServer { | ||||||
| 	  public: | 	  public: | ||||||
| @@ -41,7 +41,7 @@ namespace OpenWifi { | |||||||
| 		int Start() override; | 		int Start() override; | ||||||
| 		void Stop() override; | 		void Stop() override; | ||||||
|  |  | ||||||
| 		void PostMessage(const std::string &topic, const std::string & key, const std::string &payload, bool WrapMessage = true); | 		void PostMessage(std::string topic, std::string key, std::string payload, bool WrapMessage = true); | ||||||
| 		[[nodiscard]] std::string WrapSystemId(const std::string & PayLoad); | 		[[nodiscard]] std::string WrapSystemId(const std::string & PayLoad); | ||||||
| 		[[nodiscard]] bool Enabled() { return KafkaEnabled_; } | 		[[nodiscard]] bool Enabled() { return KafkaEnabled_; } | ||||||
| 		int RegisterTopicWatcher(const std::string &Topic, Types::TopicNotifyFunction & F); | 		int RegisterTopicWatcher(const std::string &Topic, Types::TopicNotifyFunction & F); | ||||||
| @@ -52,8 +52,8 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
| 	  private: | 	  private: | ||||||
| 		static KafkaManager 			*instance_; | 		static KafkaManager 			*instance_; | ||||||
| 		std::mutex 						ProducerMutex_; | 		SubMutex 						ProducerMutex_; | ||||||
| 		std::mutex						ConsumerMutex_; | 		SubMutex 						ConsumerMutex_; | ||||||
| 		bool 							KafkaEnabled_ = false; | 		bool 							KafkaEnabled_ = false; | ||||||
| 		std::atomic_bool 				ProducerRunning_ = false; | 		std::atomic_bool 				ProducerRunning_ = false; | ||||||
| 		std::atomic_bool 				ConsumerRunning_ = false; | 		std::atomic_bool 				ConsumerRunning_ = false; | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
| #ifndef UCENTRALGW_KAFKA_TOPICS_H | #ifndef UCENTRALGW_KAFKA_TOPICS_H | ||||||
| #define UCENTRALGW_KAFKA_TOPICS_H | #define UCENTRALGW_KAFKA_TOPICS_H | ||||||
|  |  | ||||||
| namespace OpenWifi::KafkaTopics { | namespace uCentral::KafkaTopics { | ||||||
| 	static const std::string HEALTHCHECK{"healthcheck"}; | 	static const std::string HEALTHCHECK{"healthcheck"}; | ||||||
| 	static const std::string STATE{"state"}; | 	static const std::string STATE{"state"}; | ||||||
| 	static const std::string CONNECTION{"connection"}; | 	static const std::string CONNECTION{"connection"}; | ||||||
| @@ -13,7 +13,6 @@ namespace OpenWifi::KafkaTopics { | |||||||
| 	static const std::string ALERTS{"alerts"}; | 	static const std::string ALERTS{"alerts"}; | ||||||
| 	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"}; |  | ||||||
|  |  | ||||||
| 	namespace ServiceEvents { | 	namespace ServiceEvents { | ||||||
| 		static const std::string EVENT_JOIN{"join"}; | 		static const std::string EVENT_JOIN{"join"}; | ||||||
|   | |||||||
| @@ -1,11 +1,6 @@ | |||||||
| // | // | ||||||
| //	License type: BSD 3-Clause License | // Created by stephane bourque on 2021-06-22. | ||||||
| //	License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE |  | ||||||
| // | // | ||||||
| //	Created by Stephane Bourque on 2021-03-04. |  | ||||||
| //	Arilia Wireless Inc. |  | ||||||
| // |  | ||||||
|  |  | ||||||
| #include <cstdlib> | #include <cstdlib> | ||||||
| #include <boost/algorithm/string.hpp> | #include <boost/algorithm/string.hpp> | ||||||
|  |  | ||||||
| @@ -39,7 +34,7 @@ | |||||||
| #include "AuthClient.h" | #include "AuthClient.h" | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|  |  | ||||||
| 	void MyErrorHandler::exception(const Poco::Exception & E) { | 	void MyErrorHandler::exception(const Poco::Exception & E) { | ||||||
| 		Poco::Thread * CurrentThread = Poco::Thread::current(); | 		Poco::Thread * CurrentThread = Poco::Thread::current(); | ||||||
| @@ -62,7 +57,7 @@ namespace OpenWifi { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	void MicroService::BusMessageReceived(const std::string &Key, const std::string & Message) { | 	void MicroService::BusMessageReceived(const std::string &Key, const std::string & Message) { | ||||||
| 		std::lock_guard G(InfraMutex_); | 		SubMutexGuard G(InfraMutex_); | ||||||
| 		try { | 		try { | ||||||
| 			Poco::JSON::Parser P; | 			Poco::JSON::Parser P; | ||||||
| 			auto Object = P.parse(Message).extract<Poco::JSON::Object::Ptr>(); | 			auto Object = P.parse(Message).extract<Poco::JSON::Object::Ptr>(); | ||||||
| @@ -117,23 +112,13 @@ namespace OpenWifi { | |||||||
| 			} else { | 			} else { | ||||||
| 				logger().error("Bad bus message."); | 				logger().error("Bad bus message."); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			auto i=Services_.begin(); |  | ||||||
| 			auto Now = (uint64_t )std::time(nullptr); |  | ||||||
| 			for(;i!=Services_.end();) { |  | ||||||
| 			    if((Now - i->second.LastUpdate)>60) { |  | ||||||
| 			        i = Services_.erase(i); |  | ||||||
| 			    } else |  | ||||||
| 			        ++i; |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 		} catch (const Poco::Exception &E) { | 		} catch (const Poco::Exception &E) { | ||||||
| 			logger().log(E); | 			logger().log(E); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	MicroServiceMetaVec MicroService::GetServices(const std::string & Type) { | 	MicroServiceMetaVec MicroService::GetServices(const std::string & Type) { | ||||||
| 		std::lock_guard G(InfraMutex_); | 		SubMutexGuard G(InfraMutex_); | ||||||
|  |  | ||||||
| 		auto T = Poco::toLower(Type); | 		auto T = Poco::toLower(Type); | ||||||
| 		MicroServiceMetaVec	Res; | 		MicroServiceMetaVec	Res; | ||||||
| @@ -145,7 +130,7 @@ namespace OpenWifi { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	MicroServiceMetaVec MicroService::GetServices() { | 	MicroServiceMetaVec MicroService::GetServices() { | ||||||
| 		std::lock_guard G(InfraMutex_); | 		SubMutexGuard G(InfraMutex_); | ||||||
|  |  | ||||||
| 		MicroServiceMetaVec	Res; | 		MicroServiceMetaVec	Res; | ||||||
| 		for(const auto &[Id,ServiceRec]:Services_) { | 		for(const auto &[Id,ServiceRec]:Services_) { | ||||||
| @@ -154,42 +139,6 @@ namespace OpenWifi { | |||||||
| 		return Res; | 		return Res; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|     void MicroService::LoadConfigurationFile() { |  | ||||||
| 	    std::string Location = Poco::Environment::get(DAEMON_CONFIG_ENV_VAR,"."); |  | ||||||
| 	    Poco::Path ConfigFile; |  | ||||||
|  |  | ||||||
| 	    ConfigFile = ConfigFileName_.empty() ? Location + "/" + DAEMON_PROPERTIES_FILENAME : ConfigFileName_; |  | ||||||
|  |  | ||||||
| 	    if(!ConfigFile.isFile()) |  | ||||||
| 	    { |  | ||||||
| 	        std::cerr << DAEMON_APP_NAME << ": Configuration " |  | ||||||
| 	        << ConfigFile.toString() << " does not seem to exist. Please set " + DAEMON_CONFIG_ENV_VAR |  | ||||||
| 	        + " env variable the path of the " + DAEMON_PROPERTIES_FILENAME + " file." << std::endl; |  | ||||||
| 	        std::exit(Poco::Util::Application::EXIT_CONFIG); |  | ||||||
| 	    } |  | ||||||
|  |  | ||||||
| 	    loadConfiguration(ConfigFile.toString()); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
|     void MicroService::Reload() { |  | ||||||
| 	    LoadConfigurationFile(); |  | ||||||
| 	    LoadMyConfig(); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
|     void MicroService::LoadMyConfig() { |  | ||||||
| 	    std::string KeyFile = ConfigPath("openwifi.service.key"); |  | ||||||
| 	    std::string KeyFilePassword = ConfigPath("openwifi.service.key.password" , "" ); |  | ||||||
| 	    AppKey_ = Poco::SharedPtr<Poco::Crypto::RSAKey>(new Poco::Crypto::RSAKey("", KeyFile, KeyFilePassword)); |  | ||||||
| 	    Cipher_ = CipherFactory_.createCipher(*AppKey_); |  | ||||||
| 	    ID_ = Utils::GetSystemId(); |  | ||||||
| 	    if(!DebugMode_) |  | ||||||
| 	        DebugMode_ = ConfigGetBool("openwifi.system.debug",false); |  | ||||||
| 	    MyPrivateEndPoint_ = ConfigGetString("openwifi.system.uri.private"); |  | ||||||
| 	    MyPublicEndPoint_ = ConfigGetString("openwifi.system.uri.public"); |  | ||||||
| 	    UIURI_ = ConfigGetString("openwifi.system.uri.ui"); |  | ||||||
| 	    MyHash_ = CreateHash(MyPublicEndPoint_); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	void MicroService::initialize(Poco::Util::Application &self) { | 	void MicroService::initialize(Poco::Util::Application &self) { | ||||||
| 		// add the default services | 		// add the default services | ||||||
| 		SubSystems_.push_back(KafkaManager()); | 		SubSystems_.push_back(KafkaManager()); | ||||||
| @@ -200,10 +149,22 @@ namespace OpenWifi { | |||||||
| 		Poco::Net::HTTPSStreamFactory::registerFactory(); | 		Poco::Net::HTTPSStreamFactory::registerFactory(); | ||||||
| 		Poco::Net::FTPStreamFactory::registerFactory(); | 		Poco::Net::FTPStreamFactory::registerFactory(); | ||||||
| 		Poco::Net::FTPSStreamFactory::registerFactory(); | 		Poco::Net::FTPSStreamFactory::registerFactory(); | ||||||
|  | 		std::string Location = Poco::Environment::get(DAEMON_CONFIG_ENV_VAR,"."); | ||||||
|  | 		Poco::Path ConfigFile; | ||||||
|  |  | ||||||
| 		LoadConfigurationFile(); | 		ConfigFile = ConfigFileName_.empty() ? Location + "/" + DAEMON_PROPERTIES_FILENAME : ConfigFileName_; | ||||||
|  |  | ||||||
|         static const char * LogFilePathKey = "logging.channels.c2.path"; | 		if(!ConfigFile.isFile()) | ||||||
|  | 		{ | ||||||
|  | 			std::cerr << DAEMON_APP_NAME << ": Configuration " | ||||||
|  | 					  << ConfigFile.toString() << " does not seem to exist. Please set " + DAEMON_CONFIG_ENV_VAR | ||||||
|  | 												  + " env variable the path of the " + DAEMON_PROPERTIES_FILENAME + " file." << std::endl; | ||||||
|  | 			std::exit(Poco::Util::Application::EXIT_CONFIG); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		static const char * LogFilePathKey = "logging.channels.c2.path"; | ||||||
|  |  | ||||||
|  | 		loadConfiguration(ConfigFile.toString()); | ||||||
|  |  | ||||||
| 		if(LogDir_.empty()) { | 		if(LogDir_.empty()) { | ||||||
| 			std::string OriginalLogFileValue = ConfigPath(LogFilePathKey); | 			std::string OriginalLogFileValue = ConfigPath(LogFilePathKey); | ||||||
| @@ -211,8 +172,7 @@ namespace OpenWifi { | |||||||
| 		} else { | 		} else { | ||||||
| 			config().setString(LogFilePathKey, LogDir_); | 			config().setString(LogFilePathKey, LogDir_); | ||||||
| 		} | 		} | ||||||
|  | 		Poco::File	DataDir(ConfigPath("ucentral.system.data")); | ||||||
| 		Poco::File	DataDir(ConfigPath("openwifi.system.data")); |  | ||||||
| 		DataDir_ = DataDir.path(); | 		DataDir_ = DataDir.path(); | ||||||
| 		if(!DataDir.exists()) { | 		if(!DataDir.exists()) { | ||||||
| 			try { | 			try { | ||||||
| @@ -221,9 +181,17 @@ namespace OpenWifi { | |||||||
| 				logger().log(E); | 				logger().log(E); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | 		std::string KeyFile = ConfigPath("ucentral.service.key"); | ||||||
| 		LoadMyConfig(); | 		std::string KeyFilePassword = ConfigPath("ucentral.service.key.password" , "" ); | ||||||
|  | 		AppKey_ = Poco::SharedPtr<Poco::Crypto::RSAKey>(new Poco::Crypto::RSAKey("", KeyFile, KeyFilePassword)); | ||||||
|  | 		Cipher_ = CipherFactory_.createCipher(*AppKey_); | ||||||
|  | 		ID_ = Utils::GetSystemId(); | ||||||
|  | 		if(!DebugMode_) | ||||||
|  | 			DebugMode_ = ConfigGetBool("ucentral.system.debug",false); | ||||||
|  | 		MyPrivateEndPoint_ = ConfigGetString("ucentral.system.uri.private"); | ||||||
|  | 		MyPublicEndPoint_ = ConfigGetString("ucentral.system.uri.public"); | ||||||
|  | 		UIURI_ = ConfigGetString("ucentral.system.uri.ui"); | ||||||
|  | 		MyHash_ = CreateHash(MyPublicEndPoint_); | ||||||
| 		InitializeSubSystemServers(); | 		InitializeSubSystemServers(); | ||||||
| 		ServerApplication::initialize(self); | 		ServerApplication::initialize(self); | ||||||
|  |  | ||||||
| @@ -358,23 +326,14 @@ namespace OpenWifi { | |||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	void MicroService::Reload(const std::string &Sub) { |  | ||||||
| 		for (auto i : SubSystems_) { |  | ||||||
| 			if (Poco::toLower(Sub) == Poco::toLower(i->Name())) { |  | ||||||
| 				i->reinitialize(Poco::Util::Application::instance()); |  | ||||||
| 				return; |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	Types::StringVec MicroService::GetSubSystems() const { | 	Types::StringVec MicroService::GetSubSystems() const { | ||||||
| 		Types::StringVec Result; | 		Types::StringVec Result; | ||||||
| 		for(auto i:SubSystems_) | 		for(auto i:SubSystems_) | ||||||
| 			Result.push_back(Poco::toLower(i->Name())); | 			Result.push_back(i->Name()); | ||||||
| 		return Result; | 		return Result; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	Types::StringPairVec MicroService::GetLogLevels() { | 	Types::StringPairVec MicroService::GetLogLevels() const { | ||||||
| 		Types::StringPairVec Result; | 		Types::StringPairVec Result; | ||||||
|  |  | ||||||
| 		for(auto &i:SubSystems_) { | 		for(auto &i:SubSystems_) { | ||||||
| @@ -384,7 +343,7 @@ namespace OpenWifi { | |||||||
| 		return Result; | 		return Result; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	const Types::StringVec & MicroService::GetLogLevelNames() { | 	const Types::StringVec & MicroService::GetLogLevelNames() const { | ||||||
| 		static Types::StringVec LevelNames{"none", "fatal", "critical", "error", "warning", "notice", "information", "debug", "trace" }; | 		static Types::StringVec LevelNames{"none", "fatal", "critical", "error", "warning", "notice", "information", "debug", "trace" }; | ||||||
| 		return LevelNames; | 		return LevelNames; | ||||||
| 	} | 	} | ||||||
| @@ -458,7 +417,7 @@ namespace OpenWifi { | |||||||
| 			Poco::Thread::trySleep((unsigned long)Daemon()->DaemonBusTimer()); | 			Poco::Thread::trySleep((unsigned long)Daemon()->DaemonBusTimer()); | ||||||
| 			if(!Running_) | 			if(!Running_) | ||||||
| 				break; | 				break; | ||||||
| 			Msg = Daemon()->MakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE); | 			auto Msg = Daemon()->MakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_KEEP_ALIVE); | ||||||
| 			KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS,Daemon()->PrivateEndPoint(),Msg, false); | 			KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS,Daemon()->PrivateEndPoint(),Msg, false); | ||||||
| 		} | 		} | ||||||
| 		Msg = Daemon()->MakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_LEAVE); | 		Msg = Daemon()->MakeSystemEventMessage(KafkaTopics::ServiceEvents::EVENT_LEAVE); | ||||||
|   | |||||||
| @@ -1,9 +1,5 @@ | |||||||
| // | // | ||||||
| //	License type: BSD 3-Clause License | // Created by stephane bourque on 2021-06-22. | ||||||
| //	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_MICROSERVICE_H | #ifndef UCENTRALGW_MICROSERVICE_H | ||||||
| @@ -28,17 +24,16 @@ | |||||||
| #include "Poco/Net/HTTPServerRequest.h" | #include "Poco/Net/HTTPServerRequest.h" | ||||||
| #include "Poco/Process.h" | #include "Poco/Process.h" | ||||||
|  |  | ||||||
| #include "OpenWifiTypes.h" | #include "uCentralTypes.h" | ||||||
| #include "SubSystemServer.h" | #include "SubSystemServer.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|  |  | ||||||
| 	static const std::string uSERVICE_SECURITY{"owsec"}; | 	static const std::string uSERVICE_SECURITY{"ucentralsec"}; | ||||||
| 	static const std::string uSERVICE_GATEWAY{"owgw"}; | 	static const std::string uSERVICE_GATEWAY{"ucentralgw"}; | ||||||
| 	static const std::string uSERVICE_FIRMWARE{ "owfms"}; | 	static const std::string uSERVICE_FIRMWARE{ "ucentralfws"}; | ||||||
|     static const std::string uSERVICE_TOPOLOGY{ "owtopo"}; |     static const std::string uSERVICE_TOPOLOGY{ "ucentraltopo"}; | ||||||
|     static const std::string uSERVICE_PROVISIONING{ "owprov"}; |     static const std::string uSERVICE_PROVISIONING{ "ucentralprov"}; | ||||||
|     static const std::string uSERVICE_OWLS{ "owls"}; |  | ||||||
|  |  | ||||||
| 	class MyErrorHandler : public Poco::ErrorHandler { | 	class MyErrorHandler : public Poco::ErrorHandler { | ||||||
| 	  public: | 	  public: | ||||||
| @@ -87,6 +82,9 @@ namespace OpenWifi { | |||||||
| 			DAEMON_APP_NAME(std::move(AppName)), | 			DAEMON_APP_NAME(std::move(AppName)), | ||||||
| 			DAEMON_BUS_TIMER(BusTimer), | 			DAEMON_BUS_TIMER(BusTimer), | ||||||
| 			SubSystems_(std::move(Subsystems)) { | 			SubSystems_(std::move(Subsystems)) { | ||||||
|  | 			std::string V{APP_VERSION}; | ||||||
|  | 			std::string B{BUILD_NUMBER}; | ||||||
|  | 			Version_ =  V + "(" + B +  ")"; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		int main(const ArgVec &args) override; | 		int main(const ArgVec &args) override; | ||||||
| @@ -113,8 +111,8 @@ namespace OpenWifi { | |||||||
| 		[[nodiscard]] bool Debug() const { return DebugMode_; } | 		[[nodiscard]] bool Debug() const { return DebugMode_; } | ||||||
| 		[[nodiscard]] uint64_t ID() const { return ID_; } | 		[[nodiscard]] uint64_t ID() const { return ID_; } | ||||||
| 		[[nodiscard]] Types::StringVec GetSubSystems() const; | 		[[nodiscard]] Types::StringVec GetSubSystems() const; | ||||||
| 		[[nodiscard]] Types::StringPairVec GetLogLevels() ; | 		[[nodiscard]] Types::StringPairVec GetLogLevels() const; | ||||||
| 		[[nodiscard]] static const Types::StringVec & GetLogLevelNames(); | 		[[nodiscard]] const Types::StringVec & GetLogLevelNames() const; | ||||||
| 		[[nodiscard]] std::string ConfigGetString(const std::string &Key,const std::string & Default); | 		[[nodiscard]] std::string ConfigGetString(const std::string &Key,const std::string & Default); | ||||||
| 		[[nodiscard]] std::string ConfigGetString(const std::string &Key); | 		[[nodiscard]] std::string ConfigGetString(const std::string &Key); | ||||||
| 		[[nodiscard]] std::string ConfigPath(const std::string &Key,const std::string & Default); | 		[[nodiscard]] std::string ConfigPath(const std::string &Key,const std::string & Default); | ||||||
| @@ -131,7 +129,6 @@ namespace OpenWifi { | |||||||
| 		[[nodiscard]] std::string PrivateEndPoint() const { return MyPrivateEndPoint_; }; | 		[[nodiscard]] std::string PrivateEndPoint() const { return MyPrivateEndPoint_; }; | ||||||
| 		[[nodiscard]] std::string PublicEndPoint() const { return MyPublicEndPoint_; }; | 		[[nodiscard]] std::string PublicEndPoint() const { return MyPublicEndPoint_; }; | ||||||
| 		[[nodiscard]] std::string MakeSystemEventMessage( const std::string & Type ) const ; | 		[[nodiscard]] std::string MakeSystemEventMessage( const std::string & Type ) const ; | ||||||
| 		[[nodiscard]] const Types::SubSystemVec & GetFullSubSystems() { return SubSystems_; } |  | ||||||
| 		inline uint64_t DaemonBusTimer() const { return DAEMON_BUS_TIMER; }; | 		inline uint64_t DaemonBusTimer() const { return DAEMON_BUS_TIMER; }; | ||||||
|  |  | ||||||
| 		void BusMessageReceived( const std::string & Key, const std::string & Message); | 		void BusMessageReceived( const std::string & Key, const std::string & Message); | ||||||
| @@ -139,17 +136,11 @@ namespace OpenWifi { | |||||||
| 		[[nodiscard]] MicroServiceMetaVec GetServices(); | 		[[nodiscard]] MicroServiceMetaVec GetServices(); | ||||||
| 		[[nodiscard]] bool IsValidAPIKEY(const Poco::Net::HTTPServerRequest &Request); | 		[[nodiscard]] bool IsValidAPIKEY(const Poco::Net::HTTPServerRequest &Request); | ||||||
|  |  | ||||||
| 		static void SavePID(); | 		void SavePID(); | ||||||
| 		static inline uint64_t GetPID() { return Poco::Process::id(); }; | 		inline uint64_t GetPID() { return Poco::Process::id(); }; | ||||||
| 		[[nodiscard]] inline const std::string GetPublicAPIEndPoint() { return MyPublicEndPoint_ + "/api/v1"; }; | 		[[nodiscard]] inline const std::string GetPublicAPIEndPoint() const { return MyPublicEndPoint_ + "/api/v1"; }; | ||||||
| 		[[nodiscard]] inline const std::string & GetUIURI() const { return UIURI_;}; | 		[[nodiscard]] inline const std::string & GetUIURI() const { return UIURI_;}; | ||||||
|  |  | ||||||
| 		void Reload(const std::string &Name);   //  reload a subsystem |  | ||||||
| 		void Reload();                          //  reload the daemon itself |  | ||||||
| 		void LoadMyConfig(); |  | ||||||
|  |  | ||||||
| 		void LoadConfigurationFile(); |  | ||||||
|  |  | ||||||
| 	  private: | 	  private: | ||||||
| 		bool                        HelpRequested_ = false; | 		bool                        HelpRequested_ = false; | ||||||
| 		std::string                 LogDir_; | 		std::string                 LogDir_; | ||||||
| @@ -168,9 +159,9 @@ namespace OpenWifi { | |||||||
| 		std::string 				MyPrivateEndPoint_; | 		std::string 				MyPrivateEndPoint_; | ||||||
| 		std::string 				MyPublicEndPoint_; | 		std::string 				MyPublicEndPoint_; | ||||||
| 		std::string                 UIURI_; | 		std::string                 UIURI_; | ||||||
| 		std::string 				Version_{std::string(APP_VERSION) + "("+ BUILD_NUMBER + ")"}; | 		std::string 				Version_; | ||||||
| 		BusEventManager				BusEventManager_; | 		BusEventManager				BusEventManager_; | ||||||
| 		std::mutex 					InfraMutex_; | 		SubMutex 					InfraMutex_; | ||||||
|  |  | ||||||
| 		std::string DAEMON_PROPERTIES_FILENAME; | 		std::string DAEMON_PROPERTIES_FILENAME; | ||||||
| 		std::string DAEMON_ROOT_ENV_VAR; | 		std::string DAEMON_ROOT_ENV_VAR; | ||||||
|   | |||||||
| @@ -1,71 +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 <iostream> |  | ||||||
|  |  | ||||||
| #include "OpenAPIRequest.h" |  | ||||||
|  |  | ||||||
| #include "Poco/Net/HTTPSClientSession.h" |  | ||||||
| #include <Poco/Net/HTTPRequest.h> |  | ||||||
| #include <Poco/Net/HTTPResponse.h> |  | ||||||
| #include <Poco/JSON/Parser.h> |  | ||||||
| #include <Poco/URI.h> |  | ||||||
| #include <Poco/Exception.h> |  | ||||||
| #include "Utils.h" |  | ||||||
| #include "Daemon.h" |  | ||||||
|  |  | ||||||
| namespace OpenWifi { |  | ||||||
|  |  | ||||||
| 	OpenAPIRequestGet::OpenAPIRequestGet( 	std::string ServiceType, |  | ||||||
| 											std::string EndPoint, |  | ||||||
| 									 		Types::StringPairVec & QueryData, |  | ||||||
| 											uint64_t msTimeout): |  | ||||||
|  		Type_(std::move(ServiceType)), |  | ||||||
|  		EndPoint_(std::move(EndPoint)), |  | ||||||
| 		QueryData_(QueryData), |  | ||||||
| 		msTimeout_(msTimeout) { |  | ||||||
|  |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	int OpenAPIRequestGet::Do(Poco::JSON::Object::Ptr &ResponseObject) { |  | ||||||
| 		try { |  | ||||||
| 		    auto Services = Daemon()->GetServices(Type_); |  | ||||||
| 			for(auto const &Svc:Services) { |  | ||||||
| 				Poco::URI	URI(Svc.PrivateEndPoint); |  | ||||||
| 				Poco::Net::HTTPSClientSession Session(URI.getHost(), URI.getPort()); |  | ||||||
|  |  | ||||||
| 				URI.setPath(EndPoint_); |  | ||||||
| 				for (const auto &qp : QueryData_) |  | ||||||
| 					URI.addQueryParameter(qp.first, qp.second); |  | ||||||
|  |  | ||||||
| 				std::string Path(URI.getPathAndQuery()); |  | ||||||
| 				Session.setTimeout(Poco::Timespan(msTimeout_/1000, msTimeout_ % 1000)); |  | ||||||
|  |  | ||||||
| 				Poco::Net::HTTPRequest Request(Poco::Net::HTTPRequest::HTTP_GET, |  | ||||||
| 											   Path, |  | ||||||
| 											   Poco::Net::HTTPMessage::HTTP_1_1); |  | ||||||
| 				Request.add("X-API-KEY", Svc.AccessKey); |  | ||||||
| 				Session.sendRequest(Request); |  | ||||||
|  |  | ||||||
| 				Poco::Net::HTTPResponse Response; |  | ||||||
| 				std::istream &is = Session.receiveResponse(Response); |  | ||||||
| 				if(Response.getStatus()==Poco::Net::HTTPResponse::HTTP_OK) { |  | ||||||
| 					Poco::JSON::Parser	P; |  | ||||||
| 					ResponseObject = P.parse(is).extract<Poco::JSON::Object::Ptr>(); |  | ||||||
| 				} |  | ||||||
| 				return Response.getStatus(); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		catch (const Poco::Exception &E) |  | ||||||
| 		{ |  | ||||||
| 			std::cerr << E.displayText() << std::endl; |  | ||||||
| 		} |  | ||||||
| 		return -1; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| @@ -1,33 +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. |  | ||||||
| // |  | ||||||
|  |  | ||||||
| #ifndef UCENTRALGW_OPENAPIREQUEST_H |  | ||||||
| #define UCENTRALGW_OPENAPIREQUEST_H |  | ||||||
|  |  | ||||||
| #include "Poco/JSON/Object.h" |  | ||||||
|  |  | ||||||
| #include "OpenWifiTypes.h" |  | ||||||
|  |  | ||||||
| namespace OpenWifi { |  | ||||||
|  |  | ||||||
| 	class OpenAPIRequestGet { |  | ||||||
| 	  public: |  | ||||||
| 		explicit OpenAPIRequestGet( std::string Type, |  | ||||||
| 								   	std::string EndPoint, |  | ||||||
| 									Types::StringPairVec & QueryData, |  | ||||||
| 									uint64_t msTimeout); |  | ||||||
| 		int Do(Poco::JSON::Object::Ptr &ResponseObject); |  | ||||||
| 	  private: |  | ||||||
| 		std::string 			Type_; |  | ||||||
| 		std::string 			EndPoint_; |  | ||||||
| 		Types::StringPairVec 	QueryData_; |  | ||||||
| 		uint64_t 				msTimeout_; |  | ||||||
| 	}; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #endif // UCENTRALGW_OPENAPIREQUEST_H |  | ||||||
| @@ -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. |  | ||||||
| // |  | ||||||
|  |  | ||||||
| #ifndef UCENTRALGW_UCENTRALTYPES_H |  | ||||||
| #define UCENTRALGW_UCENTRALTYPES_H |  | ||||||
|  |  | ||||||
| #include "SubSystemServer.h" |  | ||||||
|  |  | ||||||
| #include <vector> |  | ||||||
| #include <string> |  | ||||||
| #include <map> |  | ||||||
| #include <functional> |  | ||||||
| #include <list> |  | ||||||
| #include <utility> |  | ||||||
| #include <queue> |  | ||||||
|  |  | ||||||
| #include "Poco/StringTokenizer.h" |  | ||||||
| #include "Poco/JSON/Parser.h" |  | ||||||
| #include "Poco/JSON/Stringifier.h" |  | ||||||
|  |  | ||||||
| namespace OpenWifi::Types { |  | ||||||
|     typedef std::pair<std::string,std::string>              StringPair; |  | ||||||
| 	typedef std::vector<StringPair>	                        StringPairVec; |  | ||||||
|     typedef std::queue<StringPair>	                        StringPairQueue; |  | ||||||
| 	typedef std::vector<std::string>						StringVec; |  | ||||||
| 	typedef std::set<std::string>                           StringSet; |  | ||||||
| 	typedef std::vector<SubSystemServer*>					SubSystemVec; |  | ||||||
| 	typedef std::map<std::string,std::set<std::string>>		StringMapStringSet; |  | ||||||
| 	typedef std::function<void(std::string, std::string)>   TopicNotifyFunction; |  | ||||||
| 	typedef std::list<std::pair<TopicNotifyFunction,int>>   TopicNotifyFunctionList; |  | ||||||
| 	typedef std::map<std::string, TopicNotifyFunctionList>  NotifyTable; |  | ||||||
|     typedef std::map<std::string,uint64_t>                  CountedMap; |  | ||||||
|  |  | ||||||
|     typedef std::string         UUID_t; |  | ||||||
|     typedef std::vector<UUID_t> UUIDvec_t; |  | ||||||
|  |  | ||||||
|     inline void UpdateCountedMap(CountedMap &M, const std::string &S, uint64_t Increment=1) { |  | ||||||
|         auto it = M.find(S); |  | ||||||
|         if(it==M.end()) |  | ||||||
|             M[S] = Increment; |  | ||||||
|         else |  | ||||||
|             it->second += Increment; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     inline std::string to_string( const StringVec &V) { |  | ||||||
|         Poco::JSON::Array   O; |  | ||||||
|         for(const auto &i:V) { |  | ||||||
|             O.add(i); |  | ||||||
|         } |  | ||||||
|         std::stringstream SS; |  | ||||||
|         Poco::JSON::Stringifier::stringify(O,SS); |  | ||||||
|         return SS.str(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     inline std::string to_string( const StringPairVec &V) { |  | ||||||
|         Poco::JSON::Array   O; |  | ||||||
|         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 |  | ||||||
| @@ -9,20 +9,27 @@ | |||||||
| #include "Utils.h" | #include "Utils.h" | ||||||
| #include "RESTAPI_protocol.h" | #include "RESTAPI_protocol.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|     void RESTAPI_AssetServer::DoGet() { |     void RESTAPI_AssetServer::handleRequest(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) { | ||||||
|  |         if(Request.getMethod()==Poco::Net::HTTPRequest::HTTP_GET) | ||||||
|  |             DoGet(Request, Response); | ||||||
|  |         else | ||||||
|  |             NotFound(Request, Response); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void RESTAPI_AssetServer::DoGet(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) { | ||||||
|         Poco::File  AssetFile; |         Poco::File  AssetFile; | ||||||
|  |  | ||||||
|         if(Request->getURI().find("/favicon.ico") != std::string::npos) { |         if(Request.getURI().find("/favicon.ico") != std::string::npos) { | ||||||
|             AssetFile = RESTAPI_Server()->AssetDir() + "/favicon.ico"; |             AssetFile = RESTAPI_Server()->AssetDir() + "/favicon.ico"; | ||||||
|         } else { |         } else { | ||||||
|             std::string AssetName = GetBinding(RESTAPI::Protocol::ID, ""); |             std::string AssetName = GetBinding(RESTAPI::Protocol::ID, ""); | ||||||
|             AssetFile = RESTAPI_Server()->AssetDir() + "/" + AssetName; |             AssetFile = RESTAPI_Server()->AssetDir() + "/" + AssetName; | ||||||
|         } |         } | ||||||
|         if(!AssetFile.isFile()) { |         if(!AssetFile.isFile()) { | ||||||
|             NotFound(); |             NotFound(Request, Response); | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|         SendFile(AssetFile); |         SendFile(AssetFile,Request, Response); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -7,10 +7,10 @@ | |||||||
|  |  | ||||||
| #include "RESTAPI_handler.h" | #include "RESTAPI_handler.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|     class RESTAPI_AssetServer : public RESTAPIHandler { |     class RESTAPI_AssetServer : public RESTAPIHandler { | ||||||
|     public: |     public: | ||||||
|         RESTAPI_AssetServer(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, bool Internal) |         RESTAPI_AssetServer(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal) | ||||||
|                 : RESTAPIHandler(bindings, L, |                 : RESTAPIHandler(bindings, L, | ||||||
|                                  std::vector<std::string> |                                  std::vector<std::string> | ||||||
|                                          {Poco::Net::HTTPRequest::HTTP_POST, |                                          {Poco::Net::HTTPRequest::HTTP_POST, | ||||||
| @@ -18,15 +18,11 @@ namespace OpenWifi { | |||||||
|                                           Poco::Net::HTTPRequest::HTTP_PUT, |                                           Poco::Net::HTTPRequest::HTTP_PUT, | ||||||
|                                           Poco::Net::HTTPRequest::HTTP_DELETE, |                                           Poco::Net::HTTPRequest::HTTP_DELETE, | ||||||
|                                           Poco::Net::HTTPRequest::HTTP_OPTIONS}, |                                           Poco::Net::HTTPRequest::HTTP_OPTIONS}, | ||||||
|                                           Server, |  | ||||||
|                                           Internal) {} |                                           Internal) {} | ||||||
|  |         void handleRequest(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) override; | ||||||
|         static const std::list<const char *> PathName() { return std::list<const char *>{"/wwwassets/{id}" , |         static const std::list<const char *> PathName() { return std::list<const char *>{"/wwwassets/{id}" , | ||||||
|                                                                                          "/favicon.ico"}; }; |                                                                                          "/favicon.ico"}; }; | ||||||
|         void DoGet() final; |         void DoGet(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response); | ||||||
|         void DoPost() final {}; |  | ||||||
|         void DoDelete() final {}; |  | ||||||
|         void DoPut() final {}; |  | ||||||
|  |  | ||||||
|     private: |     private: | ||||||
|  |  | ||||||
|     }; |     }; | ||||||
|   | |||||||
| @@ -1,5 +0,0 @@ | |||||||
| // |  | ||||||
| // Created by stephane bourque on 2021-09-15. |  | ||||||
| // |  | ||||||
|  |  | ||||||
| #include "RESTAPI_GenericServer.h" |  | ||||||
| @@ -1,78 +0,0 @@ | |||||||
| // |  | ||||||
| // Created by stephane bourque on 2021-09-15. |  | ||||||
| // |  | ||||||
|  |  | ||||||
| #ifndef OWPROV_RESTAPI_GENERICSERVER_H |  | ||||||
| #define OWPROV_RESTAPI_GENERICSERVER_H |  | ||||||
|  |  | ||||||
| #include <vector> |  | ||||||
| #include <string> |  | ||||||
|  |  | ||||||
| #include "Daemon.h" |  | ||||||
| #include "Poco/StringTokenizer.h" |  | ||||||
| #include "Poco/Net/HTTPRequest.h" |  | ||||||
|  |  | ||||||
| namespace OpenWifi { |  | ||||||
|  |  | ||||||
|     class RESTAPI_GenericServer { |  | ||||||
|     public: |  | ||||||
|  |  | ||||||
|         enum { |  | ||||||
|             LOG_GET=0, |  | ||||||
|             LOG_DELETE, |  | ||||||
|             LOG_PUT, |  | ||||||
|             LOG_POST |  | ||||||
|         }; |  | ||||||
|  |  | ||||||
|         void inline SetFlags(bool External, const std::string &Methods) { |  | ||||||
|             Poco::StringTokenizer   Tokens(Methods,","); |  | ||||||
|             auto Offset = (External ? 0 : 4); |  | ||||||
|             for(const auto &i:Tokens) { |  | ||||||
|                 if(Poco::icompare(i,Poco::Net::HTTPRequest::HTTP_DELETE)==0) |  | ||||||
|                     LogFlags_[Offset+LOG_DELETE]=true; |  | ||||||
|                 else if(Poco::icompare(i,Poco::Net::HTTPRequest::HTTP_PUT)==0) |  | ||||||
|                     LogFlags_[Offset+LOG_PUT]=true; |  | ||||||
|                 else if(Poco::icompare(i,Poco::Net::HTTPRequest::HTTP_POST)==0) |  | ||||||
|                     LogFlags_[Offset+LOG_POST]=true; |  | ||||||
|                 else if(Poco::icompare(i,Poco::Net::HTTPRequest::HTTP_GET)==0) |  | ||||||
|                     LogFlags_[Offset+LOG_GET]=true; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         inline void InitLogging() { |  | ||||||
|             std::string Public = Daemon()->ConfigGetString("apilogging.public.methods","PUT,POST,DELETE"); |  | ||||||
|             SetFlags(true, Public); |  | ||||||
|             std::string Private = Daemon()->ConfigGetString("apilogging.private.methods","PUT,POST,DELETE"); |  | ||||||
|             SetFlags(false, Private); |  | ||||||
|  |  | ||||||
|             std::string PublicBadTokens = Daemon()->ConfigGetString("apilogging.public.badtokens.methods",""); |  | ||||||
|             LogBadTokens_[0] = (Poco::icompare(PublicBadTokens,"true")==0); |  | ||||||
|             std::string PrivateBadTokens = Daemon()->ConfigGetString("apilogging.private.badtokens.methods",""); |  | ||||||
|             LogBadTokens_[1] = (Poco::icompare(PrivateBadTokens,"true")==0); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         [[nodiscard]] inline bool LogIt(const std::string &Method, bool External) const { |  | ||||||
|             auto Offset = (External ? 0 : 4); |  | ||||||
|             if(Method == Poco::Net::HTTPRequest::HTTP_GET) |  | ||||||
|                 return LogFlags_[Offset+LOG_GET]; |  | ||||||
|             if(Method == Poco::Net::HTTPRequest::HTTP_POST) |  | ||||||
|                 return LogFlags_[Offset+LOG_POST]; |  | ||||||
|             if(Method == Poco::Net::HTTPRequest::HTTP_PUT) |  | ||||||
|                 return LogFlags_[Offset+LOG_PUT]; |  | ||||||
|             if(Method == Poco::Net::HTTPRequest::HTTP_DELETE) |  | ||||||
|                 return LogFlags_[Offset+LOG_DELETE]; |  | ||||||
|             return false; |  | ||||||
|         }; |  | ||||||
|  |  | ||||||
|         [[nodiscard]] inline bool LogBadTokens(bool External) const { |  | ||||||
|             return LogBadTokens_[ (External ? 0 : 1) ]; |  | ||||||
|         }; |  | ||||||
|  |  | ||||||
|     private: |  | ||||||
|         std::array<bool,8>       LogFlags_{false}; |  | ||||||
|         std::array<bool,2>       LogBadTokens_{false}; |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  |  | ||||||
| #endif //OWPROV_RESTAPI_GENERICSERVER_H |  | ||||||
| @@ -14,18 +14,17 @@ | |||||||
|  |  | ||||||
| #include "Utils.h" | #include "Utils.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|  |  | ||||||
|     class RESTAPI_InternalServer *RESTAPI_InternalServer::instance_ = nullptr; |     class RESTAPI_InternalServer *RESTAPI_InternalServer::instance_ = nullptr; | ||||||
|  |  | ||||||
|     RESTAPI_InternalServer::RESTAPI_InternalServer() noexcept: |     RESTAPI_InternalServer::RESTAPI_InternalServer() noexcept: | ||||||
|         SubSystemServer("RESTAPIInternalServer", "REST-ISRV", "openwifi.internal.restapi") |         SubSystemServer("RESTAPIInternalServer", "REST-ISRV", "ucentral.internal.restapi") | ||||||
|     { |     { | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     int RESTAPI_InternalServer::Start() { |     int RESTAPI_InternalServer::Start() { | ||||||
|         Logger_.information("Starting."); |         Logger_.information("Starting."); | ||||||
|         Server_.InitLogging(); |  | ||||||
|  |  | ||||||
|         for(const auto & Svr: ConfigServersList_) { |         for(const auto & Svr: ConfigServersList_) { | ||||||
|             Logger_.information(Poco::format("Starting: %s:%s Keyfile:%s CertFile: %s", Svr.Address(), std::to_string(Svr.Port()), |             Logger_.information(Poco::format("Starting: %s:%s Keyfile:%s CertFile: %s", Svr.Address(), std::to_string(Svr.Port()), | ||||||
| @@ -42,7 +41,7 @@ namespace OpenWifi { | |||||||
|             Params->setMaxQueued(200); |             Params->setMaxQueued(200); | ||||||
|             Params->setKeepAlive(true); |             Params->setKeepAlive(true); | ||||||
|  |  | ||||||
|             auto NewServer = std::make_unique<Poco::Net::HTTPServer>(new InternalRequestHandlerFactory(Server_), Pool_, Sock, Params); |             auto NewServer = std::make_unique<Poco::Net::HTTPServer>(new InternalRequestHandlerFactory, Pool_, Sock, Params); | ||||||
|             NewServer->start(); |             NewServer->start(); | ||||||
|             RESTServers_.push_back(std::move(NewServer)); |             RESTServers_.push_back(std::move(NewServer)); | ||||||
|         } |         } | ||||||
| @@ -54,17 +53,14 @@ namespace OpenWifi { | |||||||
|         Logger_.information("Stopping "); |         Logger_.information("Stopping "); | ||||||
|         for( const auto & svr : RESTServers_ ) |         for( const auto & svr : RESTServers_ ) | ||||||
|             svr->stop(); |             svr->stop(); | ||||||
|         RESTServers_.clear(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void RESTAPI_InternalServer::reinitialize(Poco::Util::Application &self) { |  | ||||||
|         Daemon()->LoadConfigurationFile(); |  | ||||||
|         Logger_.information("Reinitializing."); |  | ||||||
|         Stop(); |  | ||||||
|         Start(); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     Poco::Net::HTTPRequestHandler *InternalRequestHandlerFactory::createRequestHandler(const Poco::Net::HTTPServerRequest & Request) { |     Poco::Net::HTTPRequestHandler *InternalRequestHandlerFactory::createRequestHandler(const Poco::Net::HTTPServerRequest & Request) { | ||||||
|  |  | ||||||
|  |         Logger_.debug(Poco::format("REQUEST(%s): %s %s", | ||||||
|  |                                    uCentral::Utils::FormatIPv6(Request.clientAddress().toString()), | ||||||
|  |                                    Request.getMethod(), Request.getURI())); | ||||||
|  |  | ||||||
|         Poco::URI uri(Request.getURI()); |         Poco::URI uri(Request.getURI()); | ||||||
|         const auto & Path = uri.getPath(); |         const auto & Path = uri.getPath(); | ||||||
|         RESTAPIHandler::BindingMap Bindings; |         RESTAPIHandler::BindingMap Bindings; | ||||||
| @@ -74,7 +70,7 @@ namespace OpenWifi { | |||||||
|                 RESTAPI_system_command, |                 RESTAPI_system_command, | ||||||
|                 RESTAPI_action_links, |                 RESTAPI_action_links, | ||||||
|                 RESTAPI_validateToken_handler |                 RESTAPI_validateToken_handler | ||||||
|         >(Path,Bindings,Logger_, Server_); |         >(Path,Bindings,Logger_); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| } | } | ||||||
| @@ -11,9 +11,8 @@ | |||||||
| #include "Poco/Net/HTTPRequestHandlerFactory.h" | #include "Poco/Net/HTTPRequestHandlerFactory.h" | ||||||
| #include "Poco/Net/HTTPServerRequest.h" | #include "Poco/Net/HTTPServerRequest.h" | ||||||
| #include "Poco/Net/NetException.h" | #include "Poco/Net/NetException.h" | ||||||
| #include "RESTAPI_GenericServer.h" |  | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|  |  | ||||||
|     class RESTAPI_InternalServer : public SubSystemServer { |     class RESTAPI_InternalServer : public SubSystemServer { | ||||||
|         public: |         public: | ||||||
| @@ -28,27 +27,23 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
|             int Start() override; |             int Start() override; | ||||||
|             void Stop() override; |             void Stop() override; | ||||||
|             void reinitialize(Poco::Util::Application &self) override; |  | ||||||
|  |  | ||||||
|         private: |         private: | ||||||
|             static RESTAPI_InternalServer *instance_; |             static RESTAPI_InternalServer *instance_; | ||||||
|             std::vector<std::unique_ptr<Poco::Net::HTTPServer>>   RESTServers_; |             std::vector<std::unique_ptr<Poco::Net::HTTPServer>>   RESTServers_; | ||||||
|             Poco::ThreadPool	    Pool_; |             Poco::ThreadPool	Pool_; | ||||||
|             RESTAPI_GenericServer   Server_; |  | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     inline RESTAPI_InternalServer * RESTAPI_InternalServer() { return RESTAPI_InternalServer::instance(); }; |     inline RESTAPI_InternalServer * RESTAPI_InternalServer() { return RESTAPI_InternalServer::instance(); }; | ||||||
|  |  | ||||||
|     class InternalRequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory { |     class InternalRequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory { | ||||||
|         public: |         public: | ||||||
|         explicit InternalRequestHandlerFactory(RESTAPI_GenericServer & Server) : |             InternalRequestHandlerFactory() : | ||||||
|                     Logger_(RESTAPI_InternalServer()->Logger()), |                     Logger_(RESTAPI_InternalServer()->Logger()){} | ||||||
|                     Server_(Server){} |  | ||||||
|  |  | ||||||
|             Poco::Net::HTTPRequestHandler *createRequestHandler(const Poco::Net::HTTPServerRequest &request) override; |             Poco::Net::HTTPRequestHandler *createRequestHandler(const Poco::Net::HTTPServerRequest &request) override; | ||||||
|         private: |         private: | ||||||
|             Poco::Logger    & Logger_; |             Poco::Logger    & Logger_; | ||||||
|             RESTAPI_GenericServer & Server_; |  | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -12,10 +12,10 @@ | |||||||
| #include "RESTAPI_SecurityObjects.h" | #include "RESTAPI_SecurityObjects.h" | ||||||
| #include "RESTAPI_utils.h" | #include "RESTAPI_utils.h" | ||||||
|  |  | ||||||
| using OpenWifi::RESTAPI_utils::field_to_json; | using uCentral::RESTAPI_utils::field_to_json; | ||||||
| using OpenWifi::RESTAPI_utils::field_from_json; | using uCentral::RESTAPI_utils::field_from_json; | ||||||
|  |  | ||||||
| namespace OpenWifi::SecurityObjects { | namespace uCentral::SecurityObjects { | ||||||
|  |  | ||||||
| 	void AclTemplate::to_json(Poco::JSON::Object &Obj) const { | 	void AclTemplate::to_json(Poco::JSON::Object &Obj) const { | ||||||
| 		field_to_json(Obj,"Read",Read_); | 		field_to_json(Obj,"Read",Read_); | ||||||
| @@ -303,20 +303,6 @@ namespace OpenWifi::SecurityObjects { | |||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|     bool append_from_json(Poco::JSON::Object::Ptr Obj, const UserInfo &UInfo, NoteInfoVec & Notes) { |  | ||||||
| 	    try { |  | ||||||
| 	        SecurityObjects::NoteInfoVec NIV; |  | ||||||
| 	        NIV = RESTAPI_utils::to_object_array<SecurityObjects::NoteInfo>(Obj->get("notes").toString()); |  | ||||||
| 	        for(auto const &i:NIV) { |  | ||||||
| 	            SecurityObjects::NoteInfo   ii{.created=(uint64_t)std::time(nullptr), .createdBy=UInfo.email, .note=i.note}; |  | ||||||
| 	            Notes.push_back(ii); |  | ||||||
| 	        } |  | ||||||
| 	    } catch(...) { |  | ||||||
|  |  | ||||||
| 	    } |  | ||||||
| 	    return false; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	void ProfileAction::to_json(Poco::JSON::Object &Obj) const { | 	void ProfileAction::to_json(Poco::JSON::Object &Obj) const { | ||||||
| 		field_to_json(Obj,"resource", resource); | 		field_to_json(Obj,"resource", resource); | ||||||
| 		field_to_json<ResourceAccessType>(Obj,"access", access, ResourceAccessTypeToString); | 		field_to_json<ResourceAccessType>(Obj,"access", access, ResourceAccessTypeToString); | ||||||
|   | |||||||
| @@ -10,9 +10,9 @@ | |||||||
| #define UCENTRAL_RESTAPI_SECURITYOBJECTS_H | #define UCENTRAL_RESTAPI_SECURITYOBJECTS_H | ||||||
|  |  | ||||||
| #include "Poco/JSON/Object.h" | #include "Poco/JSON/Object.h" | ||||||
| #include "OpenWifiTypes.h" | #include "uCentralTypes.h" | ||||||
|  |  | ||||||
| namespace OpenWifi::SecurityObjects { | namespace uCentral::SecurityObjects { | ||||||
|  |  | ||||||
| 	struct AclTemplate { | 	struct AclTemplate { | ||||||
| 		bool Read_ = true; | 		bool Read_ = true; | ||||||
| @@ -94,8 +94,6 @@ namespace OpenWifi::SecurityObjects { | |||||||
| 	}; | 	}; | ||||||
| 	typedef std::vector<UserInfo>   UserInfoVec; | 	typedef std::vector<UserInfo>   UserInfoVec; | ||||||
|  |  | ||||||
| 	bool append_from_json(Poco::JSON::Object::Ptr Obj, const UserInfo &UInfo, NoteInfoVec & Notes); |  | ||||||
|  |  | ||||||
| 	struct InternalServiceInfo { | 	struct InternalServiceInfo { | ||||||
| 		std::string privateURI; | 		std::string privateURI; | ||||||
| 		std::string publicURI; | 		std::string publicURI; | ||||||
| @@ -116,9 +114,9 @@ namespace OpenWifi::SecurityObjects { | |||||||
| 	struct SystemEndpoint { | 	struct SystemEndpoint { | ||||||
| 		std::string type; | 		std::string type; | ||||||
| 		uint64_t 	id = 0; | 		uint64_t 	id = 0; | ||||||
| 		std::string vendor{"OpenWiFi"}; | 		std::string vendor; | ||||||
| 		std::string uri; | 		std::string uri; | ||||||
| 		std::string authenticationType{"internal_v1"}; | 		std::string authenticationType; | ||||||
| 		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); | ||||||
| 	}; | 	}; | ||||||
| @@ -160,7 +158,7 @@ namespace OpenWifi::SecurityObjects { | |||||||
| 	typedef std::vector<ProfileAction>	ProfileActionVec; | 	typedef std::vector<ProfileAction>	ProfileActionVec; | ||||||
|  |  | ||||||
| 	struct SecurityProfile { | 	struct SecurityProfile { | ||||||
| 		uint64_t id=0; | 		uint64_t id; | ||||||
| 		std::string name; | 		std::string name; | ||||||
| 		std::string description; | 		std::string description; | ||||||
| 		ProfileActionVec policy; | 		ProfileActionVec policy; | ||||||
|   | |||||||
| @@ -12,121 +12,122 @@ | |||||||
| #include "RESTAPI_server.h" | #include "RESTAPI_server.h" | ||||||
| #include "Daemon.h" | #include "Daemon.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|     void RESTAPI_action_links::DoGet() { |     void RESTAPI_action_links::handleRequest(Poco::Net::HTTPServerRequest &Request, | ||||||
|  |                        Poco::Net::HTTPServerResponse &Response) { | ||||||
|  |         //  there is no authentication here, this is just someone clicking on a link | ||||||
|  |         //  and arriving here. There should be a UUID in the link and this is all we need to know | ||||||
|  |         //  what we need to do. | ||||||
|  |         ParseParameters(Request); | ||||||
|  |  | ||||||
|         auto Action = GetParameter("action",""); |         auto Action = GetParameter("action",""); | ||||||
|         auto Id = GetParameter("id",""); |         auto Id = GetParameter("id",""); | ||||||
|  |  | ||||||
|         if(Action=="password_reset") |         if(Action=="password_reset") | ||||||
|             RequestResetPassword(Id); |             DoResetPassword(Id, Request, Response); | ||||||
|         else if(Action=="email_verification") |         else if(Action=="email_verification") | ||||||
|             DoEmailVerification(Id); |             DoEmailVerification(Id, Request, Response); | ||||||
|         else |         else | ||||||
|             DoReturnA404(); |             DoReturnA404(Request, Response); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void RESTAPI_action_links::DoPost() { |     void RESTAPI_action_links::DoResetPassword(std::string &Id,Poco::Net::HTTPServerRequest &Request, | ||||||
|         auto Action = GetParameter("action",""); |                          Poco::Net::HTTPServerResponse &Response) { | ||||||
|         auto Id = GetParameter("id",""); |  | ||||||
|  |  | ||||||
|         Logger_.information(Poco::format("COMPLETE-PASSWORD-RESET(%s): For ID=%s", Request->clientAddress().toString(), Id)); |         if(Request.getMethod()==Poco::Net::HTTPServerRequest::HTTP_GET) { | ||||||
|         if(Action=="password_reset") |             Poco::File  FormFile{ RESTAPI_Server()->AssetDir() + "/password_reset.html"}; | ||||||
|             CompleteResetPassword(Id); |  | ||||||
|         else |  | ||||||
|             DoReturnA404(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void RESTAPI_action_links::RequestResetPassword(std::string &Id) { |  | ||||||
|         Logger_.information(Poco::format("REQUEST-PASSWORD-RESET(%s): For ID=%s", Request->clientAddress().toString(), Id)); |  | ||||||
|         Poco::File  FormFile{ RESTAPI_Server()->AssetDir() + "/password_reset.html"}; |  | ||||||
|         Types::StringPairVec    FormVars{ {"UUID", Id}, |  | ||||||
|                                           {"PASSWORD_VALIDATION", AuthService()->PasswordValidationExpression()}}; |  | ||||||
|         SendHTMLFileBack(FormFile,FormVars); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void RESTAPI_action_links::CompleteResetPassword(std::string &Id) { |  | ||||||
|         //  form has been posted... |  | ||||||
|         RESTAPI_PartHandler PartHandler; |  | ||||||
|         Poco::Net::HTMLForm Form(*Request, Request->stream(), PartHandler); |  | ||||||
|         if (!Form.empty()) { |  | ||||||
|             auto Password1 = Form.get("password1","bla"); |  | ||||||
|             auto Password2 = Form.get("password1","blu"); |  | ||||||
|             Id = Form.get("id",""); |  | ||||||
|             if(Password1!=Password2 || !AuthService()->ValidatePassword(Password2) || !AuthService()->ValidatePassword(Password1)) { |  | ||||||
|                 Poco::File  FormFile{ RESTAPI_Server()->AssetDir() + "/password_reset_error.html"}; |  | ||||||
|                 Types::StringPairVec    FormVars{ {"UUID", Id}, |  | ||||||
|                                                   {"ERROR_TEXT", "For some reason, the passwords entered do not match or they do not comply with" |  | ||||||
|                                                                  " accepted password creation restrictions. Please consult our on-line help" |  | ||||||
|                                                                  " to look at the our password policy. If you would like to contact us, please mention" |  | ||||||
|                                                                  " id(" + Id + ")"}}; |  | ||||||
|                 SendHTMLFileBack(FormFile,FormVars); |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             SecurityObjects::UserInfo   UInfo; |  | ||||||
|             if(!Storage()->GetUserById(Id,UInfo)) { |  | ||||||
|                 Poco::File  FormFile{ RESTAPI_Server()->AssetDir() + "/password_reset_error.html"}; |  | ||||||
|                 Types::StringPairVec    FormVars{ {"UUID", Id}, |  | ||||||
|                                                   {"ERROR_TEXT", "This request does not contain a valid user ID. Please contact your system administrator."}}; |  | ||||||
|                 SendHTMLFileBack(FormFile,FormVars); |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             if(UInfo.blackListed || UInfo.suspended) { |  | ||||||
|                 Poco::File  FormFile{ RESTAPI_Server()->AssetDir() + "/password_reset_error.html"}; |  | ||||||
|                 Types::StringPairVec    FormVars{ {"UUID", Id}, |  | ||||||
|                                                   {"ERROR_TEXT", "Please contact our system administrators. We have identified an error in your account that must be resolved first."}}; |  | ||||||
|                 SendHTMLFileBack(FormFile,FormVars); |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             if(!AuthService()->SetPassword(Password1,UInfo)) { |  | ||||||
|                 Poco::File  FormFile{ RESTAPI_Server()->AssetDir() + "/password_reset_error.html"}; |  | ||||||
|                 Types::StringPairVec    FormVars{ {"UUID", Id}, |  | ||||||
|                                                   {"ERROR_TEXT", "You cannot reuse one of your recent passwords."}}; |  | ||||||
|                 SendHTMLFileBack(FormFile,FormVars); |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|             Storage()->UpdateUserInfo(UInfo.email,Id,UInfo); |  | ||||||
|             Poco::File  FormFile{ RESTAPI_Server()->AssetDir() + "/password_reset_success.html"}; |  | ||||||
|             Types::StringPairVec    FormVars{ {"UUID", Id}, |             Types::StringPairVec    FormVars{ {"UUID", Id}, | ||||||
|                                               {"USERNAME", UInfo.email}, |                                               {"PASSWORD_VALIDATION", AuthService()->PasswordValidationExpression()}}; | ||||||
|                                               {"ACTION_LINK",Daemon()->GetUIURI()}}; |             SendHTMLFileBack(FormFile,Request, Response, FormVars); | ||||||
|             SendHTMLFileBack(FormFile,FormVars); |         } else if(Request.getMethod()==Poco::Net::HTTPServerRequest::HTTP_POST) { | ||||||
|  |             //  form has been posted... | ||||||
|  |             RESTAPI_PartHandler PartHandler; | ||||||
|  |             Poco::Net::HTMLForm Form(Request, Request.stream(), PartHandler); | ||||||
|  |             if (!Form.empty()) { | ||||||
|  |                 auto Password1 = Form.get("password1","bla"); | ||||||
|  |                 auto Password2 = Form.get("password1","blu"); | ||||||
|  |                 Id = Form.get("id",""); | ||||||
|  |                 if(Password1!=Password2 || !AuthService()->ValidatePassword(Password2) || !AuthService()->ValidatePassword(Password1)) { | ||||||
|  |                     Poco::File  FormFile{ RESTAPI_Server()->AssetDir() + "/password_reset_error.html"}; | ||||||
|  |                     Types::StringPairVec    FormVars{ {"UUID", Id}, | ||||||
|  |                                                       {"ERROR_TEXT", "For some reason, the passwords entered do not match or they do not comply with" | ||||||
|  |                                                                      " accepted password creation restrictions. Please consult our on-line help" | ||||||
|  |                                                                      " to look at the our password policy. If you would like to contact us, please mention" | ||||||
|  |                                                                      " id(" + Id + ")"}}; | ||||||
|  |                     SendHTMLFileBack(FormFile,Request, Response, FormVars); | ||||||
|  |                     return; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 SecurityObjects::UserInfo   UInfo; | ||||||
|  |                 if(!Storage()->GetUserById(Id,UInfo)) { | ||||||
|  |                     Poco::File  FormFile{ RESTAPI_Server()->AssetDir() + "/password_reset_error.html"}; | ||||||
|  |                     Types::StringPairVec    FormVars{ {"UUID", Id}, | ||||||
|  |                                                       {"ERROR_TEXT", "This request does not contain a valid user ID. Please contact your system administrator."}}; | ||||||
|  |                     SendHTMLFileBack(FormFile,Request, Response, FormVars); | ||||||
|  |                     return; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 if(UInfo.blackListed || UInfo.suspended) { | ||||||
|  |                     Poco::File  FormFile{ RESTAPI_Server()->AssetDir() + "/password_reset_error.html"}; | ||||||
|  |                     Types::StringPairVec    FormVars{ {"UUID", Id}, | ||||||
|  |                                                       {"ERROR_TEXT", "Please contact our system administrators. We have identified an error in your account that must be resolved first."}}; | ||||||
|  |                     SendHTMLFileBack(FormFile,Request, Response, FormVars); | ||||||
|  |                     return; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 if(!AuthService()->SetPassword(Password1,UInfo)) { | ||||||
|  |                     Poco::File  FormFile{ RESTAPI_Server()->AssetDir() + "/password_reset_error.html"}; | ||||||
|  |                     Types::StringPairVec    FormVars{ {"UUID", Id}, | ||||||
|  |                                                       {"ERROR_TEXT", "You cannot reuse one of your recent passwords."}}; | ||||||
|  |                     SendHTMLFileBack(FormFile,Request, Response, FormVars); | ||||||
|  |                     return; | ||||||
|  |                 } | ||||||
|  |                 Storage()->UpdateUserInfo(UInfo.email,Id,UInfo); | ||||||
|  |                 Poco::File  FormFile{ RESTAPI_Server()->AssetDir() + "/password_reset_success.html"}; | ||||||
|  |                 Types::StringPairVec    FormVars{ {"UUID", Id}, | ||||||
|  |                                                   {"USERNAME", UInfo.email}, | ||||||
|  |                                                   {"ACTION_LINK",Daemon()->GetUIURI()}}; | ||||||
|  |                 SendHTMLFileBack(FormFile,Request, Response, FormVars); | ||||||
|  |             } | ||||||
|         } else { |         } else { | ||||||
|             DoReturnA404(); |             DoReturnA404(Request, Response); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void RESTAPI_action_links::DoEmailVerification(std::string &Id) { |     void RESTAPI_action_links::DoEmailVerification(std::string &Id,Poco::Net::HTTPServerRequest &Request, | ||||||
|         SecurityObjects::UserInfo UInfo; |                              Poco::Net::HTTPServerResponse &Response) { | ||||||
|  |         if(Request.getMethod()==Poco::Net::HTTPServerRequest::HTTP_GET) { | ||||||
|  |             SecurityObjects::UserInfo UInfo; | ||||||
|  |  | ||||||
|         Logger_.information(Poco::format("EMAIL-VERIFICATION(%s): For ID=%s", Request->clientAddress().toString(), Id)); |             if (!Storage()->GetUserById(Id, UInfo)) { | ||||||
|         if (!Storage()->GetUserById(Id, UInfo)) { |                 Types::StringPairVec FormVars{{"UUID",       Id}, | ||||||
|             Types::StringPairVec FormVars{{"UUID",       Id}, |                                               {"ERROR_TEXT", "This does not appear to be a valid email verification link.."}}; | ||||||
|                                           {"ERROR_TEXT", "This does not appear to be a valid email verification link.."}}; |                 Poco::File FormFile{RESTAPI_Server()->AssetDir() + "/email_verification_error.html"}; | ||||||
|             Poco::File FormFile{RESTAPI_Server()->AssetDir() + "/email_verification_error.html"}; |                 SendHTMLFileBack(FormFile, Request, Response, FormVars); | ||||||
|             SendHTMLFileBack(FormFile, FormVars); |                 return; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             UInfo.waitingForEmailCheck = false; | ||||||
|  |             UInfo.validated = true; | ||||||
|  |             UInfo.lastEmailCheck = std::time(nullptr); | ||||||
|  |             UInfo.validationDate = std::time(nullptr); | ||||||
|  |             Storage()->UpdateUserInfo(UInfo.email, Id, UInfo); | ||||||
|  |             Types::StringPairVec FormVars{{"UUID",     Id}, | ||||||
|  |                                           {"USERNAME", UInfo.email}, | ||||||
|  |                                           {"ACTION_LINK",Daemon()->GetUIURI()}}; | ||||||
|  |             Poco::File FormFile{RESTAPI_Server()->AssetDir() + "/email_verification_success.html"}; | ||||||
|  |             SendHTMLFileBack(FormFile, Request, Response, FormVars); | ||||||
|             return; |             return; | ||||||
|  |         } else { | ||||||
|  |             DoReturnA404(Request, Response); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         UInfo.waitingForEmailCheck = false; |  | ||||||
|         UInfo.validated = true; |  | ||||||
|         UInfo.lastEmailCheck = std::time(nullptr); |  | ||||||
|         UInfo.validationDate = std::time(nullptr); |  | ||||||
|         Storage()->UpdateUserInfo(UInfo.email, Id, UInfo); |  | ||||||
|         Types::StringPairVec FormVars{{"UUID",     Id}, |  | ||||||
|                                       {"USERNAME", UInfo.email}, |  | ||||||
|                                       {"ACTION_LINK",Daemon()->GetUIURI()}}; |  | ||||||
|         Poco::File FormFile{RESTAPI_Server()->AssetDir() + "/email_verification_success.html"}; |  | ||||||
|         SendHTMLFileBack(FormFile, FormVars); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void RESTAPI_action_links::DoReturnA404() { |     void RESTAPI_action_links::DoReturnA404(Poco::Net::HTTPServerRequest &Request, | ||||||
|  |                                             Poco::Net::HTTPServerResponse &Response) { | ||||||
|         Types::StringPairVec FormVars; |         Types::StringPairVec FormVars; | ||||||
|         Poco::File FormFile{RESTAPI_Server()->AssetDir() + "/404_error.html"}; |         Poco::File FormFile{RESTAPI_Server()->AssetDir() + "/404_error.html"}; | ||||||
|         SendHTMLFileBack(FormFile, FormVars); |         SendHTMLFileBack(FormFile, Request, Response, FormVars); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -15,28 +15,25 @@ | |||||||
| #include "Poco/StreamCopier.h" | #include "Poco/StreamCopier.h" | ||||||
| #include "Poco/CountingStream.h" | #include "Poco/CountingStream.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|     class RESTAPI_action_links : public RESTAPIHandler { |     class RESTAPI_action_links : public RESTAPIHandler { | ||||||
|     public: |     public: | ||||||
|         RESTAPI_action_links(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, bool Internal) |         RESTAPI_action_links(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, 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_POST, |                                                             Poco::Net::HTTPRequest::HTTP_POST, | ||||||
|                                         Poco::Net::HTTPRequest::HTTP_OPTIONS}, |                                                             Poco::Net::HTTPRequest::HTTP_OPTIONS}, | ||||||
|                                         Server, |                                                             Internal) {} | ||||||
|                                         Internal, |         void handleRequest(Poco::Net::HTTPServerRequest &Request, | ||||||
|                                         false) {} |                            Poco::Net::HTTPServerResponse &Response) override; | ||||||
|         static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/actionLink"}; }; |         static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/actionLink"}; }; | ||||||
|         void RequestResetPassword(std::string &Id); |         void DoResetPassword(std::string &Id,Poco::Net::HTTPServerRequest &Request, | ||||||
|         void CompleteResetPassword(std::string &Id); |                             Poco::Net::HTTPServerResponse &Response); | ||||||
|         void DoEmailVerification(std::string &Id); |         void DoEmailVerification(std::string &Id,Poco::Net::HTTPServerRequest &Request, | ||||||
|         void DoReturnA404(); |                             Poco::Net::HTTPServerResponse &Response); | ||||||
|  |         void DoReturnA404(Poco::Net::HTTPServerRequest &Request, | ||||||
|         void DoGet() final; |                           Poco::Net::HTTPServerResponse &Response); | ||||||
|         void DoPost() final; |  | ||||||
|         void DoDelete() final {}; |  | ||||||
|         void DoPut() final {}; |  | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ | |||||||
| #include "Utils.h" | #include "Utils.h" | ||||||
| #include "RESTAPI_protocol.h" | #include "RESTAPI_protocol.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|  |  | ||||||
|     void AvatarPartHandler::handlePart(const Poco::Net::MessageHeader &Header, std::istream &Stream) { |     void AvatarPartHandler::handlePart(const Poco::Net::MessageHeader &Header, std::istream &Stream) { | ||||||
|         FileType_ = Header.get(RESTAPI::Protocol::CONTENTTYPE, RESTAPI::Protocol::UNSPECIFIED); |         FileType_ = Header.get(RESTAPI::Protocol::CONTENTTYPE, RESTAPI::Protocol::UNSPECIFIED); | ||||||
| @@ -28,62 +28,98 @@ namespace OpenWifi { | |||||||
|         Length_ = InputStream.chars(); |         Length_ = InputStream.chars(); | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     void RESTAPI_avatarHandler::DoPost() { |     void RESTAPI_avatarHandler::handleRequest(Poco::Net::HTTPServerRequest &Request, | ||||||
|         std::string Id = GetBinding(RESTAPI::Protocol::ID, ""); |                                               Poco::Net::HTTPServerResponse &Response) { | ||||||
|         SecurityObjects::UserInfo UInfo; |         if (!ContinueProcessing(Request, Response)) | ||||||
|  |  | ||||||
|         if (Id.empty() || !Storage()->GetUserById(Id, UInfo)) { |  | ||||||
|             NotFound(); |  | ||||||
|             return; |             return; | ||||||
|         } |  | ||||||
|  |  | ||||||
|         //  if there is an avatar, just remove it... |         if (!IsAuthorized(Request, Response)) | ||||||
|         Storage()->DeleteAvatar(UserInfo_.userinfo.email,Id); |             return; | ||||||
|  |  | ||||||
|         Poco::TemporaryFile TmpFile; |         ParseParameters(Request); | ||||||
|         AvatarPartHandler partHandler(Id, Logger_, TmpFile); |         if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET) | ||||||
|  |             DoGet(Request, Response); | ||||||
|         Poco::Net::HTMLForm form(*Request, Request->stream(), partHandler); |         else if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_POST) | ||||||
|         Poco::JSON::Object Answer; |             DoPost(Request, Response); | ||||||
|         if (!partHandler.Name().empty() && partHandler.Length()<Daemon()->ConfigGetInt("openwifi.avatar.maxsize",2000000)) { |         else if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_DELETE) | ||||||
|             Answer.set(RESTAPI::Protocol::AVATARID, Id); |             DoDelete(Request, Response); | ||||||
|             Answer.set(RESTAPI::Protocol::ERRORCODE, 0); |         else | ||||||
|             Logger_.information(Poco::format("Uploaded avatar: %s Type: %s", partHandler.Name(), partHandler.ContentType())); |             BadRequest(Request, Response); | ||||||
|             Storage()->SetAvatar(UserInfo_.userinfo.email, |  | ||||||
|                                  Id, TmpFile, partHandler.ContentType(), partHandler.Name()); |  | ||||||
|         } else { |  | ||||||
|             Answer.set(RESTAPI::Protocol::AVATARID, Id); |  | ||||||
|             Answer.set(RESTAPI::Protocol::ERRORCODE, 13); |  | ||||||
|             Answer.set(RESTAPI::Protocol::ERRORTEXT, "Avatar upload could not complete."); |  | ||||||
|         } |  | ||||||
|         ReturnObject(Answer); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void RESTAPI_avatarHandler::DoGet() { |     void RESTAPI_avatarHandler::DoPost(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) { | ||||||
|         std::string Id = GetBinding(RESTAPI::Protocol::ID, ""); |         try { | ||||||
|         if (Id.empty()) { |             std::string Id = GetBinding(RESTAPI::Protocol::ID, ""); | ||||||
|             NotFound(); |             SecurityObjects::UserInfo UInfo; | ||||||
|             return; |  | ||||||
|  |             if (Id.empty() || !Storage()->GetUserById(Id, UInfo)) { | ||||||
|  |                 NotFound(Request, Response); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             //  if there is an avatar, just remove it... | ||||||
|  |             Storage()->DeleteAvatar(UserInfo_.userinfo.email,Id); | ||||||
|  |  | ||||||
|  |             Poco::TemporaryFile TmpFile; | ||||||
|  |             AvatarPartHandler partHandler(Id, Logger_, TmpFile); | ||||||
|  |  | ||||||
|  |             Poco::Net::HTMLForm form(Request, Request.stream(), partHandler); | ||||||
|  |             Poco::JSON::Object Answer; | ||||||
|  |             if (!partHandler.Name().empty() && partHandler.Length()<Daemon()->ConfigGetInt("ucentral.avatar.maxsize",2000000)) { | ||||||
|  |                 Answer.set(RESTAPI::Protocol::AVATARID, Id); | ||||||
|  |                 Answer.set(RESTAPI::Protocol::ERRORCODE, 0); | ||||||
|  |                 Logger_.information(Poco::format("Uploaded avatar: %s Type: %s", partHandler.Name(), partHandler.ContentType())); | ||||||
|  |                 Storage()->SetAvatar(UserInfo_.userinfo.email, | ||||||
|  |                                      Id, TmpFile, partHandler.ContentType(), partHandler.Name()); | ||||||
|  |             } else { | ||||||
|  |                 Answer.set(RESTAPI::Protocol::AVATARID, Id); | ||||||
|  |                 Answer.set(RESTAPI::Protocol::ERRORCODE, 13); | ||||||
|  |                 Answer.set(RESTAPI::Protocol::ERRORTEXT, "Avatar upload could not complete."); | ||||||
|  |             } | ||||||
|  |             ReturnObject(Request, Answer, Response); | ||||||
|  |         } catch (const Poco::Exception &E) { | ||||||
|  |             Logger_.log(E); | ||||||
|         } |         } | ||||||
|         Poco::TemporaryFile TempAvatar; |         BadRequest(Request, Response); | ||||||
|         std::string Type, Name; |  | ||||||
|         if (!Storage()->GetAvatar(UserInfo_.userinfo.email, Id, TempAvatar, Type, Name)) { |  | ||||||
|             NotFound(); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|         SendFile(TempAvatar, Type, Name); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void RESTAPI_avatarHandler::DoDelete() { |     void RESTAPI_avatarHandler::DoGet(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) { | ||||||
|         std::string Id = GetBinding(RESTAPI::Protocol::ID, ""); |         try { | ||||||
|         if (Id.empty()) { |             std::string Id = GetBinding(RESTAPI::Protocol::ID, ""); | ||||||
|             NotFound(); |             if (Id.empty()) { | ||||||
|  |                 NotFound(Request, Response); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             Poco::TemporaryFile TempAvatar; | ||||||
|  |             std::string Type, Name; | ||||||
|  |             if (!Storage()->GetAvatar(UserInfo_.userinfo.email, Id, TempAvatar, Type, Name)) { | ||||||
|  |                 NotFound(Request, Response); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             SendFile(TempAvatar, Type, Name, Request, Response); | ||||||
|             return; |             return; | ||||||
|  |         } catch (const Poco::Exception&E) { | ||||||
|  |             Logger_.log(E); | ||||||
|         } |         } | ||||||
|         if (!Storage()->DeleteAvatar(UserInfo_.userinfo.email, Id)) { |         BadRequest(Request, Response); | ||||||
|             NotFound(); |     } | ||||||
|  |  | ||||||
|  |     void RESTAPI_avatarHandler::DoDelete(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) { | ||||||
|  |         try { | ||||||
|  |             std::string Id = GetBinding(RESTAPI::Protocol::ID, ""); | ||||||
|  |             if (Id.empty()) { | ||||||
|  |                 NotFound(Request, Response); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             if (!Storage()->DeleteAvatar(UserInfo_.userinfo.email, Id)) { | ||||||
|  |                 NotFound(Request, Response); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             OK(Request, Response); | ||||||
|             return; |             return; | ||||||
|  |         } catch (const Poco::Exception &E) { | ||||||
|  |             Logger_.log(E); | ||||||
|         } |         } | ||||||
|         OK(); |         BadRequest(Request, Response); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ | |||||||
|  |  | ||||||
| #include "RESTAPI_handler.h" | #include "RESTAPI_handler.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|  |  | ||||||
|     class AvatarPartHandler : public Poco::Net::PartHandler { |     class AvatarPartHandler : public Poco::Net::PartHandler { | ||||||
|     public: |     public: | ||||||
| @@ -33,22 +33,26 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
|     class RESTAPI_avatarHandler : public RESTAPIHandler { |     class RESTAPI_avatarHandler : public RESTAPIHandler { | ||||||
|     public: |     public: | ||||||
|         RESTAPI_avatarHandler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, bool Internal) |         RESTAPI_avatarHandler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, 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_POST, |                                          Poco::Net::HTTPRequest::HTTP_POST, | ||||||
|                                          Poco::Net::HTTPRequest::HTTP_DELETE, |                                          Poco::Net::HTTPRequest::HTTP_DELETE, | ||||||
|                                          Poco::Net::HTTPRequest::HTTP_OPTIONS}, |                                          Poco::Net::HTTPRequest::HTTP_OPTIONS}, | ||||||
|                                          Server, |  | ||||||
|                                          Internal) {} |                                          Internal) {} | ||||||
|  |  | ||||||
|  |         void handleRequest(Poco::Net::HTTPServerRequest &Request, | ||||||
|  |                            Poco::Net::HTTPServerResponse &Response) override; | ||||||
|  |  | ||||||
|         static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/avatar/{id}"}; }; |         static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/avatar/{id}"}; }; | ||||||
|  |  | ||||||
|         void DoGet() final; |         void DoGet(     Poco::Net::HTTPServerRequest &Request, | ||||||
|         void DoPost() final; |                         Poco::Net::HTTPServerResponse &Response); | ||||||
|         void DoDelete() final; |         void DoPost(     Poco::Net::HTTPServerRequest &Request, | ||||||
|         void DoPut() final {}; |                         Poco::Net::HTTPServerResponse &Response); | ||||||
|  |         void DoDelete(     Poco::Net::HTTPServerRequest &Request, | ||||||
|  |                         Poco::Net::HTTPServerResponse &Response); | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| #endif //UCENTRALSEC_RESTAPI_AVATARHANDLER_H | #endif //UCENTRALSEC_RESTAPI_AVATARHANDLER_H | ||||||
|   | |||||||
| @@ -1,36 +0,0 @@ | |||||||
| // |  | ||||||
| // Created by stephane bourque on 2021-09-02. |  | ||||||
| // |  | ||||||
|  |  | ||||||
| #include "RESTAPI_email_handler.h" |  | ||||||
|  |  | ||||||
|  |  | ||||||
| #include "Poco/Exception.h" |  | ||||||
| #include "Poco/JSON/Parser.h" |  | ||||||
|  |  | ||||||
| #include "Daemon.h" |  | ||||||
| #include "SMTPMailerService.h" |  | ||||||
| #include "RESTAPI_errors.h" |  | ||||||
|  |  | ||||||
| namespace OpenWifi { |  | ||||||
|     void RESTAPI_email_handler::DoPost() { |  | ||||||
|         auto Obj = ParseStream(); |  | ||||||
|         if (Obj->has("subject") && |  | ||||||
|             Obj->has("from") && |  | ||||||
|             Obj->has("text") && |  | ||||||
|             Obj->has("recipients")) { |  | ||||||
|             auto   Recipients = Obj->getArray("recipients"); |  | ||||||
|             MessageAttributes Attrs; |  | ||||||
|             Attrs[RECIPIENT_EMAIL] = Recipients->get(0).toString(); |  | ||||||
|             Attrs[SUBJECT] = Obj->get("subject").toString(); |  | ||||||
|             Attrs[TEXT] = Obj->get("text").toString(); |  | ||||||
|             if(SMTPMailerService()->SendMessage(Recipients->get(0).toString(), "password_reset.txt", Attrs)) { |  | ||||||
|                 OK(); |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|             ReturnStatus(Poco::Net::HTTPResponse::HTTP_SERVICE_UNAVAILABLE); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|         BadRequest(RESTAPI::Errors::MissingOrInvalidParameters); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -1,28 +0,0 @@ | |||||||
| // |  | ||||||
| // Created by stephane bourque on 2021-09-02. |  | ||||||
| // |  | ||||||
|  |  | ||||||
| #ifndef OWSEC_RESTAPI_EMAIL_HANDLER_H |  | ||||||
| #define OWSEC_RESTAPI_EMAIL_HANDLER_H |  | ||||||
|  |  | ||||||
|  |  | ||||||
| #include "RESTAPI_handler.h" |  | ||||||
|  |  | ||||||
| namespace OpenWifi { |  | ||||||
|     class RESTAPI_email_handler : public RESTAPIHandler { |  | ||||||
|     public: |  | ||||||
|         RESTAPI_email_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, bool Internal) |  | ||||||
|         : RESTAPIHandler(bindings, L, |  | ||||||
|                          std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_POST, |  | ||||||
|                                                   Poco::Net::HTTPRequest::HTTP_OPTIONS}, |  | ||||||
|                                                   Server, |  | ||||||
|                                                   Internal) {} |  | ||||||
|         static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/email"};} |  | ||||||
|         void DoGet() final {}; |  | ||||||
|         void DoPost() final; |  | ||||||
|         void DoDelete() final {}; |  | ||||||
|         void DoPut() final {}; |  | ||||||
|     }; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #endif //OWSEC_RESTAPI_EMAIL_HANDLER_H |  | ||||||
| @@ -1,55 +0,0 @@ | |||||||
| // |  | ||||||
| // Created by stephane bourque on 2021-09-12. |  | ||||||
| // |  | ||||||
|  |  | ||||||
| #ifndef OWPROV_RESTAPI_ERRORS_H |  | ||||||
| #define OWPROV_RESTAPI_ERRORS_H |  | ||||||
|  |  | ||||||
| namespace OpenWifi::RESTAPI::Errors { |  | ||||||
|     static const std::string MissingUUID{"Missing UUID."}; |  | ||||||
|     static const std::string MissingSerialNumber{"Missing Serial Number."}; |  | ||||||
|     static const std::string InternalError{"Internal error. Please try later."}; |  | ||||||
|     static const std::string InvalidJSONDocument{"Invalid JSON document."}; |  | ||||||
|     static const std::string UnsupportedHTTPMethod{"Unsupported HTTP Method"}; |  | ||||||
|     static const std::string StillInUse{"Element still in use."}; |  | ||||||
|     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 ConfigBlockInvalid{"Configuration block type invalid."}; |  | ||||||
|     static const std::string UnknownId{"Unknown management policy."}; |  | ||||||
|     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 RecordNotUpdated{"Record could not be updated."}; |  | ||||||
|     static const std::string UnknownManagementPolicyUUID{"Unknown management policy UUID."}; |  | ||||||
|     static const std::string CannotDeleteRoot{"Root Entity cannot be removed, only modified."}; |  | ||||||
|     static const std::string MustCreateRootFirst{"Root entity must be created first."}; |  | ||||||
|     static const std::string ParentUUIDMustExist{"Parent UUID must exist."}; |  | ||||||
|     static const std::string ConfigurationMustExist{"Configuration must exist."}; |  | ||||||
|     static const std::string MissingOrInvalidParameters{"Invalid or missing parameters."}; |  | ||||||
|     static const std::string UnknownSerialNumber{"Unknown Serial Number."}; |  | ||||||
|     static const std::string InvalidSerialNumber{"Invalid Serial Number."}; |  | ||||||
|     static const std::string SerialNumberExists{"Serial Number already exists."}; |  | ||||||
|     static const std::string ValidNonRootUUID{"Must be a non-root, and valid UUID."}; |  | ||||||
|     static const std::string VenueMustExist{"Venue does not exist."}; |  | ||||||
|     static const std::string NotBoth{"You cannot specify both Entity and Venue"}; |  | ||||||
|     static const std::string EntityMustExist{"Entity must exist."}; |  | ||||||
|     static const std::string ParentOrEntityMustBeSet{"Parent or Entity must be set."}; |  | ||||||
|     static const std::string ContactMustExist{"Contact must exist."}; |  | ||||||
|     static const std::string LocationMustExist{"Location must exist."}; |  | ||||||
|     static const std::string OnlyWSSupported{"This endpoint only supports WebSocket."}; |  | ||||||
|     static const std::string SerialNumberMismatch{"Serial Number mismatch."}; |  | ||||||
|     static const std::string InvalidCommand{"Invalid command."}; |  | ||||||
|     static const std::string NoRecordsDeleted{"No records deleted."}; |  | ||||||
|     static const std::string DeviceNotConnected{"Device is not currently connected."}; |  | ||||||
|     static const std::string CannotCreateWS{"Telemetry system could not create WS endpoint. Please try again."}; |  | ||||||
|     static const std::string BothDeviceTypeRevision{"Both deviceType and revision must be set."}; |  | ||||||
|     static const std::string IdOrSerialEmpty{"SerialNumber and Id must not be empty."}; |  | ||||||
|     static const std::string MissingUserID{"Missing user ID."}; |  | ||||||
|     static const std::string IdMustBe0{"To create a user, you must set the ID to 0"}; |  | ||||||
|     static const std::string InvalidUserRole{"Invalid userRole."}; |  | ||||||
|     static const std::string InvalidEmailAddress{"Invalid email address."}; |  | ||||||
|     static const std::string InvalidPassword{"Invalid password."}; |  | ||||||
|     static const std::string PasswordRejected{"Password was rejected. This maybe an old password."}; |  | ||||||
|     static const std::string InvalidIPRanges{"Invalid IP range specifications."}; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #endif //OWPROV_RESTAPI_ERRORS_H |  | ||||||
| @@ -8,7 +8,6 @@ | |||||||
|  |  | ||||||
| #include <cctype> | #include <cctype> | ||||||
| #include <algorithm> | #include <algorithm> | ||||||
| #include <functional> |  | ||||||
| #include <iostream> | #include <iostream> | ||||||
| #include <iterator> | #include <iterator> | ||||||
| #include <future> | #include <future> | ||||||
| @@ -17,8 +16,6 @@ | |||||||
| #include "Poco/URI.h" | #include "Poco/URI.h" | ||||||
| #include "Poco/Net/OAuth20Credentials.h" | #include "Poco/Net/OAuth20Credentials.h" | ||||||
|  |  | ||||||
| #include "RESTAPI_errors.h" |  | ||||||
|  |  | ||||||
| #ifdef	TIP_SECURITY_SERVICE | #ifdef	TIP_SECURITY_SERVICE | ||||||
| #include "AuthService.h" | #include "AuthService.h" | ||||||
| #else | #else | ||||||
| @@ -30,53 +27,22 @@ | |||||||
| #include "Utils.h" | #include "Utils.h" | ||||||
| #include "Daemon.h" | #include "Daemon.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|  |  | ||||||
|     void RESTAPIHandler::handleRequest(Poco::Net::HTTPServerRequest &RequestIn, |  | ||||||
|                        Poco::Net::HTTPServerResponse &ResponseIn) { |  | ||||||
| 		try { |  | ||||||
| 			Request = &RequestIn; |  | ||||||
| 			Response = &ResponseIn; |  | ||||||
|  |  | ||||||
| 			if (!ContinueProcessing()) |  | ||||||
| 				return; |  | ||||||
|  |  | ||||||
| 			if (AlwaysAuthorize_ && !IsAuthorized()) |  | ||||||
| 				return; |  | ||||||
|  |  | ||||||
| 			ParseParameters(); |  | ||||||
| 			if (Request->getMethod() == Poco::Net::HTTPRequest::HTTP_GET) |  | ||||||
| 				DoGet(); |  | ||||||
| 			else if (Request->getMethod() == Poco::Net::HTTPRequest::HTTP_POST) |  | ||||||
| 				DoPost(); |  | ||||||
| 			else if (Request->getMethod() == Poco::Net::HTTPRequest::HTTP_DELETE) |  | ||||||
| 				DoDelete(); |  | ||||||
| 			else if (Request->getMethod() == Poco::Net::HTTPRequest::HTTP_PUT) |  | ||||||
| 				DoPut(); |  | ||||||
| 			else |  | ||||||
| 				BadRequest(RESTAPI::Errors::UnsupportedHTTPMethod); |  | ||||||
| 			return; |  | ||||||
| 		} catch (const Poco::Exception &E) { |  | ||||||
| 			Logger_.log(E); |  | ||||||
| 			BadRequest(RESTAPI::Errors::InternalError); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
|     const Poco::JSON::Object::Ptr &RESTAPIHandler::ParseStream() { |  | ||||||
|         return IncomingParser_.parse(Request->stream()).extract<Poco::JSON::Object::Ptr>(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| 	bool RESTAPIHandler::ParseBindings(const std::string & Request, const std::list<const char *> & EndPoints, BindingMap &bindings) { | 	bool RESTAPIHandler::ParseBindings(const std::string & Request, const std::list<const char *> & EndPoints, BindingMap &bindings) { | ||||||
|  | 		std::string Param, Value; | ||||||
|  |  | ||||||
| 		bindings.clear(); | 		bindings.clear(); | ||||||
| 		std::vector<std::string> PathItems = Utils::Split(Request, '/'); | 		std::vector<std::string> PathItems = uCentral::Utils::Split(Request, '/'); | ||||||
|  |  | ||||||
| 		for(const auto &EndPoint:EndPoints) { | 		for(const auto &EndPoint:EndPoints) { | ||||||
| 			std::vector<std::string> ParamItems = Utils::Split(EndPoint, '/'); | 			std::vector<std::string> ParamItems = uCentral::Utils::Split(EndPoint, '/'); | ||||||
| 			if (PathItems.size() != ParamItems.size()) | 			if (PathItems.size() != ParamItems.size()) | ||||||
| 				continue; | 				continue; | ||||||
|  |  | ||||||
| 			bool Matched = true; | 			bool Matched = true; | ||||||
| 			for (auto i = 0; i != PathItems.size() && Matched; i++) { | 			for (auto i = 0; i != PathItems.size() && Matched; i++) { | ||||||
|  | 				// std::cout << "PATH:" << PathItems[i] << "  ENDPOINT:" << ParamItems[i] << std::endl; | ||||||
| 				if (PathItems[i] != ParamItems[i]) { | 				if (PathItems[i] != ParamItems[i]) { | ||||||
| 					if (ParamItems[i][0] == '{') { | 					if (ParamItems[i][0] == '{') { | ||||||
| 						auto ParamName = ParamItems[i].substr(1, ParamItems[i].size() - 2); | 						auto ParamName = ParamItems[i].substr(1, ParamItems[i].size() - 2); | ||||||
| @@ -93,14 +59,14 @@ namespace OpenWifi { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	void RESTAPIHandler::PrintBindings() { | 	void RESTAPIHandler::PrintBindings() { | ||||||
| 		for (const auto &[key, value] : Bindings_) | 		for (auto &[key, value] : Bindings_) | ||||||
| 			std::cout << "Key = " << key << "  Value= " << value << std::endl; | 			std::cout << "Key = " << key << "  Value= " << value << std::endl; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	void RESTAPIHandler::ParseParameters() { | 	void RESTAPIHandler::ParseParameters(Poco::Net::HTTPServerRequest &request) { | ||||||
| 		Poco::URI uri(Request->getURI()); |  | ||||||
|  | 		Poco::URI uri(request.getURI()); | ||||||
| 		Parameters_ = uri.getQueryParameters(); | 		Parameters_ = uri.getQueryParameters(); | ||||||
| 		InitQueryBlock(); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	static bool is_number(const std::string &s) { | 	static bool is_number(const std::string &s) { | ||||||
| @@ -114,40 +80,35 @@ namespace OpenWifi { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	uint64_t RESTAPIHandler::GetParameter(const std::string &Name, const uint64_t Default) { | 	uint64_t RESTAPIHandler::GetParameter(const std::string &Name, const uint64_t Default) { | ||||||
|         auto Hint = std::find_if(Parameters_.begin(),Parameters_.end(),[Name](const std::pair<std::string,std::string> &S){ return S.first==Name; }); |  | ||||||
|         if(Hint==Parameters_.end() || !is_number(Hint->second)) | 		for (const auto &i : Parameters_) { | ||||||
|             return Default; | 			if (i.first == Name) { | ||||||
|         return std::stoull(Hint->second); | 				if (!is_number(i.second)) | ||||||
|  | 					return Default; | ||||||
|  | 				return std::stoi(i.second); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return Default; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	bool RESTAPIHandler::GetBoolParameter(const std::string &Name, bool Default) { | 	bool RESTAPIHandler::GetBoolParameter(const std::string &Name, bool Default) { | ||||||
|         auto Hint = std::find_if(begin(Parameters_),end(Parameters_),[Name](const std::pair<std::string,std::string> &S){ return S.first==Name; }); |  | ||||||
|         if(Hint==end(Parameters_) || !is_bool(Hint->second)) | 		for (const auto &i : Parameters_) { | ||||||
|             return Default; | 			if (i.first == Name) { | ||||||
| 		return Hint->second=="true"; | 				if (!is_bool(i.second)) | ||||||
|  | 					return Default; | ||||||
|  | 				return i.second == "true"; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return Default; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	std::string RESTAPIHandler::GetParameter(const std::string &Name, const std::string &Default) { | 	std::string RESTAPIHandler::GetParameter(const std::string &Name, const std::string &Default) { | ||||||
|         auto Hint = std::find_if(begin(Parameters_),end(Parameters_),[Name](const std::pair<std::string,std::string> &S){ return S.first==Name; }); | 		for (const auto &i : Parameters_) { | ||||||
|         if(Hint==end(Parameters_)) | 			if (i.first == Name) | ||||||
|             return Default; | 				return i.second; | ||||||
|         return Hint->second; | 		} | ||||||
| 	} | 		return Default; | ||||||
|  |  | ||||||
| 	bool RESTAPIHandler::HasParameter(const std::string &Name, std::string &Value) { |  | ||||||
|         auto Hint = std::find_if(begin(Parameters_),end(Parameters_),[Name](const std::pair<std::string,std::string> &S){ return S.first==Name; }); |  | ||||||
|         if(Hint==end(Parameters_)) |  | ||||||
|             return false; |  | ||||||
|         Value = Hint->second; |  | ||||||
|         return true; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	bool RESTAPIHandler::HasParameter(const std::string &Name, uint64_t & Value) { |  | ||||||
|         auto Hint = std::find_if(begin(Parameters_),end(Parameters_),[Name](const std::pair<std::string,std::string> &S){ return S.first==Name; }); |  | ||||||
|         if(Hint==end(Parameters_)) |  | ||||||
|             return false; |  | ||||||
|         Value = std::stoull(Hint->second); |  | ||||||
|         return true; |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	const std::string &RESTAPIHandler::GetBinding(const std::string &Name, const std::string &Default) { | 	const std::string &RESTAPIHandler::GetBinding(const std::string &Name, const std::string &Default) { | ||||||
| @@ -169,225 +130,202 @@ namespace OpenWifi { | |||||||
| 		return Return; | 		return Return; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	bool RESTAPIHandler::AssignIfPresent(const Poco::JSON::Object::Ptr &O, const std::string &Field, std::string &Value) { | 	void RESTAPIHandler::AddCORS(Poco::Net::HTTPServerRequest &Request, | ||||||
| 	    if(O->has(Field)) { | 								 Poco::Net::HTTPServerResponse &Response) { | ||||||
| 	        Value = O->get(Field).toString(); | 		auto Origin = Request.find("Origin"); | ||||||
| 	        return true; | 		if (Origin != Request.end()) { | ||||||
| 	    } | 			Response.set("Access-Control-Allow-Origin", Origin->second); | ||||||
| 	    return false; | 			Response.set("Vary", "Origin"); | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	bool RESTAPIHandler::AssignIfPresent(const Poco::JSON::Object::Ptr &O, const std::string &Field, uint64_t &Value) { |  | ||||||
| 	    if(O->has(Field)) { |  | ||||||
| 	        Value = O->get(Field); |  | ||||||
| 	        return true; |  | ||||||
| 	    } |  | ||||||
| 	    return false; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	void RESTAPIHandler::AddCORS() { |  | ||||||
| 		auto Origin = Request->find("Origin"); |  | ||||||
| 		if (Origin != Request->end()) { |  | ||||||
| 			Response->set("Access-Control-Allow-Origin", Origin->second); |  | ||||||
| 			Response->set("Vary", "Origin"); |  | ||||||
| 		} else { | 		} else { | ||||||
| 			Response->set("Access-Control-Allow-Origin", "*"); | 			Response.set("Access-Control-Allow-Origin", "*"); | ||||||
| 		} | 		} | ||||||
| 		Response->set("Access-Control-Allow-Headers", "*"); | 		Response.set("Access-Control-Allow-Headers", "*"); | ||||||
| 		Response->set("Access-Control-Allow-Methods", MakeList(Methods_)); | 		Response.set("Access-Control-Allow-Methods", MakeList(Methods_)); | ||||||
| 		Response->set("Access-Control-Max-Age", "86400"); | 		Response.set("Access-Control-Max-Age", "86400"); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	void RESTAPIHandler::SetCommonHeaders(bool CloseConnection) { | 	void RESTAPIHandler::SetCommonHeaders(Poco::Net::HTTPServerResponse &Response, bool CloseConnection) { | ||||||
| 		Response->setVersion(Poco::Net::HTTPMessage::HTTP_1_1); | 		Response.setVersion(Poco::Net::HTTPMessage::HTTP_1_1); | ||||||
| 		Response->setChunkedTransferEncoding(true); | 		Response.setChunkedTransferEncoding(true); | ||||||
| 		Response->setContentType("application/json"); | 		Response.setContentType("application/json"); | ||||||
| 		if(CloseConnection) { | 		if(CloseConnection) { | ||||||
| 			Response->set("Connection", "close"); | 			Response.set("Connection", "close"); | ||||||
| 			Response->setKeepAlive(false); | 			Response.setKeepAlive(false); | ||||||
| 		} else { | 		} else { | ||||||
| 			Response->setKeepAlive(true); | 			Response.setKeepAlive(true); | ||||||
| 			Response->set("Connection", "Keep-Alive"); | 			Response.set("Connection", "Keep-Alive"); | ||||||
| 			Response->set("Keep-Alive", "timeout=5, max=1000"); | 			Response.set("Keep-Alive", "timeout=5, max=1000"); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	void RESTAPIHandler::ProcessOptions() { | 	void RESTAPIHandler::ProcessOptions(Poco::Net::HTTPServerRequest &Request, | ||||||
| 		AddCORS(); | 										Poco::Net::HTTPServerResponse &Response) { | ||||||
| 		SetCommonHeaders(); | 		AddCORS(Request, Response); | ||||||
| 		Response->setContentLength(0); | 		SetCommonHeaders(Response); | ||||||
| 		Response->set("Access-Control-Allow-Credentials", "true"); | 		Response.setContentLength(0); | ||||||
| 		Response->setStatus(Poco::Net::HTTPResponse::HTTP_OK); | 		Response.set("Access-Control-Allow-Credentials", "true"); | ||||||
| 		Response->set("Vary", "Origin, Access-Control-Request-Headers, Access-Control-Request-Method"); | 		Response.setStatus(Poco::Net::HTTPResponse::HTTP_OK); | ||||||
| 		Response->send(); | 		Response.set("Vary", "Origin, Access-Control-Request-Headers, Access-Control-Request-Method"); | ||||||
|  | 		/*	std::cout << "RESPONSE:" << std::endl; | ||||||
|  | 			for(const auto &[f,s]:Response) | ||||||
|  | 				std::cout << "First: " << f << " second:" << s << std::endl; | ||||||
|  | 		*/ | ||||||
|  | 		Response.send(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	void RESTAPIHandler::PrepareResponse( Poco::Net::HTTPResponse::HTTPStatus Status, | 	void RESTAPIHandler::PrepareResponse(Poco::Net::HTTPServerRequest &Request, | ||||||
|  | 										 Poco::Net::HTTPServerResponse &Response, | ||||||
|  | 										 Poco::Net::HTTPResponse::HTTPStatus Status, | ||||||
| 										 bool CloseConnection) { | 										 bool CloseConnection) { | ||||||
| 		Response->setStatus(Status); | 		Response.setStatus(Status); | ||||||
| 		AddCORS(); | 		AddCORS(Request, Response); | ||||||
| 		SetCommonHeaders(CloseConnection); | 		SetCommonHeaders(Response, CloseConnection); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	void RESTAPIHandler::BadRequest(const std::string & Reason) { | 	void RESTAPIHandler::BadRequest(Poco::Net::HTTPServerRequest &Request, | ||||||
| 		PrepareResponse(Poco::Net::HTTPResponse::HTTP_BAD_REQUEST); | 									Poco::Net::HTTPServerResponse &Response, | ||||||
|  | 									const std::string & Reason) { | ||||||
|  | 		PrepareResponse(Request, Response, Poco::Net::HTTPResponse::HTTP_BAD_REQUEST); | ||||||
| 		Poco::JSON::Object	ErrorObject; | 		Poco::JSON::Object	ErrorObject; | ||||||
| 		ErrorObject.set("ErrorCode",400); | 		ErrorObject.set("ErrorCode",500); | ||||||
| 		ErrorObject.set("ErrorDetails",Request->getMethod()); | 		ErrorObject.set("ErrorDetails",Request.getMethod()); | ||||||
| 		ErrorObject.set("ErrorDescription",Reason.empty() ? "Command is missing parameters or wrong values." : Reason) ; | 		ErrorObject.set("ErrorDescription",Reason.empty() ? "Command is missing parameters or wrong values." : Reason) ; | ||||||
| 		std::ostream &Answer = Response->send(); | 		std::ostream &Answer = Response.send(); | ||||||
| 		Poco::JSON::Stringifier::stringify(ErrorObject, Answer); | 		Poco::JSON::Stringifier::stringify(ErrorObject, Answer); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	void RESTAPIHandler::InternalError(const std::string & Reason) { | 	void RESTAPIHandler::UnAuthorized(Poco::Net::HTTPServerRequest &Request, | ||||||
|         PrepareResponse(Poco::Net::HTTPResponse::HTTP_INTERNAL_SERVER_ERROR); | 									  Poco::Net::HTTPServerResponse &Response, | ||||||
|         Poco::JSON::Object	ErrorObject; |                                       const std::string & Reason) { | ||||||
|         ErrorObject.set("ErrorCode",500); | 		PrepareResponse(Request, Response, Poco::Net::HTTPResponse::HTTP_FORBIDDEN); | ||||||
|         ErrorObject.set("ErrorDetails",Request->getMethod()); |  | ||||||
|         ErrorObject.set("ErrorDescription",Reason.empty() ? "Please try later or review the data submitted." : Reason) ; |  | ||||||
|         std::ostream &Answer = Response->send(); |  | ||||||
|         Poco::JSON::Stringifier::stringify(ErrorObject, Answer); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| 	void RESTAPIHandler::UnAuthorized(const std::string & Reason) { |  | ||||||
| 		PrepareResponse(Poco::Net::HTTPResponse::HTTP_FORBIDDEN); |  | ||||||
| 		Poco::JSON::Object	ErrorObject; | 		Poco::JSON::Object	ErrorObject; | ||||||
| 		ErrorObject.set("ErrorCode",403); | 		ErrorObject.set("ErrorCode",403); | ||||||
| 		ErrorObject.set("ErrorDetails",Request->getMethod()); | 		ErrorObject.set("ErrorDetails",Request.getMethod()); | ||||||
| 		ErrorObject.set("ErrorDescription",Reason.empty() ? "No access allowed." : Reason) ; | 		ErrorObject.set("ErrorDescription",Reason.empty() ? "No access allowed." : Reason) ; | ||||||
| 		std::ostream &Answer = Response->send(); | 		std::ostream &Answer = Response.send(); | ||||||
| 		Poco::JSON::Stringifier::stringify(ErrorObject, Answer); | 		Poco::JSON::Stringifier::stringify(ErrorObject, Answer); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	void RESTAPIHandler::NotFound() { | 	void RESTAPIHandler::NotFound(Poco::Net::HTTPServerRequest &Request, | ||||||
| 		PrepareResponse(Poco::Net::HTTPResponse::HTTP_NOT_FOUND); | 								  Poco::Net::HTTPServerResponse &Response) { | ||||||
|  | 		PrepareResponse(Request, Response, Poco::Net::HTTPResponse::HTTP_NOT_FOUND); | ||||||
| 		Poco::JSON::Object	ErrorObject; | 		Poco::JSON::Object	ErrorObject; | ||||||
| 		ErrorObject.set("ErrorCode",404); | 		ErrorObject.set("ErrorCode",404); | ||||||
| 		ErrorObject.set("ErrorDetails",Request->getMethod()); | 		ErrorObject.set("ErrorDetails",Request.getMethod()); | ||||||
| 		ErrorObject.set("ErrorDescription","This resource does not exist."); | 		ErrorObject.set("ErrorDescription","This resource does not exist."); | ||||||
| 		std::ostream &Answer = Response->send(); | 		std::ostream &Answer = Response.send(); | ||||||
| 		Poco::JSON::Stringifier::stringify(ErrorObject, Answer); | 		Poco::JSON::Stringifier::stringify(ErrorObject, Answer); | ||||||
| 		Logger_.debug(Poco::format("RES-NOTFOUND: User='%s' Method='%s' Path='%s", |  | ||||||
|                                    Utils::FormatIPv6(Request->clientAddress().toString()), |  | ||||||
|                                    Request->getMethod(), |  | ||||||
|                                    Request->getURI())); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	void RESTAPIHandler::OK() { | 	void RESTAPIHandler::OK(Poco::Net::HTTPServerRequest &Request, | ||||||
| 		PrepareResponse(); | 							Poco::Net::HTTPServerResponse &Response) { | ||||||
| 		if(	Request->getMethod()==Poco::Net::HTTPRequest::HTTP_DELETE || | 		PrepareResponse(Request, Response); | ||||||
| 			Request->getMethod()==Poco::Net::HTTPRequest::HTTP_OPTIONS) { | 		if(	Request.getMethod()==Poco::Net::HTTPRequest::HTTP_DELETE || | ||||||
| 			Response->send(); | 			Request.getMethod()==Poco::Net::HTTPRequest::HTTP_OPTIONS) { | ||||||
|  | 			Response.send(); | ||||||
| 		} else { | 		} else { | ||||||
| 			Poco::JSON::Object ErrorObject; | 			Poco::JSON::Object ErrorObject; | ||||||
| 			ErrorObject.set("Code", 0); | 			ErrorObject.set("Code", 0); | ||||||
| 			ErrorObject.set("Operation", Request->getMethod()); | 			ErrorObject.set("Operation", Request.getMethod()); | ||||||
| 			ErrorObject.set("Details", "Command completed."); | 			ErrorObject.set("Details", "Command completed."); | ||||||
| 			std::ostream &Answer = Response->send(); | 			std::ostream &Answer = Response.send(); | ||||||
| 			Poco::JSON::Stringifier::stringify(ErrorObject, Answer); | 			Poco::JSON::Stringifier::stringify(ErrorObject, Answer); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	void RESTAPIHandler::SendFile(Poco::File & File, const std::string & UUID) { | 	void RESTAPIHandler::SendFile(Poco::File & File, const std::string & UUID, Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) { | ||||||
| 		Response->set("Content-Type","application/octet-stream"); | 		Response.set("Content-Type","application/octet-stream"); | ||||||
| 		Response->set("Content-Disposition", "attachment; filename=" + UUID ); | 		Response.set("Content-Disposition", "attachment; filename=" + UUID ); | ||||||
| 		Response->set("Content-Transfer-Encoding","binary"); | 		Response.set("Content-Transfer-Encoding","binary"); | ||||||
| 		Response->set("Accept-Ranges", "bytes"); | 		Response.set("Accept-Ranges", "bytes"); | ||||||
| 		Response->set("Cache-Control", "private"); | 		Response.set("Cache-Control", "private"); | ||||||
| 		Response->set("Pragma", "private"); | 		Response.set("Pragma", "private"); | ||||||
| 		Response->set("Expires", "Mon, 26 Jul 2027 05:00:00 GMT"); | 		Response.set("Expires", "Mon, 26 Jul 2027 05:00:00 GMT"); | ||||||
| 		Response->set("Content-Length", std::to_string(File.getSize())); | 		Response.set("Content-Length", std::to_string(File.getSize())); | ||||||
| 		AddCORS(); | 		AddCORS(Request, Response); | ||||||
| 		Response->sendFile(File.path(),"application/octet-stream"); | 		Response.sendFile(File.path(),"application/octet-stream"); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|     void RESTAPIHandler::SendFile(Poco::File & File) { |     void RESTAPIHandler::SendFile(Poco::File & File, Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) { | ||||||
|         Poco::Path  P(File.path()); |         Poco::Path  P(File.path()); | ||||||
|         auto MT = Utils::FindMediaType(File); |         auto MT = Utils::FindMediaType(File); | ||||||
|         if(MT.Encoding==Utils::BINARY) { |         if(MT.Encoding==Utils::BINARY) { | ||||||
|             Response->set("Content-Transfer-Encoding","binary"); |             Response.set("Content-Transfer-Encoding","binary"); | ||||||
|             Response->set("Accept-Ranges", "bytes"); |             Response.set("Accept-Ranges", "bytes"); | ||||||
|         } |         } | ||||||
|         Response->set("Cache-Control", "private"); |         Response.set("Cache-Control", "private"); | ||||||
|         Response->set("Pragma", "private"); |         Response.set("Pragma", "private"); | ||||||
|         Response->set("Expires", "Mon, 26 Jul 2027 05:00:00 GMT"); |         Response.set("Expires", "Mon, 26 Jul 2027 05:00:00 GMT"); | ||||||
|         AddCORS(); |         AddCORS(Request, Response); | ||||||
|         Response->sendFile(File.path(),MT.ContentType); |         Response.sendFile(File.path(),MT.ContentType); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void RESTAPIHandler::SendFile(Poco::TemporaryFile &TempAvatar, const std::string &Type, const std::string & Name) { |     void RESTAPIHandler::SendFile(Poco::TemporaryFile &TempAvatar, const std::string &Type, const std::string & Name, Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) { | ||||||
|         auto MT = Utils::FindMediaType(Name); |         auto MT = Utils::FindMediaType(Name); | ||||||
|         if(MT.Encoding==Utils::BINARY) { |         if(MT.Encoding==Utils::BINARY) { | ||||||
|             Response->set("Content-Transfer-Encoding","binary"); |             Response.set("Content-Transfer-Encoding","binary"); | ||||||
|             Response->set("Accept-Ranges", "bytes"); |             Response.set("Accept-Ranges", "bytes"); | ||||||
|         } |         } | ||||||
|         Response->set("Content-Disposition", "attachment; filename=" + Name ); |         Response.set("Content-Disposition", "attachment; filename=" + Name ); | ||||||
|         Response->set("Accept-Ranges", "bytes"); |         Response.set("Accept-Ranges", "bytes"); | ||||||
|         Response->set("Cache-Control", "private"); |         Response.set("Cache-Control", "private"); | ||||||
|         Response->set("Pragma", "private"); |         Response.set("Pragma", "private"); | ||||||
|         Response->set("Expires", "Mon, 26 Jul 2027 05:00:00 GMT"); |         Response.set("Expires", "Mon, 26 Jul 2027 05:00:00 GMT"); | ||||||
|         AddCORS(); |         AddCORS(Request, Response); | ||||||
|         Response->sendFile(TempAvatar.path(),MT.ContentType); |         Response.sendFile(TempAvatar.path(),MT.ContentType); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|     void RESTAPIHandler::SendHTMLFileBack(Poco::File & File, |     void RESTAPIHandler::SendHTMLFileBack(Poco::File & File, | ||||||
|  |                           Poco::Net::HTTPServerRequest &Request, | ||||||
|  |                           Poco::Net::HTTPServerResponse &Response , | ||||||
|                           const Types::StringPairVec & FormVars) { |                           const Types::StringPairVec & FormVars) { | ||||||
|         Response->set("Pragma", "private"); |         Response.set("Pragma", "private"); | ||||||
|         Response->set("Expires", "Mon, 26 Jul 2027 05:00:00 GMT"); |         Response.set("Expires", "Mon, 26 Jul 2027 05:00:00 GMT"); | ||||||
|         Response->set("Content-Length", std::to_string(File.getSize())); |         Response.set("Content-Length", std::to_string(File.getSize())); | ||||||
|         AddCORS(); |         AddCORS(Request, Response); | ||||||
|         auto FormContent = Utils::LoadFile(File.path()); |         auto FormContent = Utils::LoadFile(File.path()); | ||||||
|         Utils::ReplaceVariables(FormContent, FormVars); |         Utils::ReplaceVariables(FormContent, FormVars); | ||||||
|         Response->setChunkedTransferEncoding(true); |         Response.setChunkedTransferEncoding(true); | ||||||
|         Response->setContentType("text/html"); |         Response.setContentType("text/html"); | ||||||
|         std::ostream& ostr = Response->send(); |         std::ostream& ostr = Response.send(); | ||||||
|         ostr << FormContent; |         ostr << FormContent; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|     void RESTAPIHandler::ReturnStatus(Poco::Net::HTTPResponse::HTTPStatus Status, bool CloseConnection) { |     void RESTAPIHandler::ReturnStatus(Poco::Net::HTTPServerRequest &Request, | ||||||
| 		PrepareResponse(Status, CloseConnection); | 									  Poco::Net::HTTPServerResponse &Response, | ||||||
|  | 									  Poco::Net::HTTPResponse::HTTPStatus Status, | ||||||
|  | 									  bool CloseConnection) { | ||||||
|  | 		PrepareResponse(Request, Response, Status, CloseConnection); | ||||||
| 		if(Status == Poco::Net::HTTPResponse::HTTP_NO_CONTENT) { | 		if(Status == Poco::Net::HTTPResponse::HTTP_NO_CONTENT) { | ||||||
| 			Response->setContentLength(0); | 			Response.setContentLength(0); | ||||||
| 			Response->erase("Content-Type"); | 			Response.erase("Content-Type"); | ||||||
| 			Response->setChunkedTransferEncoding(false); | 			Response.setChunkedTransferEncoding(false); | ||||||
| 		} | 		} | ||||||
| 		Response->send(); | 		Response.send(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	bool RESTAPIHandler::ContinueProcessing() { | 	bool RESTAPIHandler::ContinueProcessing(Poco::Net::HTTPServerRequest &Request, | ||||||
| 		if (Request->getMethod() == Poco::Net::HTTPRequest::HTTP_OPTIONS) { | 											Poco::Net::HTTPServerResponse &Response) { | ||||||
| 			ProcessOptions(); | 		if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_OPTIONS) { | ||||||
|  | 			ProcessOptions(Request, Response); | ||||||
| 			return false; | 			return false; | ||||||
| 		} else if (std::find(Methods_.begin(), Methods_.end(), Request->getMethod()) == Methods_.end()) { | 		} else if (std::find(Methods_.begin(), Methods_.end(), Request.getMethod()) == Methods_.end()) { | ||||||
| 			BadRequest(RESTAPI::Errors::UnsupportedHTTPMethod); | 			BadRequest(Request, Response); | ||||||
| 			return false; | 			return false; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		return true; | 		return true; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	bool RESTAPIHandler::IsAuthorized() { | 	bool RESTAPIHandler::IsAuthorized(Poco::Net::HTTPServerRequest &Request, | ||||||
|  | 									  Poco::Net::HTTPServerResponse &Response) { | ||||||
| 	    if(Internal_) { | 	    if(Internal_) { | ||||||
| 	        auto Allowed = Daemon()->IsValidAPIKEY(*Request); | 	        return Daemon()->IsValidAPIKEY(Request); | ||||||
| 	        if(!Allowed) { |  | ||||||
| 	            if(Server_.LogBadTokens(false)) { |  | ||||||
| 	                Logger_.debug(Poco::format("I-REQ-DENIED(%s): Method='%s' Path='%s", |  | ||||||
|                                                Utils::FormatIPv6(Request->clientAddress().toString()), |  | ||||||
|                                                Request->getMethod(), Request->getURI())); |  | ||||||
| 	            } |  | ||||||
| 	        } else { |  | ||||||
| 	            auto Id = Request->get("X-INTERNAL-NAME", "unknown"); |  | ||||||
| 	            if(Server_.LogIt(Request->getMethod(),true)) { |  | ||||||
| 	                Logger_.debug(Poco::format("I-REQ-ALLOWED(%s): User='%s' Method='%s' Path='%s", |  | ||||||
|                                                Utils::FormatIPv6(Request->clientAddress().toString()), Id, |  | ||||||
|                                                Request->getMethod(), Request->getURI())); |  | ||||||
| 	            } |  | ||||||
| 	        } |  | ||||||
|             return Allowed; |  | ||||||
| 	    } else { | 	    } else { | ||||||
|             if (SessionToken_.empty()) { |             if (SessionToken_.empty()) { | ||||||
|                 try { |                 try { | ||||||
|                     Poco::Net::OAuth20Credentials Auth(*Request); |                     Poco::Net::OAuth20Credentials Auth(Request); | ||||||
|  |  | ||||||
|                     if (Auth.getScheme() == "Bearer") { |                     if (Auth.getScheme() == "Bearer") { | ||||||
|                         SessionToken_ = Auth.getBearerToken(); |                         SessionToken_ = Auth.getBearerToken(); | ||||||
|                     } |                     } | ||||||
| @@ -396,63 +334,48 @@ namespace OpenWifi { | |||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| #ifdef    TIP_SECURITY_SERVICE | #ifdef    TIP_SECURITY_SERVICE | ||||||
|             if (AuthService()->IsAuthorized(*Request, SessionToken_, UserInfo_)) { |             if (AuthService()->IsAuthorized(Request, SessionToken_, UserInfo_)) { | ||||||
| #else | #else | ||||||
|             if (AuthClient()->IsAuthorized(*Request, SessionToken_, UserInfo_)) { |             if (AuthClient()->IsAuthorized(Request, SessionToken_, UserInfo_)) { | ||||||
| #endif | #endif | ||||||
|                 if(Server_.LogIt(Request->getMethod(),true)) { |  | ||||||
|                     Logger_.debug(Poco::format("X-REQ-ALLOWED(%s): User='%s@%s' Method='%s' Path='%s", |  | ||||||
|                          Utils::FormatIPv6(Request->clientAddress().toString()), |  | ||||||
|                          UserInfo_.userinfo.email, |  | ||||||
|                          Request->clientAddress().toString(), |  | ||||||
|                          Request->getMethod(), |  | ||||||
|                          Request->getURI())); |  | ||||||
|                 } |  | ||||||
|                 return true; |                 return true; | ||||||
|             } else { |             } else { | ||||||
|                 if(Server_.LogBadTokens(true)) { |                 UnAuthorized(Request, Response); | ||||||
|                     Logger_.debug(Poco::format("X-REQ-DENIED(%s): Method='%s' Path='%s", |  | ||||||
|                          Utils::FormatIPv6(Request->clientAddress().toString()), |  | ||||||
|                          Request->getMethod(), Request->getURI())); |  | ||||||
|                 } |  | ||||||
|                 UnAuthorized(); |  | ||||||
|             } |             } | ||||||
|             return false; |             return false; | ||||||
|         } |         } | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	void RESTAPIHandler::ReturnObject(Poco::JSON::Object &Object) { | /* | ||||||
| 		PrepareResponse(); | 	bool RESTAPIHandler::ValidateAPIKey(Poco::Net::HTTPServerRequest &Request, | ||||||
| 		std::ostream &Answer = Response->send(); | 										Poco::Net::HTTPServerResponse &Response) { | ||||||
|  | 		auto Key = Request.get("X-API-KEY", ""); | ||||||
|  |  | ||||||
|  | 		if (Key.empty()) | ||||||
|  | 			return false; | ||||||
|  |  | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | */ | ||||||
|  | 	void RESTAPIHandler::ReturnObject(Poco::Net::HTTPServerRequest &Request, Poco::JSON::Object &Object, | ||||||
|  | 									  Poco::Net::HTTPServerResponse &Response) { | ||||||
|  | 		PrepareResponse(Request, Response); | ||||||
|  | 		std::ostream &Answer = Response.send(); | ||||||
| 		Poco::JSON::Stringifier::stringify(Object, Answer); | 		Poco::JSON::Stringifier::stringify(Object, Answer); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	void RESTAPIHandler::ReturnCountOnly(uint64_t Count) { | 	void RESTAPIHandler::InitQueryBlock() { | ||||||
| 	    Poco::JSON::Object  Answer; | 		QB_.SerialNumber = GetParameter(uCentral::RESTAPI::Protocol::SERIALNUMBER, ""); | ||||||
| 	    Answer.set("count", Count); | 		QB_.StartDate = GetParameter(uCentral::RESTAPI::Protocol::STARTDATE, 0); | ||||||
|         ReturnObject(Answer); | 		QB_.EndDate = GetParameter(uCentral::RESTAPI::Protocol::ENDDATE, 0); | ||||||
| 	} | 		QB_.Offset = GetParameter(uCentral::RESTAPI::Protocol::OFFSET, 0); | ||||||
|  | 		QB_.Limit = GetParameter(uCentral::RESTAPI::Protocol::LIMIT, 100); | ||||||
| 	bool RESTAPIHandler::InitQueryBlock() { | 		QB_.Filter = GetParameter(uCentral::RESTAPI::Protocol::FILTER, ""); | ||||||
| 	    if(QueryBlockInitialized_) | 		QB_.Select = GetParameter(uCentral::RESTAPI::Protocol::SELECT, ""); | ||||||
| 	        return true; | 		QB_.Lifetime = GetBoolParameter(uCentral::RESTAPI::Protocol::LIFETIME,false); | ||||||
| 	    QueryBlockInitialized_=true; | 		QB_.LogType = GetParameter(uCentral::RESTAPI::Protocol::LOGTYPE,0); | ||||||
| 		QB_.SerialNumber = GetParameter(RESTAPI::Protocol::SERIALNUMBER, ""); | 		QB_.LastOnly = GetBoolParameter(uCentral::RESTAPI::Protocol::LASTONLY,false); | ||||||
| 		QB_.StartDate = GetParameter(RESTAPI::Protocol::STARTDATE, 0); | 		QB_.Newest = GetBoolParameter(uCentral::RESTAPI::Protocol::NEWEST,false); | ||||||
| 		QB_.EndDate = GetParameter(RESTAPI::Protocol::ENDDATE, 0); |  | ||||||
| 		QB_.Offset = GetParameter(RESTAPI::Protocol::OFFSET, 1); |  | ||||||
| 		QB_.Limit = GetParameter(RESTAPI::Protocol::LIMIT, 100); |  | ||||||
| 		QB_.Filter = GetParameter(RESTAPI::Protocol::FILTER, ""); |  | ||||||
| 		QB_.Select = GetParameter(RESTAPI::Protocol::SELECT, ""); |  | ||||||
| 		QB_.Lifetime = GetBoolParameter(RESTAPI::Protocol::LIFETIME,false); |  | ||||||
| 		QB_.LogType = GetParameter(RESTAPI::Protocol::LOGTYPE,0); |  | ||||||
| 		QB_.LastOnly = GetBoolParameter(RESTAPI::Protocol::LASTONLY,false); |  | ||||||
| 		QB_.Newest = GetBoolParameter(RESTAPI::Protocol::NEWEST,false); |  | ||||||
| 		QB_.CountOnly = GetBoolParameter(RESTAPI::Protocol::COUNTONLY,false); |  | ||||||
|  |  | ||||||
| 		if(QB_.Offset<1) |  | ||||||
| 		    QB_.Offset=1; |  | ||||||
| 		return true; |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	[[nodiscard]] uint64_t RESTAPIHandler::Get(const char *Parameter,const Poco::JSON::Object::Ptr &Obj, uint64_t Default){ | 	[[nodiscard]] uint64_t RESTAPIHandler::Get(const char *Parameter,const Poco::JSON::Object::Ptr &Obj, uint64_t Default){ | ||||||
| @@ -474,6 +397,8 @@ namespace OpenWifi { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	[[nodiscard]] uint64_t RESTAPIHandler::GetWhen(const Poco::JSON::Object::Ptr &Obj) { | 	[[nodiscard]] uint64_t RESTAPIHandler::GetWhen(const Poco::JSON::Object::Ptr &Obj) { | ||||||
| 		return RESTAPIHandler::Get(RESTAPI::Protocol::WHEN, Obj); | 		return RESTAPIHandler::Get(uCentral::RESTAPI::Protocol::WHEN, Obj); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  |  | ||||||
| } | } | ||||||
| @@ -25,10 +25,8 @@ | |||||||
| #include "Poco/NullStream.h" | #include "Poco/NullStream.h" | ||||||
|  |  | ||||||
| #include "RESTAPI_SecurityObjects.h" | #include "RESTAPI_SecurityObjects.h" | ||||||
| #include "RESTAPI_utils.h" |  | ||||||
| #include "RESTAPI_GenericServer.h" |  | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|  |  | ||||||
|     class RESTAPI_PartHandler: public Poco::Net::PartHandler |     class RESTAPI_PartHandler: public Poco::Net::PartHandler | ||||||
|     { |     { | ||||||
| @@ -88,78 +86,66 @@ namespace OpenWifi { | |||||||
| 		struct QueryBlock { | 		struct QueryBlock { | ||||||
| 			uint64_t StartDate = 0 , EndDate = 0 , Offset = 0 , Limit = 0, LogType = 0 ; | 			uint64_t StartDate = 0 , EndDate = 0 , Offset = 0 , Limit = 0, LogType = 0 ; | ||||||
| 			std::string SerialNumber, Filter, Select; | 			std::string SerialNumber, Filter, Select; | ||||||
| 			bool Lifetime=false, LastOnly=false, Newest=false, CountOnly=false; | 			bool Lifetime=false, LastOnly=false, Newest=false; | ||||||
| 		}; | 		}; | ||||||
|  |  | ||||||
| 		typedef std::map<std::string, std::string> BindingMap; | 		typedef std::map<std::string, std::string> BindingMap; | ||||||
|  |  | ||||||
| 		RESTAPIHandler(BindingMap map, Poco::Logger &l, std::vector<std::string> Methods, RESTAPI_GenericServer & Server, bool Internal=false, bool AlwaysAuthorize=true) | 		RESTAPIHandler(BindingMap map, Poco::Logger &l, std::vector<std::string> Methods, bool Internal=false) | ||||||
| 		: Bindings_(std::move(map)), Logger_(l), Methods_(std::move(Methods)), Server_(Server), Internal_(Internal), AlwaysAuthorize_(AlwaysAuthorize) {} | 			: Bindings_(std::move(map)), Logger_(l), Methods_(std::move(Methods)), Internal_(Internal) {} | ||||||
|  |  | ||||||
| 		static bool ParseBindings(const std::string & Request, const std::list<const char *> & EndPoints, BindingMap &Keys); | 		static bool ParseBindings(const std::string & Request, const std::list<const char *> & EndPoints, BindingMap &Keys); | ||||||
| 		void PrintBindings(); | 		void PrintBindings(); | ||||||
| 		void ParseParameters(); | 		void ParseParameters(Poco::Net::HTTPServerRequest &request); | ||||||
|  |  | ||||||
| 		void AddCORS(); | 		void AddCORS(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &response); | ||||||
| 	 	void SetCommonHeaders(bool CloseConnection=false); | 	 	void SetCommonHeaders(Poco::Net::HTTPServerResponse &response, bool CloseConnection=false); | ||||||
| 		void ProcessOptions(); | 		void ProcessOptions(Poco::Net::HTTPServerRequest &Request, | ||||||
|  | 							Poco::Net::HTTPServerResponse &response); | ||||||
| 		void | 		void | ||||||
| 		PrepareResponse(Poco::Net::HTTPResponse::HTTPStatus Status = Poco::Net::HTTPResponse::HTTP_OK, | 		PrepareResponse(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &response, | ||||||
|  | 						Poco::Net::HTTPResponse::HTTPStatus Status = Poco::Net::HTTPResponse::HTTP_OK, | ||||||
| 						bool CloseConnection = false); | 						bool CloseConnection = false); | ||||||
| 		bool ContinueProcessing(); | 		bool ContinueProcessing(Poco::Net::HTTPServerRequest &Request, | ||||||
| 		bool IsAuthorized(); | 								Poco::Net::HTTPServerResponse &Response); | ||||||
|  |  | ||||||
|  | 		bool IsAuthorized(Poco::Net::HTTPServerRequest &Request, | ||||||
|  | 						  Poco::Net::HTTPServerResponse &Response); | ||||||
|  | /*		bool ValidateAPIKey(Poco::Net::HTTPServerRequest &Request, | ||||||
|  | 							Poco::Net::HTTPServerResponse &Response); */ | ||||||
|  |  | ||||||
| 		uint64_t GetParameter(const std::string &Name, uint64_t Default); | 		uint64_t GetParameter(const std::string &Name, uint64_t Default); | ||||||
| 		std::string GetParameter(const std::string &Name, const std::string &Default); | 		std::string GetParameter(const std::string &Name, const std::string &Default); | ||||||
| 		bool GetBoolParameter(const std::string &Name, bool Default); | 		bool GetBoolParameter(const std::string &Name, bool Default); | ||||||
|  |  | ||||||
| 		void BadRequest(const std::string &Reason ); | 		void BadRequest(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response, const std::string &Reason = ""); | ||||||
| 		void InternalError(const std::string &Reason = ""); | 		void UnAuthorized(Poco::Net::HTTPServerRequest &Request, | ||||||
| 		void UnAuthorized(const std::string &Reason = ""); | 						  Poco::Net::HTTPServerResponse &Response, const std::string &Reason = ""); | ||||||
| 		void ReturnObject(Poco::JSON::Object &Object); | 		void ReturnObject(Poco::Net::HTTPServerRequest &Request, Poco::JSON::Object &Object, | ||||||
| 		void NotFound(); | 						  Poco::Net::HTTPServerResponse &Response); | ||||||
| 		void OK(); | 		void NotFound(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response); | ||||||
| 		void ReturnStatus(Poco::Net::HTTPResponse::HTTPStatus Status, | 		void OK(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response); | ||||||
|  | 		void ReturnStatus(Poco::Net::HTTPServerRequest &Request, | ||||||
|  | 						  Poco::Net::HTTPServerResponse &Response, | ||||||
|  | 						  Poco::Net::HTTPResponse::HTTPStatus Status, | ||||||
| 						  bool CloseConnection=false); | 						  bool CloseConnection=false); | ||||||
| 		void SendFile(Poco::File & File, const std::string & UUID); | 		void SendFile(Poco::File & File, const std::string & UUID, | ||||||
|  | 					  Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response); | ||||||
| 		void SendHTMLFileBack(Poco::File & File, | 		void SendHTMLFileBack(Poco::File & File, | ||||||
|  |                               Poco::Net::HTTPServerRequest &Request, | ||||||
|  |                               Poco::Net::HTTPServerResponse &Response , | ||||||
|                               const Types::StringPairVec & FormVars); |                               const Types::StringPairVec & FormVars); | ||||||
|         void SendFile(Poco::TemporaryFile &TempAvatar, const std::string &Type, const std::string & Name); |         void SendFile(Poco::TemporaryFile &TempAvatar, const std::string &Type, const std::string & Name, Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response); | ||||||
|  |  | ||||||
|         void SendFile(Poco::File & File); |         void SendFile(Poco::File & File, Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response); | ||||||
|  |  | ||||||
|         const std::string &GetBinding(const std::string &Name, const std::string &Default); |         const std::string &GetBinding(const std::string &Name, const std::string &Default); | ||||||
| 		bool InitQueryBlock(); | 		void InitQueryBlock(); | ||||||
|  |  | ||||||
| 		void ReturnCountOnly(uint64_t Count); |  | ||||||
|  |  | ||||||
| 		[[nodiscard]] static uint64_t Get(const char *Parameter,const Poco::JSON::Object::Ptr &Obj, uint64_t Default=0); | 		[[nodiscard]] static uint64_t Get(const char *Parameter,const Poco::JSON::Object::Ptr &Obj, uint64_t Default=0); | ||||||
| 		[[nodiscard]] static std::string GetS(const char *Parameter,const Poco::JSON::Object::Ptr &Obj, const std::string & Default=""); | 		[[nodiscard]] static std::string GetS(const char *Parameter,const Poco::JSON::Object::Ptr &Obj, const std::string & Default=""); | ||||||
| 		[[nodiscard]] static bool GetB(const char *Parameter,const Poco::JSON::Object::Ptr &Obj, bool Default=false); | 		[[nodiscard]] static bool GetB(const char *Parameter,const Poco::JSON::Object::Ptr &Obj, bool Default=false); | ||||||
| 		[[nodiscard]] static uint64_t GetWhen(const Poco::JSON::Object::Ptr &Obj); | 		[[nodiscard]] static uint64_t GetWhen(const Poco::JSON::Object::Ptr &Obj); | ||||||
| 		bool HasParameter(const std::string &QueryParameter, std::string &Value); |  | ||||||
| 		bool HasParameter(const std::string &QueryParameter, uint64_t & Value); |  | ||||||
|  |  | ||||||
| 		static bool AssignIfPresent(const Poco::JSON::Object::Ptr &O, const std::string &Field, std::string &Value); |  | ||||||
| 		static bool AssignIfPresent(const Poco::JSON::Object::Ptr &O, const std::string &Field, uint64_t &Value); |  | ||||||
|  |  | ||||||
| 		template<typename T> void ReturnObject(const char *Name, const std::vector<T> & Objects) { |  | ||||||
| 		    Poco::JSON::Object  Answer; |  | ||||||
| 		    RESTAPI_utils::field_to_json(Answer,Name,Objects); |  | ||||||
|             ReturnObject(Answer); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		Poco::Logger & Logger() { return Logger_; } |  | ||||||
|  |  | ||||||
| 		void handleRequest(Poco::Net::HTTPServerRequest &request, |  | ||||||
|                            Poco::Net::HTTPServerResponse &response) final; |  | ||||||
|  |  | ||||||
| 		virtual void DoGet() = 0 ; |  | ||||||
| 		virtual void DoDelete() = 0 ; |  | ||||||
| 		virtual void DoPost() = 0 ; |  | ||||||
| 		virtual void DoPut() = 0 ; |  | ||||||
|  |  | ||||||
| 		const Poco::JSON::Object::Ptr & ParseStream(); |  | ||||||
|  |  | ||||||
| 	  protected: | 	  protected: | ||||||
| 		BindingMap 					Bindings_; | 		BindingMap 					Bindings_; | ||||||
| @@ -170,23 +156,19 @@ namespace OpenWifi { | |||||||
| 		std::vector<std::string> 	Methods_; | 		std::vector<std::string> 	Methods_; | ||||||
| 		QueryBlock					QB_; | 		QueryBlock					QB_; | ||||||
| 		bool                        Internal_=false; | 		bool                        Internal_=false; | ||||||
| 		bool                        QueryBlockInitialized_=false; |  | ||||||
| 		Poco::Net::HTTPServerRequest    *Request= nullptr; |  | ||||||
| 		Poco::Net::HTTPServerResponse   *Response= nullptr; |  | ||||||
| 		bool                        AlwaysAuthorize_=true; |  | ||||||
| 		Poco::JSON::Parser          IncomingParser_; |  | ||||||
| 		RESTAPI_GenericServer       & Server_; |  | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	class RESTAPI_UnknownRequestHandler : public RESTAPIHandler { | 	class RESTAPI_UnknownRequestHandler : public RESTAPIHandler { | ||||||
| 	  public: | 	  public: | ||||||
| 		RESTAPI_UnknownRequestHandler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server) | 		RESTAPI_UnknownRequestHandler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L) | ||||||
| 			: RESTAPIHandler(bindings, L, std::vector<std::string>{}, Server) {} | 			: RESTAPIHandler(bindings, L, std::vector<std::string>{}) {} | ||||||
|         inline void DoGet() override {}; | 		void handleRequest(Poco::Net::HTTPServerRequest &Request, | ||||||
| 		inline void DoPost() override {}; | 						   Poco::Net::HTTPServerResponse &Response) override { | ||||||
| 		inline void DoPut() override {}; | 			if (!IsAuthorized(Request, Response)) | ||||||
| 		inline void DoDelete() override {}; | 				return; | ||||||
|     }; | 			BadRequest(Request, Response); | ||||||
|  | 		} | ||||||
|  | 	}; | ||||||
|  |  | ||||||
| 	template<class T> | 	template<class T> | ||||||
| 	constexpr auto test_has_PathName_method(T*) | 	constexpr auto test_has_PathName_method(T*) | ||||||
| @@ -200,30 +182,30 @@ namespace OpenWifi { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	template<typename T, typename... Args> | 	template<typename T, typename... Args> | ||||||
| 	RESTAPIHandler * RESTAPI_Router(const std::string & RequestedPath, RESTAPIHandler::BindingMap &Bindings, Poco::Logger & Logger, RESTAPI_GenericServer & Server) { | 	RESTAPIHandler * RESTAPI_Router(const std::string & RequestedPath, RESTAPIHandler::BindingMap &Bindings, Poco::Logger & Logger ) { | ||||||
| 		static_assert(test_has_PathName_method((T*)nullptr), "Class must have a static PathName() method."); | 		static_assert(test_has_PathName_method((T*)nullptr), "Class must have a static PathName() method."); | ||||||
| 		if(RESTAPIHandler::ParseBindings(RequestedPath,T::PathName(),Bindings)) { | 		if(RESTAPIHandler::ParseBindings(RequestedPath,T::PathName(),Bindings)) { | ||||||
| 			return new T(Bindings, Logger, Server, false); | 			return new T(Bindings, Logger, false); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if constexpr (sizeof...(Args) == 0) { | 		if constexpr (sizeof...(Args) == 0) { | ||||||
| 			return new RESTAPI_UnknownRequestHandler(Bindings,Logger, Server); | 			return new RESTAPI_UnknownRequestHandler(Bindings,Logger); | ||||||
| 		} else { | 		} else { | ||||||
| 			return RESTAPI_Router<Args...>(RequestedPath, Bindings, Logger, Server); | 			return RESTAPI_Router<Args...>(RequestedPath, Bindings, Logger); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|     template<typename T, typename... Args> |     template<typename T, typename... Args> | ||||||
|     RESTAPIHandler * RESTAPI_Router_I(const std::string & RequestedPath, RESTAPIHandler::BindingMap &Bindings, Poco::Logger & Logger, RESTAPI_GenericServer & Server) { |     RESTAPIHandler * RESTAPI_Router_I(const std::string & RequestedPath, RESTAPIHandler::BindingMap &Bindings, Poco::Logger & Logger) { | ||||||
|         static_assert(test_has_PathName_method((T*)nullptr), "Class must have a static PathName() method."); |         static_assert(test_has_PathName_method((T*)nullptr), "Class must have a static PathName() method."); | ||||||
|         if(RESTAPIHandler::ParseBindings(RequestedPath,T::PathName(),Bindings)) { |         if(RESTAPIHandler::ParseBindings(RequestedPath,T::PathName(),Bindings)) { | ||||||
|             return new T(Bindings, Logger, Server, true); |             return new T(Bindings, Logger, true); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if constexpr (sizeof...(Args) == 0) { |         if constexpr (sizeof...(Args) == 0) { | ||||||
|             return new RESTAPI_UnknownRequestHandler(Bindings,Logger, Server); |             return new RESTAPI_UnknownRequestHandler(Bindings,Logger); | ||||||
|         } else { |         } else { | ||||||
|             return RESTAPI_Router_I<Args...>(RequestedPath, Bindings, Logger, Server); |             return RESTAPI_Router_I<Args...>(RequestedPath, Bindings, Logger); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -15,86 +15,98 @@ | |||||||
|  |  | ||||||
| #include "Utils.h" | #include "Utils.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
| 	void RESTAPI_oauth2Handler::DoGet() { | 	void RESTAPI_oauth2Handler::handleRequest(Poco::Net::HTTPServerRequest &Request, | ||||||
|         if (!IsAuthorized()) { | 											  Poco::Net::HTTPServerResponse &Response) { | ||||||
|             UnAuthorized("Not authorized."); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|         bool GetMe = GetBoolParameter(RESTAPI::Protocol::ME, false); |  | ||||||
|         if(GetMe) { |  | ||||||
|             Logger_.information(Poco::format("REQUEST-ME(%s): Request for %s", Request->clientAddress().toString(), UserInfo_.userinfo.email)); |  | ||||||
|             Poco::JSON::Object Me; |  | ||||||
|             UserInfo_.userinfo.to_json(Me); |  | ||||||
|             ReturnObject(Me); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|         BadRequest("Ill-formed request. Please consult documentation."); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
|     void RESTAPI_oauth2Handler::DoDelete() { | 		if (!ContinueProcessing(Request, Response)) | ||||||
|         if (!IsAuthorized()) { | 			return; | ||||||
|             UnAuthorized("Not authorized."); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|         auto Token = GetBinding(RESTAPI::Protocol::TOKEN, "..."); |  | ||||||
|         if (Token == SessionToken_) { |  | ||||||
|             AuthService()->Logout(Token); |  | ||||||
|             ReturnStatus(Poco::Net::HTTPResponse::HTTP_NO_CONTENT, true); |  | ||||||
|         } else { |  | ||||||
|             Logger_.information(Poco::format("BAD-LOGOUT(%s): Request for %s", Request->clientAddress().toString(), UserInfo_.userinfo.email)); |  | ||||||
|             NotFound(); |  | ||||||
|         } |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	void RESTAPI_oauth2Handler::DoPost() { | 		try { | ||||||
|         auto Obj = ParseStream(); |             ParseParameters(Request); | ||||||
|         auto userId = GetS(RESTAPI::Protocol::USERID, Obj); | 			if (Request.getMethod() == Poco::Net::HTTPServerRequest::HTTP_POST) { | ||||||
|         auto password = GetS(RESTAPI::Protocol::PASSWORD, Obj); | 				// Extract the info for login... | ||||||
|         auto newPassword = GetS(RESTAPI::Protocol::NEWPASSWORD, Obj); | 				Poco::JSON::Parser parser; | ||||||
|         Poco::toLowerInPlace(userId); | 				Poco::JSON::Object::Ptr Obj = parser.parse(Request.stream()).extract<Poco::JSON::Object::Ptr>(); | ||||||
|  |  | ||||||
|         if(GetBoolParameter(RESTAPI::Protocol::REQUIREMENTS, false)) { | 				auto userId = GetS(uCentral::RESTAPI::Protocol::USERID, Obj); | ||||||
|             Logger_.information(Poco::format("POLICY-REQUEST(%s): Request.", Request->clientAddress().toString())); | 				auto password = GetS(uCentral::RESTAPI::Protocol::PASSWORD, Obj); | ||||||
|             Poco::JSON::Object  Answer; | 				auto newPassword = GetS(uCentral::RESTAPI::Protocol::NEWPASSWORD, Obj); | ||||||
|             Answer.set(RESTAPI::Protocol::PASSWORDPATTERN, AuthService()->PasswordValidationExpression()); |  | ||||||
|             Answer.set(RESTAPI::Protocol::ACCESSPOLICY, RESTAPI_Server()->GetAccessPolicy()); |  | ||||||
|             Answer.set(RESTAPI::Protocol::PASSWORDPOLICY, RESTAPI_Server()->GetPasswordPolicy()); |  | ||||||
|             ReturnObject(Answer); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if(GetBoolParameter(RESTAPI::Protocol::FORGOTPASSWORD,false)) { |                 if(GetBoolParameter(RESTAPI::Protocol::REQUIREMENTS, false)) { | ||||||
|             //  Send an email to the userId |                     Poco::JSON::Object  Answer; | ||||||
|             Logger_.information(Poco::format("FORGOTTEN-PASSWORD(%s): Request for %s", Request->clientAddress().toString(), userId)); |                     Answer.set(RESTAPI::Protocol::PASSWORDPATTERN, AuthService()->PasswordValidationExpression()); | ||||||
|             SecurityObjects::UserInfoAndPolicy UInfo; |                     Answer.set(RESTAPI::Protocol::ACCESSPOLICY, RESTAPI_Server()->GetAccessPolicy()); | ||||||
|             if(AuthService::SendEmailToUser(userId,AuthService::FORGOT_PASSWORD)) |                     Answer.set(RESTAPI::Protocol::PASSWORDPOLICY, RESTAPI_Server()->GetPasswordPolicy()); | ||||||
|                 Logger_.information(Poco::format("Send password reset link to %s",userId)); |                     ReturnObject(Request, Answer, Response); | ||||||
|             UInfo.webtoken.userMustChangePassword=true; |                     return; | ||||||
|             Poco::JSON::Object ReturnObj; |                 } | ||||||
|             UInfo.webtoken.to_json(ReturnObj); |  | ||||||
|             ReturnObject(ReturnObj); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         SecurityObjects::UserInfoAndPolicy UInfo; |                 if(GetBoolParameter(RESTAPI::Protocol::FORGOTPASSWORD,false)) { | ||||||
|  |                     //  Send an email to the userId | ||||||
|  |                     SecurityObjects::UserInfoAndPolicy UInfo; | ||||||
|  |                     if(AuthService::SendEmailToUser(userId,AuthService::FORGOT_PASSWORD)) | ||||||
|  |                         Logger_.information(Poco::format("Send password reset link to %s",userId)); | ||||||
|  |                     UInfo.webtoken.userMustChangePassword=true; | ||||||
|  |                     Poco::JSON::Object ReturnObj; | ||||||
|  |                     UInfo.webtoken.to_json(ReturnObj); | ||||||
|  |                     ReturnObject(Request, ReturnObj, Response); | ||||||
|  |                     return; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|         auto Code=AuthService()->Authorize(userId, password, newPassword, UInfo); | 				Poco::toLowerInPlace(userId); | ||||||
|         if (Code==AuthService::SUCCESS) { |                 SecurityObjects::UserInfoAndPolicy UInfo; | ||||||
|             Poco::JSON::Object ReturnObj; |  | ||||||
|             UInfo.webtoken.to_json(ReturnObj); |                 auto Code=AuthService()->Authorize(userId, password, newPassword, UInfo); | ||||||
|             ReturnObject(ReturnObj); | 				if (Code==AuthService::SUCCESS) { | ||||||
|             return; | 					Poco::JSON::Object ReturnObj; | ||||||
|         } else { |                     UInfo.webtoken.to_json(ReturnObj); | ||||||
|             switch(Code) { | 					ReturnObject(Request, ReturnObj, Response); | ||||||
|                 case AuthService::INVALID_CREDENTIALS: UnAuthorized("Unrecognized credentials (username/password)."); break; | 					return; | ||||||
|                 case AuthService::PASSWORD_INVALID: UnAuthorized("Invalid password."); break; | 				} else { | ||||||
|                 case AuthService::PASSWORD_ALREADY_USED: UnAuthorized("Password already used previously."); break; | 				    switch(Code) { | ||||||
|                 case AuthService::USERNAME_PENDING_VERIFICATION: UnAuthorized("User access pending email verification."); break; | 				        case AuthService::INVALID_CREDENTIALS: UnAuthorized(Request, Response, "Unrecognized credentials (username/password)."); break; | ||||||
|                 case AuthService::PASSWORD_CHANGE_REQUIRED: UnAuthorized("Password change expected."); break; |                         case AuthService::PASSWORD_INVALID: UnAuthorized(Request, Response, "Invalid password."); break; | ||||||
|                 default: UnAuthorized("Unrecognized credentials (username/password)."); break; |                         case AuthService::PASSWORD_ALREADY_USED: UnAuthorized(Request, Response, "Password already used previously."); break; | ||||||
|             } |                         case AuthService::USERNAME_PENDING_VERIFICATION: UnAuthorized(Request, Response, "User access pending email verification."); break; | ||||||
|             return; |                         case AuthService::PASSWORD_CHANGE_REQUIRED: UnAuthorized(Request, Response, "Password change expected."); break; | ||||||
|         } |                         default: UnAuthorized(Request, Response, "Unrecognized credentials (username/password)."); break; | ||||||
|  | 				    } | ||||||
|  | 				    return; | ||||||
|  | 				} | ||||||
|  | 			} else if (Request.getMethod() == Poco::Net::HTTPServerRequest::HTTP_DELETE) { | ||||||
|  | 				if (!IsAuthorized(Request, Response)) { | ||||||
|  |                     UnAuthorized(Request, Response, "Not authorized."); | ||||||
|  | 					return; | ||||||
|  | 				} | ||||||
|  | 				auto Token = GetBinding(uCentral::RESTAPI::Protocol::TOKEN, "..."); | ||||||
|  | 				if (Token == SessionToken_) { | ||||||
|  | 					AuthService()->Logout(Token); | ||||||
|  | 					ReturnStatus(Request, Response, Poco::Net::HTTPResponse::HTTP_NO_CONTENT, true); | ||||||
|  | 				} else { | ||||||
|  | 					NotFound(Request, Response); | ||||||
|  | 				} | ||||||
|  | 			} else if (Request.getMethod() == Poco::Net::HTTPServerRequest::HTTP_GET) { | ||||||
|  |                 if (!IsAuthorized(Request, Response)) { | ||||||
|  |                     UnAuthorized(Request, Response, "Not authorized."); | ||||||
|  |                     return; | ||||||
|  |                 } | ||||||
|  |                 bool GetMe = GetBoolParameter(RESTAPI::Protocol::ME, false); | ||||||
|  |                 if(GetMe) { | ||||||
|  |                     Poco::JSON::Object Me; | ||||||
|  |                     UserInfo_.userinfo.to_json(Me); | ||||||
|  |                     ReturnObject(Request, Me, Response); | ||||||
|  |                     return; | ||||||
|  |                 } | ||||||
|  |                 BadRequest(Request, Response); | ||||||
|  | 			} else { | ||||||
|  |                 BadRequest(Request, Response, "Unsupported HTTP method."); | ||||||
|  | 			} | ||||||
|  | 			return; | ||||||
|  | 		} catch (const Poco::Exception &E) { | ||||||
|  | 			Logger_.warning( | ||||||
|  | 				Poco::format("%s: Failed with: %s", std::string(__func__), E.displayText())); | ||||||
|  | 		} | ||||||
|  | 		BadRequest(Request, Response); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @@ -11,22 +11,19 @@ | |||||||
|  |  | ||||||
| #include "RESTAPI_handler.h" | #include "RESTAPI_handler.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
| 	class RESTAPI_oauth2Handler : public RESTAPIHandler { | 	class RESTAPI_oauth2Handler : public RESTAPIHandler { | ||||||
| 	  public: | 	  public: | ||||||
| 	    RESTAPI_oauth2Handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, bool Internal) | 		RESTAPI_oauth2Handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal) | ||||||
| 			: RESTAPIHandler(bindings, L, | 			: RESTAPIHandler(bindings, L, | ||||||
| 							 std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_POST, | 							 std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_POST, | ||||||
| 													  Poco::Net::HTTPRequest::HTTP_DELETE, | 													  Poco::Net::HTTPRequest::HTTP_DELETE, | ||||||
|                                                       Poco::Net::HTTPRequest::HTTP_GET, |                                                       Poco::Net::HTTPRequest::HTTP_GET, | ||||||
| 													  Poco::Net::HTTPRequest::HTTP_OPTIONS}, | 													  Poco::Net::HTTPRequest::HTTP_OPTIONS}, | ||||||
| 													  Server, | 													  Internal) {} | ||||||
| 													  Internal, false) {} | 		void handleRequest(Poco::Net::HTTPServerRequest &request, | ||||||
|  | 						   Poco::Net::HTTPServerResponse &response) override; | ||||||
| 		static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/oauth2/{token}","/api/v1/oauth2"}; }; | 		static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/oauth2/{token}","/api/v1/oauth2"}; }; | ||||||
| 		void DoGet() final; |  | ||||||
| 		void DoPost() final; |  | ||||||
| 		void DoDelete() final; |  | ||||||
| 		void DoPut() final {}; |  | ||||||
| 	}; | 	}; | ||||||
| } | } | ||||||
| #endif //UCENTRAL_RESTAPI_OAUTH2HANDLER_H | #endif //UCENTRAL_RESTAPI_OAUTH2HANDLER_H | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ | |||||||
| #ifndef UCENTRALGW_RESTAPI_PROTOCOL_H | #ifndef UCENTRALGW_RESTAPI_PROTOCOL_H | ||||||
| #define UCENTRALGW_RESTAPI_PROTOCOL_H | #define UCENTRALGW_RESTAPI_PROTOCOL_H | ||||||
|  |  | ||||||
| namespace OpenWifi::RESTAPI::Protocol { | namespace uCentral::RESTAPI::Protocol { | ||||||
| 	static const char * CAPABILITIES = "capabilities"; | 	static const char * CAPABILITIES = "capabilities"; | ||||||
| 	static const char * LOGS = "logs"; | 	static const char * LOGS = "logs"; | ||||||
| 	static const char * HEALTHCHECKS = "healthchecks"; | 	static const char * HEALTHCHECKS = "healthchecks"; | ||||||
| @@ -69,13 +69,7 @@ namespace OpenWifi::RESTAPI::Protocol { | |||||||
| 	static const char * COMMANDUUID = "commandUUID"; | 	static const char * COMMANDUUID = "commandUUID"; | ||||||
| 	static const char * FIRMWARES = "firmwares"; | 	static const char * FIRMWARES = "firmwares"; | ||||||
| 	static const char * TOPIC = "topic"; | 	static const char * TOPIC = "topic"; | ||||||
| 	static const char * HOST = "host"; |  | ||||||
| 	static const char * OS = "os"; |  | ||||||
| 	static const char * HOSTNAME = "hostname"; |  | ||||||
| 	static const char * PROCESSORS = "processors"; |  | ||||||
| 	static const char * REASON = "reason"; | 	static const char * REASON = "reason"; | ||||||
| 	static const char * RELOAD = "reload"; |  | ||||||
| 	static const char * SUBSYSTEMS = "subsystems"; |  | ||||||
| 	static const char * FILEUUID = "uuid"; | 	static const char * FILEUUID = "uuid"; | ||||||
| 	static const char * USERID = "userId"; | 	static const char * USERID = "userId"; | ||||||
| 	static const char * PASSWORD = "password"; | 	static const char * PASSWORD = "password"; | ||||||
| @@ -128,8 +122,6 @@ namespace OpenWifi::RESTAPI::Protocol { | |||||||
|     static const char * PASSWORDPOLICY = "passwordPolicy"; |     static const char * PASSWORDPOLICY = "passwordPolicy"; | ||||||
|     static const char * FORGOTPASSWORD = "forgotPassword"; |     static const char * FORGOTPASSWORD = "forgotPassword"; | ||||||
|     static const char * ME = "me"; |     static const char * ME = "me"; | ||||||
|     static const char * TELEMETRY = "telemetry"; |  | ||||||
|     static const char * INTERVAL = "interval"; |  | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -19,22 +19,20 @@ | |||||||
| #include "RESTAPI_systemEndpoints_handler.h" | #include "RESTAPI_systemEndpoints_handler.h" | ||||||
| #include "RESTAPI_AssetServer.h" | #include "RESTAPI_AssetServer.h" | ||||||
| #include "RESTAPI_avatarHandler.h" | #include "RESTAPI_avatarHandler.h" | ||||||
| #include "RESTAPI_email_handler.h" |  | ||||||
|  |  | ||||||
| #include "Daemon.h" | #include "Daemon.h" | ||||||
| #include "Utils.h" | #include "Utils.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|  |  | ||||||
|     class RESTAPI_Server *RESTAPI_Server::instance_ = nullptr; |     class RESTAPI_Server *RESTAPI_Server::instance_ = nullptr; | ||||||
|  |  | ||||||
|     int RESTAPI_Server::Start() { |     int RESTAPI_Server::Start() { | ||||||
|         Logger_.information("Starting."); |         Logger_.information("Starting."); | ||||||
|         Server_.InitLogging(); |  | ||||||
|  |  | ||||||
|         AsserDir_ = Daemon()->ConfigPath("openwifi.restapi.wwwassets"); |         AsserDir_ = Daemon()->ConfigPath("ucentral.restapi.wwwassets"); | ||||||
|         AccessPolicy_ = Daemon()->ConfigGetString("openwifi.document.policy.access", "/wwwassets/access_policy.html"); |         AccessPolicy_ = Daemon()->ConfigGetString("ucentral.document.policy.access", "/wwwassets/access_policy.html"); | ||||||
|         PasswordPolicy_ = Daemon()->ConfigGetString("openwifi.document.policy.password", "/wwwassets/possword_policy.html"); |         PasswordPolicy_ = Daemon()->ConfigGetString("ucentral.document.policy.password", "/wwwassets/possword_policy.html"); | ||||||
|  |  | ||||||
|         for(const auto & Svr: ConfigServersList_) { |         for(const auto & Svr: ConfigServersList_) { | ||||||
| 			Logger_.information(Poco::format("Starting: %s:%s Keyfile:%s CertFile: %s", Svr.Address(), std::to_string(Svr.Port()), | 			Logger_.information(Poco::format("Starting: %s:%s Keyfile:%s CertFile: %s", Svr.Address(), std::to_string(Svr.Port()), | ||||||
| @@ -51,14 +49,18 @@ namespace OpenWifi { | |||||||
|             Params->setMaxQueued(200); |             Params->setMaxQueued(200); | ||||||
| 			Params->setKeepAlive(true); | 			Params->setKeepAlive(true); | ||||||
|  |  | ||||||
|             auto NewServer = std::make_unique<Poco::Net::HTTPServer>(new RequestHandlerFactory(Server_), Pool_, Sock, Params); |             auto NewServer = std::make_unique<Poco::Net::HTTPServer>(new RequestHandlerFactory, Pool_, Sock, Params); | ||||||
|             NewServer->start(); |             NewServer->start(); | ||||||
|             RESTServers_.push_back(std::move(NewServer)); |             RESTServers_.push_back(std::move(NewServer)); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         return 0; |         return 0; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     Poco::Net::HTTPRequestHandler *RequestHandlerFactory::createRequestHandler(const Poco::Net::HTTPServerRequest & Request) { |     Poco::Net::HTTPRequestHandler *RequestHandlerFactory::createRequestHandler(const Poco::Net::HTTPServerRequest & Request) { | ||||||
|  |  | ||||||
|  |         Logger_.debug(Poco::format("REQUEST(%s): %s %s", uCentral::Utils::FormatIPv6(Request.clientAddress().toString()), Request.getMethod(), Request.getURI())); | ||||||
|  |  | ||||||
|         Poco::URI uri(Request.getURI()); |         Poco::URI uri(Request.getURI()); | ||||||
|         const auto & Path = uri.getPath(); |         const auto & Path = uri.getPath(); | ||||||
|         RESTAPIHandler::BindingMap Bindings; |         RESTAPIHandler::BindingMap Bindings; | ||||||
| @@ -70,23 +72,14 @@ namespace OpenWifi { | |||||||
|                 RESTAPI_AssetServer, |                 RESTAPI_AssetServer, | ||||||
|                 RESTAPI_systemEndpoints_handler, |                 RESTAPI_systemEndpoints_handler, | ||||||
|                 RESTAPI_action_links, |                 RESTAPI_action_links, | ||||||
|                 RESTAPI_avatarHandler, |                 RESTAPI_avatarHandler | ||||||
|                 RESTAPI_email_handler |                 >(Path,Bindings,Logger_); | ||||||
|                 >(Path,Bindings,Logger_,Server_); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void RESTAPI_Server::Stop() { |     void RESTAPI_Server::Stop() { | ||||||
|         Logger_.information("Stopping "); |         Logger_.information("Stopping "); | ||||||
|         for( const auto & svr : RESTServers_ ) |         for( const auto & svr : RESTServers_ ) | ||||||
|             svr->stop(); |             svr->stop(); | ||||||
|         RESTServers_.clear(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void RESTAPI_Server::reinitialize(Poco::Util::Application &self) { |  | ||||||
|         Daemon()->LoadConfigurationFile(); |  | ||||||
|         Logger_.information("Reinitializing."); |  | ||||||
|         Stop(); |  | ||||||
|         Start(); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
| }  // namespace | }  // namespace | ||||||
| @@ -15,9 +15,8 @@ | |||||||
| #include "Poco/Net/HTTPRequestHandlerFactory.h" | #include "Poco/Net/HTTPRequestHandlerFactory.h" | ||||||
| #include "Poco/Net/HTTPServerRequest.h" | #include "Poco/Net/HTTPServerRequest.h" | ||||||
| #include "Poco/Net/NetException.h" | #include "Poco/Net/NetException.h" | ||||||
| #include "RESTAPI_GenericServer.h" |  | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|  |  | ||||||
|     class RESTAPI_Server : public SubSystemServer { |     class RESTAPI_Server : public SubSystemServer { | ||||||
|  |  | ||||||
| @@ -31,8 +30,6 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
|         int Start() override; |         int Start() override; | ||||||
|         void Stop() override; |         void Stop() override; | ||||||
|         void reinitialize(Poco::Util::Application &self) override; |  | ||||||
|  |  | ||||||
|         inline const std::string & AssetDir() { return AsserDir_; } |         inline const std::string & AssetDir() { return AsserDir_; } | ||||||
|         inline const std::string & GetPasswordPolicy() const { return PasswordPolicy_; } |         inline const std::string & GetPasswordPolicy() const { return PasswordPolicy_; } | ||||||
|         inline const std::string & GetAccessPolicy() const { return AccessPolicy_; } |         inline const std::string & GetAccessPolicy() const { return AccessPolicy_; } | ||||||
| @@ -43,10 +40,9 @@ namespace OpenWifi { | |||||||
| 		std::string         AsserDir_; | 		std::string         AsserDir_; | ||||||
| 		std::string         PasswordPolicy_; | 		std::string         PasswordPolicy_; | ||||||
| 		std::string         AccessPolicy_; | 		std::string         AccessPolicy_; | ||||||
| 		RESTAPI_GenericServer   Server_; |  | ||||||
|  |  | ||||||
|         RESTAPI_Server() noexcept: |         RESTAPI_Server() noexcept: | ||||||
|             SubSystemServer("RESTAPIServer", "REST-SRV", "openwifi.restapi") |             SubSystemServer("RESTAPIServer", "REST-SRV", "ucentral.restapi") | ||||||
|         { |         { | ||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
| @@ -55,14 +51,12 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
|     class RequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory { |     class RequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory { | ||||||
|         public: |         public: | ||||||
|         RequestHandlerFactory(RESTAPI_GenericServer &Server) : |             RequestHandlerFactory() : | ||||||
|                 Logger_(RESTAPI_Server()->Logger()), |                 Logger_(RESTAPI_Server()->Logger()){} | ||||||
|                 Server_(Server){} |  | ||||||
|  |  | ||||||
|             Poco::Net::HTTPRequestHandler *createRequestHandler(const Poco::Net::HTTPServerRequest &request) override; |             Poco::Net::HTTPRequestHandler *createRequestHandler(const Poco::Net::HTTPServerRequest &request) override; | ||||||
|         private: |         private: | ||||||
|             Poco::Logger    & Logger_; |             Poco::Logger    & Logger_; | ||||||
|             RESTAPI_GenericServer   &Server_; |  | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -6,20 +6,39 @@ | |||||||
| #include "Daemon.h" | #include "Daemon.h" | ||||||
| #include "RESTAPI_SecurityObjects.h" | #include "RESTAPI_SecurityObjects.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|  |     void RESTAPI_systemEndpoints_handler::handleRequest(Poco::Net::HTTPServerRequest &Request, | ||||||
|  |                                                         Poco::Net::HTTPServerResponse &Response) { | ||||||
|  |  | ||||||
|     void RESTAPI_systemEndpoints_handler::DoGet() { |         if (!ContinueProcessing(Request, Response)) | ||||||
|         auto Services = Daemon()->GetServices(); |             return; | ||||||
|         SecurityObjects::SystemEndpointList L; |  | ||||||
|         for(const auto &i:Services) { |         if (!IsAuthorized(Request, Response)) | ||||||
|             SecurityObjects::SystemEndpoint S{ |             return; | ||||||
|                 .type = i.Type, |  | ||||||
|                 .id = i.Id, |         try { | ||||||
|                 .uri = i.PublicEndPoint}; |             if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET) { | ||||||
|             L.endpoints.push_back(S); |                 auto Services = Daemon()->GetServices(); | ||||||
|  |  | ||||||
|  |                 SecurityObjects::SystemEndpointList L; | ||||||
|  |  | ||||||
|  |                 for(const auto &i:Services) { | ||||||
|  |                     SecurityObjects::SystemEndpoint S{ | ||||||
|  |                         .type = i.Type, | ||||||
|  |                         .id = i.Id, | ||||||
|  |                         .uri = i.PublicEndPoint}; | ||||||
|  |                     L.endpoints.push_back(S); | ||||||
|  |                 } | ||||||
|  |                 Poco::JSON::Object  Obj; | ||||||
|  |                 L.to_json(Obj); | ||||||
|  |  | ||||||
|  |                 ReturnObject(Request, Obj, Response); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |         } catch (const Poco::Exception &E) { | ||||||
|  |             Logger_.log(E); | ||||||
|         } |         } | ||||||
|         Poco::JSON::Object  Obj; |         BadRequest(Request, Response); | ||||||
|         L.to_json(Obj); |  | ||||||
|         ReturnObject(Obj); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -6,20 +6,17 @@ | |||||||
| #define UCENTRALSEC_RESTAPI_SYSTEMENDPOINTS_HANDLER_H | #define UCENTRALSEC_RESTAPI_SYSTEMENDPOINTS_HANDLER_H | ||||||
|  |  | ||||||
| #include "RESTAPI_handler.h" | #include "RESTAPI_handler.h" | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|     class RESTAPI_systemEndpoints_handler : public RESTAPIHandler { |     class RESTAPI_systemEndpoints_handler : public RESTAPIHandler { | ||||||
|     public: |     public: | ||||||
|         RESTAPI_systemEndpoints_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, bool Internal) |         RESTAPI_systemEndpoints_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal) | ||||||
|                 : RESTAPIHandler(bindings, L, |                 : RESTAPIHandler(bindings, L, | ||||||
|                                  std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_GET, |                                  std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_GET, | ||||||
|                                                           Poco::Net::HTTPRequest::HTTP_OPTIONS}, |                                                           Poco::Net::HTTPRequest::HTTP_OPTIONS}, | ||||||
|                                                           Server, |  | ||||||
|                                                           Internal) {} |                                                           Internal) {} | ||||||
|  |         void handleRequest(Poco::Net::HTTPServerRequest &request, | ||||||
|  |                            Poco::Net::HTTPServerResponse &response) override; | ||||||
|         static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/systemEndpoints"}; }; |         static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/systemEndpoints"}; }; | ||||||
|         void DoGet() final; |  | ||||||
|         void DoPost() final {}; |  | ||||||
|         void DoDelete() final {}; |  | ||||||
|         void DoPut() final {}; |  | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -9,138 +9,124 @@ | |||||||
|  |  | ||||||
| #include "Poco/Exception.h" | #include "Poco/Exception.h" | ||||||
| #include "Poco/JSON/Parser.h" | #include "Poco/JSON/Parser.h" | ||||||
| #include "Poco/DateTime.h" |  | ||||||
| #include "Poco/DateTimeFormat.h" |  | ||||||
|  |  | ||||||
| #include "Daemon.h" | #include "Daemon.h" | ||||||
| #include "RESTAPI_protocol.h" | #include "RESTAPI_protocol.h" | ||||||
| #include "RESTAPI_errors.h" |  | ||||||
| #include <thread> |  | ||||||
| #include <chrono> |  | ||||||
|  |  | ||||||
| using namespace std::chrono_literals; | namespace uCentral { | ||||||
|  | 	void RESTAPI_system_command::handleRequest(Poco::Net::HTTPServerRequest &Request, | ||||||
|  | 											   Poco::Net::HTTPServerResponse &Response) { | ||||||
|  |  | ||||||
| namespace OpenWifi { | 		if (!ContinueProcessing(Request, Response)) | ||||||
| 	void RESTAPI_system_command::DoPost() { | 			return; | ||||||
| 		auto Obj = ParseStream(); |  | ||||||
| 		if (Obj->has(RESTAPI::Protocol::COMMAND)) { | 		if (!IsAuthorized(Request, Response)) | ||||||
| 			auto Command = Poco::toLower(Obj->get(RESTAPI::Protocol::COMMAND).toString()); | 			return; | ||||||
| 			if (Command == RESTAPI::Protocol::SETLOGLEVEL) { |  | ||||||
| 				if (Obj->has(RESTAPI::Protocol::SUBSYSTEMS) && | 		if (Request.getMethod() == Poco::Net::HTTPRequest::HTTP_POST) | ||||||
| 					Obj->isArray(RESTAPI::Protocol::SUBSYSTEMS)) { | 			DoPost(Request, Response); | ||||||
| 					auto ParametersBlock = Obj->getArray(RESTAPI::Protocol::SUBSYSTEMS); | 		else if(Request.getMethod()==Poco::Net::HTTPRequest::HTTP_GET) | ||||||
| 					for (const auto &i : *ParametersBlock) { | 			DoGet(Request, Response); | ||||||
| 						Poco::JSON::Parser pp; |  | ||||||
| 						auto InnerObj = pp.parse(i).extract<Poco::JSON::Object::Ptr>(); | 		BadRequest(Request, Response); | ||||||
| 						if (InnerObj->has(RESTAPI::Protocol::TAG) && | 	} | ||||||
| 							InnerObj->has(RESTAPI::Protocol::VALUE)) { |  | ||||||
| 							auto Name = GetS(RESTAPI::Protocol::TAG, InnerObj); | 	void RESTAPI_system_command::DoPost(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) { | ||||||
| 							auto Value = GetS(RESTAPI::Protocol::VALUE, InnerObj); | 		try { | ||||||
| 							Daemon()->SetSubsystemLogLevel(Name, Value); | 			Poco::JSON::Parser parser; | ||||||
| 							Logger_.information( | 			auto Obj = parser.parse(Request.stream()).extract<Poco::JSON::Object::Ptr>(); | ||||||
| 								Poco::format("Setting log level for %s at %s", Name, Value)); |  | ||||||
|  | 			if (Obj->has(uCentral::RESTAPI::Protocol::COMMAND)) { | ||||||
|  | 				auto Command = Poco::toLower(Obj->get(uCentral::RESTAPI::Protocol::COMMAND).toString()); | ||||||
|  | 				if (Command == uCentral::RESTAPI::Protocol::SETLOGLEVEL) { | ||||||
|  | 					if (Obj->has(uCentral::RESTAPI::Protocol::PARAMETERS) && | ||||||
|  | 						Obj->isArray(uCentral::RESTAPI::Protocol::PARAMETERS)) { | ||||||
|  | 						auto ParametersBlock = Obj->getArray(uCentral::RESTAPI::Protocol::PARAMETERS); | ||||||
|  | 						for (const auto &i:*ParametersBlock) { | ||||||
|  | 							Poco::JSON::Parser pp; | ||||||
|  | 							auto InnerObj = pp.parse(i).extract<Poco::JSON::Object::Ptr>(); | ||||||
|  | 							if (InnerObj->has(uCentral::RESTAPI::Protocol::TAG) && | ||||||
|  | 								InnerObj->has(uCentral::RESTAPI::Protocol::VALUE)) { | ||||||
|  | 								auto Name = GetS(uCentral::RESTAPI::Protocol::TAG, InnerObj); | ||||||
|  | 								auto Value = GetS(uCentral::RESTAPI::Protocol::VALUE, InnerObj); | ||||||
|  | 								Daemon()->SetSubsystemLogLevel(Name, Value); | ||||||
|  | 								Logger_.information(Poco::format("Setting log level for %s at %s", Name, Value)); | ||||||
|  | 							} | ||||||
| 						} | 						} | ||||||
|  | 						OK(Request, Response); | ||||||
|  | 						return; | ||||||
| 					} | 					} | ||||||
| 					OK(); | 				} else if (Command == uCentral::RESTAPI::Protocol::GETLOGLEVELS) { | ||||||
|  | 					auto CurrentLogLevels = Daemon()->GetLogLevels(); | ||||||
|  | 					Poco::JSON::Object	Result; | ||||||
|  | 					Poco::JSON::Array	Array; | ||||||
|  | 					for(auto &[Name,Level]:CurrentLogLevels) { | ||||||
|  | 						Poco::JSON::Object	Pair; | ||||||
|  | 						Pair.set( uCentral::RESTAPI::Protocol::TAG,Name); | ||||||
|  | 						Pair.set(uCentral::RESTAPI::Protocol::VALUE,Level); | ||||||
|  | 						Array.add(Pair); | ||||||
|  | 					} | ||||||
|  | 					Result.set(uCentral::RESTAPI::Protocol::TAGLIST,Array); | ||||||
|  | 					ReturnObject(Request,Result,Response); | ||||||
| 					return; | 					return; | ||||||
| 				} | 				} else if (Command == uCentral::RESTAPI::Protocol::GETLOGLEVELNAMES) { | ||||||
| 			} else if (Command == RESTAPI::Protocol::GETLOGLEVELS) { | 					Poco::JSON::Object	Result; | ||||||
| 				auto CurrentLogLevels = Daemon()->GetLogLevels(); | 					Poco::JSON::Array	LevelNamesArray; | ||||||
| 				Poco::JSON::Object Result; | 					const Types::StringVec & LevelNames = Daemon()->GetLogLevelNames(); | ||||||
| 				Poco::JSON::Array Array; | 					for(const auto &i:LevelNames) | ||||||
| 				for (auto &[Name, Level] : CurrentLogLevels) { | 						LevelNamesArray.add(i); | ||||||
| 					Poco::JSON::Object Pair; | 					Result.set(uCentral::RESTAPI::Protocol::LIST,LevelNamesArray); | ||||||
| 					Pair.set(RESTAPI::Protocol::TAG, Name); | 					ReturnObject(Request,Result,Response); | ||||||
| 					Pair.set(RESTAPI::Protocol::VALUE, Level); | 					return; | ||||||
| 					Array.add(Pair); | 				} else if (Command == uCentral::RESTAPI::Protocol::GETSUBSYSTEMNAMES) { | ||||||
| 				} | 					Poco::JSON::Object	Result; | ||||||
| 				Result.set(RESTAPI::Protocol::TAGLIST, Array); | 					Poco::JSON::Array	LevelNamesArray; | ||||||
| 				ReturnObject(Result); | 					const Types::StringVec & SubSystemNames = Daemon()->GetSubSystems(); | ||||||
| 				return; | 					for(const auto &i:SubSystemNames) | ||||||
| 			} else if (Command == RESTAPI::Protocol::GETLOGLEVELNAMES) { | 						LevelNamesArray.add(i); | ||||||
| 				Poco::JSON::Object Result; | 					Result.set(uCentral::RESTAPI::Protocol::LIST,LevelNamesArray); | ||||||
| 				Poco::JSON::Array LevelNamesArray; | 					ReturnObject(Request,Result,Response); | ||||||
| 				const Types::StringVec &LevelNames = Daemon()->GetLogLevelNames(); | 					return; | ||||||
| 				for (const auto &i : LevelNames) | 				} else if (Command == uCentral::RESTAPI::Protocol::STATS) { | ||||||
| 					LevelNamesArray.add(i); |  | ||||||
| 				Result.set(RESTAPI::Protocol::LIST, LevelNamesArray); |  | ||||||
| 				ReturnObject(Result); |  | ||||||
| 				return; |  | ||||||
| 			} else if (Command == RESTAPI::Protocol::GETSUBSYSTEMNAMES) { |  | ||||||
| 				Poco::JSON::Object Result; |  | ||||||
| 				Poco::JSON::Array LevelNamesArray; |  | ||||||
| 				const Types::StringVec &SubSystemNames = Daemon()->GetSubSystems(); |  | ||||||
| 				for (const auto &i : SubSystemNames) |  | ||||||
| 					LevelNamesArray.add(i); |  | ||||||
| 				Result.set(RESTAPI::Protocol::LIST, LevelNamesArray); |  | ||||||
| 				ReturnObject(Result); |  | ||||||
| 				return; |  | ||||||
| 			} else if (Command == RESTAPI::Protocol::STATS) { |  | ||||||
|  |  | ||||||
| 			} else if (Command == RESTAPI::Protocol::RELOAD) { |  | ||||||
| 				if (Obj->has(RESTAPI::Protocol::SUBSYSTEMS) && |  | ||||||
| 					Obj->isArray(RESTAPI::Protocol::SUBSYSTEMS)) { |  | ||||||
| 					auto SubSystems = Obj->getArray(RESTAPI::Protocol::SUBSYSTEMS); |  | ||||||
| 					std::vector<std::string> Names; |  | ||||||
| 					for (const auto &i : *SubSystems) |  | ||||||
| 						Names.push_back(i.toString()); |  | ||||||
| 						std::thread	ReloadThread([Names](){ |  | ||||||
| 						std::this_thread::sleep_for(10000ms); |  | ||||||
| 						for(const auto &i:Names) { |  | ||||||
| 						    if(i=="daemon") |  | ||||||
| 						        Daemon()->Reload(); |  | ||||||
| 						    else |  | ||||||
|     							Daemon()->Reload(i); |  | ||||||
| 						} |  | ||||||
| 					 }); |  | ||||||
| 					ReloadThread.detach(); |  | ||||||
| 				} | 				} | ||||||
| 				OK(); |  | ||||||
| 				return; |  | ||||||
| 			} | 			} | ||||||
| 		} else { | 		} catch(const Poco::Exception &E) { | ||||||
| 			BadRequest(RESTAPI::Errors::InvalidCommand); | 			Logger_.log(E); | ||||||
| 			return; |  | ||||||
| 		} | 		} | ||||||
| 		BadRequest(RESTAPI::Errors::MissingOrInvalidParameters); | 		BadRequest(Request, Response); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	void RESTAPI_system_command::DoGet() { | 	void RESTAPI_system_command::DoGet(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) { | ||||||
| 		std::string Arg; | 		try { | ||||||
| 		if(HasParameter("command",Arg) && Arg=="info") { | 			ParseParameters(Request); | ||||||
| 			Poco::JSON::Object Answer; | 			auto Command = GetParameter(RESTAPI::Protocol::COMMAND, ""); | ||||||
| 			Answer.set(RESTAPI::Protocol::VERSION, Daemon()->Version()); | 			if (!Poco::icompare(Command, RESTAPI::Protocol::VERSION)) { | ||||||
| 			Answer.set(RESTAPI::Protocol::UPTIME, Daemon()->uptime().totalSeconds()); | 				Poco::JSON::Object Answer; | ||||||
| 			Answer.set(RESTAPI::Protocol::START, Daemon()->startTime().epochTime()); | 				Answer.set(RESTAPI::Protocol::TAG, RESTAPI::Protocol::VERSION); | ||||||
| 			Answer.set(RESTAPI::Protocol::OS, Poco::Environment::osName()); | 				Answer.set(RESTAPI::Protocol::VALUE, Daemon()->Version()); | ||||||
| 			Answer.set(RESTAPI::Protocol::PROCESSORS, Poco::Environment::processorCount()); | 				ReturnObject(Request, Answer, Response); | ||||||
| 			Answer.set(RESTAPI::Protocol::HOSTNAME, Poco::Environment::nodeName()); | 				return; | ||||||
|  |  | ||||||
| 			Poco::JSON::Array   Certificates; |  | ||||||
| 			auto SubSystems = Daemon()->GetFullSubSystems(); |  | ||||||
| 			std::set<std::string>   CertNames; |  | ||||||
|  |  | ||||||
| 			for(const auto &i:SubSystems) { |  | ||||||
| 			    auto Hosts=i->HostSize(); |  | ||||||
| 			    for(uint64_t j=0;j<Hosts;++j) { |  | ||||||
| 			        auto CertFileName = i->Host(j).CertFile(); |  | ||||||
| 			        if(!CertFileName.empty()) { |  | ||||||
| 			            auto InsertResult = CertNames.insert(CertFileName); |  | ||||||
| 			            if(InsertResult.second) { |  | ||||||
| 			                Poco::JSON::Object  Inner; |  | ||||||
| 			                Inner.set("filename", CertFileName); |  | ||||||
| 			                Poco::Crypto::X509Certificate   C(CertFileName); |  | ||||||
| 			                auto ExpiresOn = C.expiresOn(); |  | ||||||
| 			                Inner.set("expiresOn",ExpiresOn.timestamp().epochTime()); |  | ||||||
| 			                Certificates.add(Inner); |  | ||||||
| 			            } |  | ||||||
| 			        } |  | ||||||
| 			    } |  | ||||||
| 			} | 			} | ||||||
| 			Answer.set("certificates", Certificates); | 			if (!Poco::icompare(Command, RESTAPI::Protocol::TIMES)) { | ||||||
| 			ReturnObject(Answer); | 				Poco::JSON::Array	Array; | ||||||
| 			return; | 				Poco::JSON::Object 	Answer; | ||||||
|  | 				Poco::JSON::Object	UpTimeObj; | ||||||
|  | 				UpTimeObj.set(RESTAPI::Protocol::TAG,RESTAPI::Protocol::UPTIME); | ||||||
|  | 				UpTimeObj.set(RESTAPI::Protocol::VALUE, Daemon()->uptime().totalSeconds()); | ||||||
|  | 				Poco::JSON::Object	StartObj; | ||||||
|  | 				StartObj.set(RESTAPI::Protocol::TAG,RESTAPI::Protocol::START); | ||||||
|  | 				StartObj.set(RESTAPI::Protocol::VALUE, Daemon()->startTime().epochTime()); | ||||||
|  | 				Array.add(UpTimeObj); | ||||||
|  | 				Array.add(StartObj); | ||||||
|  | 				Answer.set(RESTAPI::Protocol::TIMES, Array); | ||||||
|  | 				ReturnObject(Request, Answer, Response); | ||||||
|  | 				return; | ||||||
|  | 			} | ||||||
|  | 		} catch (const Poco::Exception &E) { | ||||||
|  | 			Logger_.log(E); | ||||||
| 		} | 		} | ||||||
| 		BadRequest(RESTAPI::Errors::InvalidCommand); | 		BadRequest(Request, Response); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| } | } | ||||||
| @@ -11,22 +11,22 @@ | |||||||
|  |  | ||||||
| #include "RESTAPI_handler.h" | #include "RESTAPI_handler.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
| class RESTAPI_system_command : public RESTAPIHandler { | class RESTAPI_system_command : public RESTAPIHandler { | ||||||
|   public: |   public: | ||||||
|     RESTAPI_system_command(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer & Server, bool Internal) | 	RESTAPI_system_command(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal) | ||||||
| 		: RESTAPIHandler(bindings, L, | 		: RESTAPIHandler(bindings, L, | ||||||
| 						 std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_POST, | 						 std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_POST, | ||||||
| 														  Poco::Net::HTTPRequest::HTTP_GET, | 														  Poco::Net::HTTPRequest::HTTP_GET, | ||||||
| 														  Poco::Net::HTTPRequest::HTTP_OPTIONS}, | 														  Poco::Net::HTTPRequest::HTTP_OPTIONS}, | ||||||
| 														  Server, |  | ||||||
| 						 Internal) {} | 						 Internal) {} | ||||||
|  | 	void handleRequest(Poco::Net::HTTPServerRequest &request, | ||||||
|  | 					   Poco::Net::HTTPServerResponse &response) override; | ||||||
| 	static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/system"};} | 	static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/system"};} | ||||||
|  | 	void DoGet(Poco::Net::HTTPServerRequest &Request, | ||||||
| 	void DoGet() final; | 			   Poco::Net::HTTPServerResponse &Response); | ||||||
| 	void DoPost() final; | 	void DoPost(Poco::Net::HTTPServerRequest &Request, | ||||||
| 	void DoPut() final {}; | 				Poco::Net::HTTPServerResponse &Response); | ||||||
| 	void DoDelete() final {}; |  | ||||||
| 	}; | 	}; | ||||||
| } | } | ||||||
| #endif // UCENTRALGW_RESTAPI_SYSTEM_COMMAND_H | #endif // UCENTRALGW_RESTAPI_SYSTEM_COMMAND_H | ||||||
|   | |||||||
| @@ -7,180 +7,214 @@ | |||||||
| #include "Poco/JSON/Parser.h" | #include "Poco/JSON/Parser.h" | ||||||
| #include "Utils.h" | #include "Utils.h" | ||||||
| #include "RESTAPI_utils.h" | #include "RESTAPI_utils.h" | ||||||
| #include "RESTAPI_errors.h" |  | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|     void RESTAPI_user_handler::DoGet() { |     void RESTAPI_user_handler::handleRequest(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) { | ||||||
|         std::string Id = GetBinding("id", ""); |  | ||||||
|         if(Id.empty()) { |  | ||||||
|             BadRequest(RESTAPI::Errors::MissingUserID); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         SecurityObjects::UserInfo   UInfo; |         if (!ContinueProcessing(Request, Response)) | ||||||
|         if(!Storage()->GetUserById(Id,UInfo)) { |  | ||||||
|             NotFound(); |  | ||||||
|             return; |             return; | ||||||
|         } |  | ||||||
|         Poco::JSON::Object  UserInfoObject; |         if (!IsAuthorized(Request, Response)) | ||||||
|         UInfo.to_json(UserInfoObject); |             return; | ||||||
|         ReturnObject(UserInfoObject); |  | ||||||
|  |         ParseParameters(Request); | ||||||
|  |         if(Request.getMethod()==Poco::Net::HTTPRequest::HTTP_GET) | ||||||
|  |             DoGet(Request, Response); | ||||||
|  |         else if(Request.getMethod()==Poco::Net::HTTPRequest::HTTP_POST) | ||||||
|  |             DoPost(Request, Response); | ||||||
|  |         else if(Request.getMethod()==Poco::Net::HTTPRequest::HTTP_DELETE) | ||||||
|  |             DoDelete(Request, Response); | ||||||
|  |         else if(Request.getMethod()==Poco::Net::HTTPRequest::HTTP_PUT) | ||||||
|  |             DoPut(Request, Response); | ||||||
|  |         else | ||||||
|  |             BadRequest(Request, Response, "Unimplemented HTTP Operation."); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void RESTAPI_user_handler::DoDelete() { |     void RESTAPI_user_handler::DoGet(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) { | ||||||
|         std::string Id = GetBinding("id", ""); |         try { | ||||||
|         if(Id.empty()) { |             std::string Id = GetBinding("id", ""); | ||||||
|             BadRequest(RESTAPI::Errors::MissingUserID); |             if(Id.empty()) { | ||||||
|             return; |                 BadRequest(Request, Response, "You must supply the ID of the user."); | ||||||
|         } |                 return; | ||||||
|  |             } | ||||||
|  |  | ||||||
|         SecurityObjects::UserInfo UInfo; |             SecurityObjects::UserInfo   UInfo; | ||||||
|         if(!Storage()->GetUserById(Id,UInfo)) { |             if(!Storage()->GetUserById(Id,UInfo)) { | ||||||
|             NotFound(); |                 NotFound(Request, Response); | ||||||
|             return; |                 return; | ||||||
|         } |             } | ||||||
|  |  | ||||||
|         if(!Storage()->DeleteUser(UserInfo_.userinfo.email,Id)) { |             Poco::JSON::Object  UserInfoObject; | ||||||
|             NotFound(); |             UInfo.to_json(UserInfoObject); | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if(AuthService()->DeleteUserFromCache(UInfo.email)) |             ReturnObject(Request, UserInfoObject, Response); | ||||||
|             ; |             return; | ||||||
|         Logger_.information(Poco::format("Remove all tokens for '%s'", UserInfo_.userinfo.email)); |         } catch (const Poco::Exception &E ) { | ||||||
|         Storage()->RevokeAllTokens(UInfo.email); |             Logger_.log(E); | ||||||
|         Logger_.information(Poco::format("User '%s' deleted by '%s'.",Id,UserInfo_.userinfo.email)); |         } | ||||||
|         OK(); |         BadRequest(Request, Response); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void RESTAPI_user_handler::DoPost() { |     void RESTAPI_user_handler::DoDelete(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) { | ||||||
|         std::string Id = GetBinding("id", ""); |         try { | ||||||
|         if(Id!="0") { |             std::string Id = GetBinding("id", ""); | ||||||
|             BadRequest(RESTAPI::Errors::IdMustBe0); |             if(Id.empty()) { | ||||||
|             return; |                 BadRequest(Request, Response, "You must supply the ID of the user."); | ||||||
|         } |  | ||||||
|  |  | ||||||
|         SecurityObjects::UserInfo   UInfo; |  | ||||||
|         RESTAPI_utils::from_request(UInfo,*Request); |  | ||||||
|  |  | ||||||
|         if(UInfo.userRole == SecurityObjects::UNKNOWN) { |  | ||||||
|             BadRequest(RESTAPI::Errors::InvalidUserRole); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         Poco::toLowerInPlace(UInfo.email); |  | ||||||
|         if(!Utils::ValidEMailAddress(UInfo.email)) { |  | ||||||
|             BadRequest(RESTAPI::Errors::InvalidEmailAddress); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if(!UInfo.currentPassword.empty()) { |  | ||||||
|             if(!AuthService()->ValidatePassword(UInfo.currentPassword)) { |  | ||||||
|                 BadRequest(RESTAPI::Errors::InvalidPassword); |  | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|         } |             if(!Storage()->DeleteUser(UserInfo_.userinfo.name,Id)) { | ||||||
|  |                 NotFound(Request, Response); | ||||||
|         if(UInfo.name.empty()) |                 return; | ||||||
|             UInfo.name = UInfo.email; |             } | ||||||
|  |             Logger_.information(Poco::format("User '%s' deleted by '%s'.",Id,UserInfo_.userinfo.email)); | ||||||
|         if(!Storage()->CreateUser(UInfo.email,UInfo)) { |             OK(Request, Response); | ||||||
|             Logger_.information(Poco::format("Could not add user '%s'.",UInfo.email)); |  | ||||||
|             BadRequest(RESTAPI::Errors::RecordNotCreated); |  | ||||||
|             return; |             return; | ||||||
|  |         } catch (const Poco::Exception &E ) { | ||||||
|  |             Logger_.log(E); | ||||||
|         } |         } | ||||||
|  |         BadRequest(Request, Response); | ||||||
|         if(GetParameter("email_verification","false")=="true") { |  | ||||||
|             if(AuthService::VerifyEmail(UInfo)) |  | ||||||
|                 Logger_.information(Poco::format("Verification e-mail requested for %s",UInfo.email)); |  | ||||||
|             Storage()->UpdateUserInfo(UserInfo_.userinfo.email,UInfo.Id,UInfo); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if(!Storage()->GetUserByEmail(UInfo.email, UInfo)) { |  | ||||||
|             Logger_.information(Poco::format("User '%s' but not retrieved.",UInfo.email)); |  | ||||||
|             NotFound(); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         Poco::JSON::Object  UserInfoObject; |  | ||||||
|         UInfo.to_json(UserInfoObject); |  | ||||||
|  |  | ||||||
|         ReturnObject(UserInfoObject); |  | ||||||
|  |  | ||||||
|         Logger_.information(Poco::format("User '%s' has been added by '%s')",UInfo.email, UserInfo_.userinfo.email)); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void RESTAPI_user_handler::DoPut() { |     void RESTAPI_user_handler::DoPost(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) { | ||||||
|         std::string Id = GetBinding("id", ""); |         try { | ||||||
|         if(Id.empty()) { |             std::string Id = GetBinding("id", ""); | ||||||
|             BadRequest(RESTAPI::Errors::MissingUserID); |             if(Id!="0") { | ||||||
|             return; |                 BadRequest(Request, Response, "To create a user, you must set the ID to 0"); | ||||||
|         } |  | ||||||
|  |  | ||||||
|         SecurityObjects::UserInfo   LocalObject; |  | ||||||
|         if(!Storage()->GetUserById(Id,LocalObject)) { |  | ||||||
|             NotFound(); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         // some basic validations |  | ||||||
|         auto RawObject = ParseStream(); |  | ||||||
|         if(RawObject->has("userRole") && SecurityObjects::UserTypeFromString(RawObject->get("userRole").toString())==SecurityObjects::UNKNOWN) { |  | ||||||
|             BadRequest(RESTAPI::Errors::InvalidUserRole); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         // The only valid things to change are: changePassword, name, |  | ||||||
|         if(RawObject->has("name")) |  | ||||||
|             LocalObject.name = RawObject->get("name").toString(); |  | ||||||
|         if(RawObject->has("description")) |  | ||||||
|             LocalObject.description = RawObject->get("description").toString(); |  | ||||||
|         if(RawObject->has("avatar")) |  | ||||||
|             LocalObject.avatar = RawObject->get("avatar").toString(); |  | ||||||
|         if(RawObject->has("changePassword")) |  | ||||||
|             LocalObject.changePassword = RawObject->get("changePassword").toString()=="true"; |  | ||||||
|         if(RawObject->has("owner")) |  | ||||||
|             LocalObject.owner = RawObject->get("owner").toString(); |  | ||||||
|         if(RawObject->has("location")) |  | ||||||
|             LocalObject.location = RawObject->get("location").toString(); |  | ||||||
|         if(RawObject->has("locale")) |  | ||||||
|             LocalObject.locale = RawObject->get("locale").toString(); |  | ||||||
|         if(RawObject->has("userRole")) |  | ||||||
|             LocalObject.userRole = SecurityObjects::UserTypeFromString(RawObject->get("userRole").toString()); |  | ||||||
|         if(RawObject->has("suspended")) |  | ||||||
|             LocalObject.suspended = RawObject->get("suspended").toString()=="true"; |  | ||||||
|         if(RawObject->has("blackListed")) |  | ||||||
|             LocalObject.blackListed = RawObject->get("blackListed").toString()=="true"; |  | ||||||
|         if(RawObject->has("notes")) { |  | ||||||
|             SecurityObjects::NoteInfoVec NIV; |  | ||||||
|             NIV = RESTAPI_utils::to_object_array<SecurityObjects::NoteInfo>(RawObject->get("notes").toString()); |  | ||||||
|             for(auto const &i:NIV) { |  | ||||||
|                 SecurityObjects::NoteInfo   ii{.created=(uint64_t)std::time(nullptr), .createdBy=UserInfo_.userinfo.email, .note=i.note}; |  | ||||||
|                 LocalObject.notes.push_back(ii); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         if(RawObject->has("currentPassword")) { |  | ||||||
|             if(!AuthService()->ValidatePassword(RawObject->get("currentPassword").toString())) { |  | ||||||
|                 BadRequest(RESTAPI::Errors::InvalidPassword); |  | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|             if(!AuthService()->SetPassword(RawObject->get("currentPassword").toString(),LocalObject)) { |  | ||||||
|                 BadRequest(RESTAPI::Errors::PasswordRejected); |             SecurityObjects::UserInfo   UInfo; | ||||||
|  |             RESTAPI_utils::from_request(UInfo,Request); | ||||||
|  |  | ||||||
|  |             if(UInfo.userRole == SecurityObjects::UNKNOWN) { | ||||||
|  |                 BadRequest(Request, Response, "Invalid userRole."); | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if(GetParameter("email_verification","false")=="true") { |             Poco::toLowerInPlace(UInfo.email); | ||||||
|             if(AuthService::VerifyEmail(LocalObject)) |             if(!Utils::ValidEMailAddress(UInfo.email)) { | ||||||
|                 Logger_.information(Poco::format("Verification e-mail requested for %s",LocalObject.email)); |                 BadRequest(Request, Response, "Invalid email address."); | ||||||
|         } |                 return; | ||||||
|  |             } | ||||||
|  |  | ||||||
|         if(Storage()->UpdateUserInfo(UserInfo_.userinfo.email,Id,LocalObject)) { |             if(!UInfo.currentPassword.empty()) { | ||||||
|             Poco::JSON::Object  ModifiedObject; |                 if(!AuthService()->ValidatePassword(UInfo.currentPassword)) { | ||||||
|             LocalObject.to_json(ModifiedObject); |                     BadRequest(Request, Response, "Invalid password."); | ||||||
|             ReturnObject(ModifiedObject); |                     return; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if(UInfo.name.empty()) | ||||||
|  |                 UInfo.name = UInfo.email; | ||||||
|  |  | ||||||
|  |             if(!Storage()->CreateUser(UserInfo_.userinfo.name,UInfo)) { | ||||||
|  |                 Logger_.information(Poco::format("Could not add user '%s'.",UInfo.email)); | ||||||
|  |                 BadRequest(Request, Response); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if(GetParameter("email_verification","false")=="true") { | ||||||
|  |                 if(AuthService::VerifyEmail(UInfo)) | ||||||
|  |                     Logger_.information(Poco::format("Verification e-mail requested for %s",UInfo.email)); | ||||||
|  |                 Storage()->UpdateUserInfo(UserInfo_.userinfo.email,UInfo.Id,UInfo); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if(!Storage()->GetUserByEmail(UInfo.email, UInfo)) { | ||||||
|  |                 Logger_.information(Poco::format("User '%s' but not retrieved.",UInfo.email)); | ||||||
|  |                 BadRequest(Request, Response); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             Poco::JSON::Object  UserInfoObject; | ||||||
|  |             UInfo.to_json(UserInfoObject); | ||||||
|  |  | ||||||
|  |             ReturnObject(Request, UserInfoObject, Response); | ||||||
|  |  | ||||||
|  |             Logger_.information(Poco::format("User '%s' has been added by '%s')",UInfo.email, UserInfo_.userinfo.email)); | ||||||
|             return; |             return; | ||||||
|  |         } catch (const Poco::Exception &E ) { | ||||||
|  |             Logger_.log(E); | ||||||
|         } |         } | ||||||
|         BadRequest(RESTAPI::Errors::RecordNotUpdated); |         BadRequest(Request, Response); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void RESTAPI_user_handler::DoPut(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) { | ||||||
|  |         try { | ||||||
|  |             std::string Id = GetBinding("id", ""); | ||||||
|  |             if(Id.empty()) { | ||||||
|  |                 BadRequest(Request, Response, "You must supply the ID of the user."); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             SecurityObjects::UserInfo   LocalObject; | ||||||
|  |             if(!Storage()->GetUserById(Id,LocalObject)) { | ||||||
|  |                 NotFound(Request, Response); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             // some basic validations | ||||||
|  |             Poco::JSON::Parser IncomingParser; | ||||||
|  |             auto RawObject = IncomingParser.parse(Request.stream()).extract<Poco::JSON::Object::Ptr>(); | ||||||
|  |  | ||||||
|  |             if(RawObject->has("userRole") && SecurityObjects::UserTypeFromString(RawObject->get("userRole").toString())==SecurityObjects::UNKNOWN) { | ||||||
|  |                 BadRequest(Request, Response, "Bad userRole value."); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             // The only valid things to change are: changePassword, name, | ||||||
|  |             if(RawObject->has("name")) | ||||||
|  |                 LocalObject.name = RawObject->get("name").toString(); | ||||||
|  |             if(RawObject->has("description")) | ||||||
|  |                 LocalObject.description = RawObject->get("description").toString(); | ||||||
|  |             if(RawObject->has("avatar")) | ||||||
|  |                 LocalObject.avatar = RawObject->get("avatar").toString(); | ||||||
|  |             if(RawObject->has("changePassword")) | ||||||
|  |                 LocalObject.changePassword = RawObject->get("changePassword").toString()=="true"; | ||||||
|  |             if(RawObject->has("owner")) | ||||||
|  |                 LocalObject.owner = RawObject->get("owner").toString(); | ||||||
|  |             if(RawObject->has("location")) | ||||||
|  |                 LocalObject.location = RawObject->get("location").toString(); | ||||||
|  |             if(RawObject->has("locale")) | ||||||
|  |                 LocalObject.locale = RawObject->get("locale").toString(); | ||||||
|  |             if(RawObject->has("userRole")) | ||||||
|  |                 LocalObject.userRole = SecurityObjects::UserTypeFromString(RawObject->get("userRole").toString()); | ||||||
|  |             if(RawObject->has("suspended")) | ||||||
|  |                 LocalObject.suspended = RawObject->get("suspended").toString()=="true"; | ||||||
|  |             if(RawObject->has("blackListed")) | ||||||
|  |                 LocalObject.blackListed = RawObject->get("blackListed").toString()=="true"; | ||||||
|  |             if(RawObject->has("notes")) { | ||||||
|  |                 SecurityObjects::NoteInfoVec NIV; | ||||||
|  |                 NIV = RESTAPI_utils::to_object_array<SecurityObjects::NoteInfo>(RawObject->get("notes").toString()); | ||||||
|  |                 for(auto const &i:NIV) { | ||||||
|  |                     SecurityObjects::NoteInfo   ii{.created=(uint64_t)std::time(nullptr), .createdBy=UserInfo_.userinfo.email, .note=i.note}; | ||||||
|  |                     LocalObject.notes.push_back(ii); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             if(RawObject->has("currentPassword")) { | ||||||
|  |                 if(!AuthService()->ValidatePassword(RawObject->get("currentPassword").toString())) { | ||||||
|  |                     BadRequest(Request, Response, "Invalid password."); | ||||||
|  |                     return; | ||||||
|  |                 } | ||||||
|  |                 if(!AuthService()->SetPassword(RawObject->get("currentPassword").toString(),LocalObject)) { | ||||||
|  |                     BadRequest(Request, Response, "Password was rejected. This maybe an old password."); | ||||||
|  |                     return; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if(GetParameter("email_verification","false")=="true") { | ||||||
|  |                 if(AuthService::VerifyEmail(LocalObject)) | ||||||
|  |                     Logger_.information(Poco::format("Verification e-mail requested for %s",LocalObject.email)); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if(Storage()->UpdateUserInfo(UserInfo_.userinfo.email,Id,LocalObject)) { | ||||||
|  |                 Poco::JSON::Object  ModifiedObject; | ||||||
|  |                 LocalObject.to_json(ModifiedObject); | ||||||
|  |                 ReturnObject(Request, ModifiedObject, Response); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |         } catch( const Poco::Exception &E) { | ||||||
|  |             Logger_.log(E); | ||||||
|  |         } | ||||||
|  |         BadRequest(Request, Response, "Request rejected."); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -7,10 +7,10 @@ | |||||||
|  |  | ||||||
| #include "RESTAPI_handler.h" | #include "RESTAPI_handler.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|     class RESTAPI_user_handler : public RESTAPIHandler { |     class RESTAPI_user_handler : public RESTAPIHandler { | ||||||
|     public: |     public: | ||||||
|         RESTAPI_user_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, bool Internal) |         RESTAPI_user_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, bool Internal) | ||||||
|                 : RESTAPIHandler(bindings, L, |                 : RESTAPIHandler(bindings, L, | ||||||
|                                  std::vector<std::string> |                                  std::vector<std::string> | ||||||
|                                          {Poco::Net::HTTPRequest::HTTP_POST, |                                          {Poco::Net::HTTPRequest::HTTP_POST, | ||||||
| @@ -18,13 +18,13 @@ namespace OpenWifi { | |||||||
|                                           Poco::Net::HTTPRequest::HTTP_PUT, |                                           Poco::Net::HTTPRequest::HTTP_PUT, | ||||||
|                                           Poco::Net::HTTPRequest::HTTP_DELETE, |                                           Poco::Net::HTTPRequest::HTTP_DELETE, | ||||||
|                                           Poco::Net::HTTPRequest::HTTP_OPTIONS}, |                                           Poco::Net::HTTPRequest::HTTP_OPTIONS}, | ||||||
|                                           Server, |  | ||||||
|                                           Internal) {} |                                           Internal) {} | ||||||
|  |         void handleRequest(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) override; | ||||||
|         static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/user/{id}"}; }; |         static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/user/{id}"}; }; | ||||||
|         void DoGet() final; |         void DoGet(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response); | ||||||
|         void DoPost() final; |         void DoDelete(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response); | ||||||
|         void DoDelete() final; |         void DoPost(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response); | ||||||
|         void DoPut() final; |         void DoPut(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response); | ||||||
|     private: |     private: | ||||||
|  |  | ||||||
|     }; |     }; | ||||||
|   | |||||||
| @@ -7,47 +7,67 @@ | |||||||
| #include "RESTAPI_protocol.h" | #include "RESTAPI_protocol.h" | ||||||
| #include "Utils.h" | #include "Utils.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|     void RESTAPI_users_handler::DoGet() { |     void RESTAPI_users_handler::handleRequest(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) { | ||||||
|         std::vector<SecurityObjects::UserInfo> Users; |         if (!ContinueProcessing(Request, Response)) | ||||||
|         bool IdOnly = (GetParameter("idOnly","false")=="true"); |             return; | ||||||
|  |  | ||||||
|         if(QB_.Select.empty()) { |         if (!IsAuthorized(Request, Response)) | ||||||
|             Poco::JSON::Array ArrayObj; |             return; | ||||||
|             Poco::JSON::Object Answer; |  | ||||||
|             if (Storage()->GetUsers(QB_.Offset, QB_.Limit, Users)) { |         ParseParameters(Request); | ||||||
|                 for (const auto &i : Users) { |         if(Request.getMethod()==Poco::Net::HTTPRequest::HTTP_GET) | ||||||
|                     Poco::JSON::Object Obj; |             DoGet(Request, Response); | ||||||
|                     if (IdOnly) { |         else | ||||||
|                         ArrayObj.add(i.Id); |             BadRequest(Request, Response); | ||||||
|                     } else { |     } | ||||||
|                         i.to_json(Obj); |  | ||||||
|                         ArrayObj.add(Obj); |     void RESTAPI_users_handler::DoGet(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) { | ||||||
|  |         try { | ||||||
|  |             std::vector<SecurityObjects::UserInfo> Users; | ||||||
|  |             InitQueryBlock(); | ||||||
|  |             bool IdOnly = (GetParameter("idOnly","false")=="true"); | ||||||
|  |  | ||||||
|  |             if(QB_.Select.empty()) { | ||||||
|  |                 if (Storage()->GetUsers(QB_.Offset, QB_.Limit, Users)) { | ||||||
|  |                     Poco::JSON::Array ArrayObj; | ||||||
|  |                     for (const auto &i : Users) { | ||||||
|  |                         Poco::JSON::Object Obj; | ||||||
|  |                         if (IdOnly) { | ||||||
|  |                             ArrayObj.add(i.Id); | ||||||
|  |                         } else { | ||||||
|  |                             i.to_json(Obj); | ||||||
|  |                             ArrayObj.add(Obj); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                     Poco::JSON::Object RetObj; | ||||||
|  |                     RetObj.set(uCentral::RESTAPI::Protocol::USERS, ArrayObj); | ||||||
|  |                     ReturnObject(Request, RetObj, Response); | ||||||
|  |                     return; | ||||||
|  |                 } | ||||||
|  |             } else { | ||||||
|  |                 Types::StringVec IDs = Utils::Split(QB_.Select); | ||||||
|  |                 Poco::JSON::Array ArrayObj; | ||||||
|  |                 for(auto &i:IDs) { | ||||||
|  |                     SecurityObjects::UserInfo   UInfo; | ||||||
|  |                     if(Storage()->GetUserById(i,UInfo)) { | ||||||
|  |                         Poco::JSON::Object Obj; | ||||||
|  |                         if (IdOnly) { | ||||||
|  |                             ArrayObj.add(UInfo.Id); | ||||||
|  |                         } else { | ||||||
|  |                             UInfo.to_json(Obj); | ||||||
|  |                             ArrayObj.add(Obj); | ||||||
|  |                         } | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 Answer.set(RESTAPI::Protocol::USERS, ArrayObj); |                 Poco::JSON::Object RetObj; | ||||||
|  |                 RetObj.set(uCentral::RESTAPI::Protocol::USERS, ArrayObj); | ||||||
|  |                 ReturnObject(Request, RetObj, Response); | ||||||
|  |                 return; | ||||||
|             } |             } | ||||||
|             ReturnObject(Answer); |         } catch ( const Poco::Exception &E ) { | ||||||
|             return; |             Logger_.log(E); | ||||||
|         } else { |  | ||||||
|             Types::StringVec IDs = Utils::Split(QB_.Select); |  | ||||||
|             Poco::JSON::Array ArrayObj; |  | ||||||
|             for(auto &i:IDs) { |  | ||||||
|                 SecurityObjects::UserInfo   UInfo; |  | ||||||
|                 if(Storage()->GetUserById(i,UInfo)) { |  | ||||||
|                     Poco::JSON::Object Obj; |  | ||||||
|                     if (IdOnly) { |  | ||||||
|                         ArrayObj.add(UInfo.Id); |  | ||||||
|                     } else { |  | ||||||
|                         UInfo.to_json(Obj); |  | ||||||
|                         ArrayObj.add(Obj); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             Poco::JSON::Object RetObj; |  | ||||||
|             RetObj.set(RESTAPI::Protocol::USERS, ArrayObj); |  | ||||||
|             ReturnObject(RetObj); |  | ||||||
|             return; |  | ||||||
|         } |         } | ||||||
|  |         BadRequest(Request, Response); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -7,21 +7,18 @@ | |||||||
|  |  | ||||||
| #include "RESTAPI_handler.h" | #include "RESTAPI_handler.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|     class RESTAPI_users_handler : public RESTAPIHandler { |     class RESTAPI_users_handler : public RESTAPIHandler { | ||||||
|     public: |     public: | ||||||
|         RESTAPI_users_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, bool Internal) |         RESTAPI_users_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, 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, |  | ||||||
|                                   Internal) {} |                                   Internal) {} | ||||||
|  |         void handleRequest(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) override; | ||||||
|         static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/users"}; }; |         static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/users"}; }; | ||||||
|         void DoGet() final; |         void DoGet(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response); | ||||||
|         void DoPost() final {}; |  | ||||||
|         void DoDelete() final {}; |  | ||||||
|         void DoPut() final {}; |  | ||||||
|     }; |     }; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ | |||||||
|  |  | ||||||
| #include "RESTAPI_utils.h" | #include "RESTAPI_utils.h" | ||||||
|  |  | ||||||
| namespace OpenWifi::RESTAPI_utils { | namespace uCentral::RESTAPI_utils { | ||||||
|  |  | ||||||
| 	void EmbedDocument(const std::string & ObjName, Poco::JSON::Object & Obj, const std::string &ObjStr) { | 	void EmbedDocument(const std::string & ObjName, Poco::JSON::Object & Obj, const std::string &ObjStr) { | ||||||
| 		std::string D = ObjStr.empty() ? "{}" : ObjStr; | 		std::string D = ObjStr.empty() ? "{}" : ObjStr; | ||||||
|   | |||||||
| @@ -9,10 +9,10 @@ | |||||||
| #include "Poco/JSON/Object.h" | #include "Poco/JSON/Object.h" | ||||||
| #include "Poco/JSON/Parser.h" | #include "Poco/JSON/Parser.h" | ||||||
| #include "Poco/Net/HTTPServerRequest.h" | #include "Poco/Net/HTTPServerRequest.h" | ||||||
| #include "OpenWifiTypes.h" | #include "uCentralTypes.h" | ||||||
| #include "Utils.h" | #include "Utils.h" | ||||||
|  |  | ||||||
| namespace OpenWifi::RESTAPI_utils { | namespace uCentral::RESTAPI_utils { | ||||||
|  |  | ||||||
| 	void EmbedDocument(const std::string & ObjName, Poco::JSON::Object & Obj, const std::string &ObjStr); | 	void EmbedDocument(const std::string & ObjName, Poco::JSON::Object & Obj, const std::string &ObjStr); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -7,22 +7,35 @@ | |||||||
| #include "AuthService.h" | #include "AuthService.h" | ||||||
| #include "Utils.h" | #include "Utils.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|     void RESTAPI_validateToken_handler::DoGet() { |     void RESTAPI_validateToken_handler::handleRequest(Poco::Net::HTTPServerRequest &Request, | ||||||
|         Poco::URI URI(Request->getURI()); |                                                       Poco::Net::HTTPServerResponse &Response) { | ||||||
|         auto Parameters = URI.getQueryParameters(); |  | ||||||
|         for(auto const &i:Parameters) { |         if (!ContinueProcessing(Request, Response)) | ||||||
|             if (i.first == "token") { |             return; | ||||||
|                 //  can we find this token? |  | ||||||
|                 SecurityObjects::UserInfoAndPolicy SecObj; |         if (!IsAuthorized(Request, Response)) | ||||||
|                 if (AuthService()->IsValidToken(i.second, SecObj.webtoken, SecObj.userinfo)) { |             return; | ||||||
|                     Poco::JSON::Object Obj; |  | ||||||
|                     SecObj.to_json(Obj); |         try { | ||||||
|                     ReturnObject(Obj); |             Poco::URI URI(Request.getURI()); | ||||||
|                     return; |             auto Parameters = URI.getQueryParameters(); | ||||||
|  |             for(auto const &i:Parameters) { | ||||||
|  |                 if (i.first == "token") { | ||||||
|  |                     //  can we find this token? | ||||||
|  |                     SecurityObjects::UserInfoAndPolicy SecObj; | ||||||
|  |                     if (AuthService()->IsValidToken(i.first, SecObj.webtoken, SecObj.userinfo)) { | ||||||
|  |                         Poco::JSON::Object Obj; | ||||||
|  |                         SecObj.to_json(Obj); | ||||||
|  |                         ReturnObject(Request, Obj, Response); | ||||||
|  |                         return; | ||||||
|  |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |             NotFound(Request, Response); | ||||||
|  |         } catch (const Poco::Exception &E) { | ||||||
|  |             Logger_.log(E); | ||||||
|         } |         } | ||||||
|         NotFound(); |         BadRequest(Request, Response); | ||||||
|     } |     }; | ||||||
| } | } | ||||||
| @@ -7,21 +7,18 @@ | |||||||
|  |  | ||||||
| #include "RESTAPI_handler.h" | #include "RESTAPI_handler.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|     class RESTAPI_validateToken_handler : public RESTAPIHandler { |     class RESTAPI_validateToken_handler : public RESTAPIHandler { | ||||||
|     public: |     public: | ||||||
|         RESTAPI_validateToken_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, bool Internal) |         RESTAPI_validateToken_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, 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, |  | ||||||
|                                           Internal) {}; |                                           Internal) {}; | ||||||
|  |  | ||||||
|  |         void handleRequest(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) override; | ||||||
|         static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/validateToken"}; }; |         static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/validateToken"}; }; | ||||||
|         void DoGet() final; |  | ||||||
|         void DoPost() final {}; |  | ||||||
|         void DoDelete() final {}; |  | ||||||
|         void DoPut() final {}; |  | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -20,22 +20,17 @@ | |||||||
| #include "Utils.h" | #include "Utils.h" | ||||||
| #include "Daemon.h" | #include "Daemon.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|  |  | ||||||
|     class SMTPMailerService * SMTPMailerService::instance_ = nullptr; |     class SMTPMailerService * SMTPMailerService::instance_ = nullptr; | ||||||
|  |  | ||||||
|     void SMTPMailerService::LoadMyConfig() { |     int SMTPMailerService::Start() { | ||||||
|         MailHost_ = Daemon()->ConfigGetString("mailer.hostname"); |         MailHost_ = Daemon()->ConfigGetString("mailer.hostname"); | ||||||
|         SenderLoginUserName_ = Daemon()->ConfigGetString("mailer.username"); |         SenderLoginUserName_ = Daemon()->ConfigGetString("mailer.username"); | ||||||
|         SenderLoginPassword_ = Daemon()->ConfigGetString("mailer.password"); |         SenderLoginPassword_ = Daemon()->ConfigGetString("mailer.password"); | ||||||
|         Sender_ = Daemon()->ConfigGetString("mailer.sender"); |  | ||||||
|         LoginMethod_ = Daemon()->ConfigGetString("mailer.loginmethod"); |         LoginMethod_ = Daemon()->ConfigGetString("mailer.loginmethod"); | ||||||
|         MailHostPort_ = (int)Daemon()->ConfigGetInt("mailer.port"); |         MailHostPort_ = (int)Daemon()->ConfigGetInt("mailer.port"); | ||||||
|         TemplateDir_ = Daemon()->ConfigPath("mailer.templates", Daemon()->DataDir()); |         TemplateDir_ = Daemon()->ConfigPath("mailer.templates", Daemon()->DataDir()); | ||||||
|     } |  | ||||||
|  |  | ||||||
|     int SMTPMailerService::Start() { |  | ||||||
|         LoadMyConfig(); |  | ||||||
|         SenderThr_.start(*this); |         SenderThr_.start(*this); | ||||||
|         return 0; |         return 0; | ||||||
|     } |     } | ||||||
| @@ -46,14 +41,8 @@ namespace OpenWifi { | |||||||
|         SenderThr_.join(); |         SenderThr_.join(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void SMTPMailerService::reinitialize(Poco::Util::Application &self) { |  | ||||||
|         Daemon()->LoadConfigurationFile(); |  | ||||||
|         Logger_.information("Reinitializing."); |  | ||||||
|         LoadMyConfig(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     bool SMTPMailerService::SendMessage(const std::string &Recipient, const std::string &Name, const MessageAttributes &Attrs) { |     bool SMTPMailerService::SendMessage(const std::string &Recipient, const std::string &Name, const MessageAttributes &Attrs) { | ||||||
|         std::lock_guard G(Mutex_); |         SubMutexGuard G(Mutex_); | ||||||
|  |  | ||||||
|         uint64_t Now = std::time(nullptr); |         uint64_t Now = std::time(nullptr); | ||||||
|         auto CE = Cache_.find(Poco::toLower(Recipient)); |         auto CE = Cache_.find(Poco::toLower(Recipient)); | ||||||
| @@ -71,18 +60,17 @@ namespace OpenWifi { | |||||||
|                                             .File=Poco::File(TemplateDir_ + "/" +Name), |                                             .File=Poco::File(TemplateDir_ + "/" +Name), | ||||||
|                                             .Attrs=Attrs}); |                                             .Attrs=Attrs}); | ||||||
|  |  | ||||||
|         return true; |         return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void SMTPMailerService::run() { |     void SMTPMailerService::run() { | ||||||
|  |  | ||||||
|         Running_ = true; |         Running_ = true; | ||||||
|         while(Running_) { |         while(Running_) { | ||||||
|             Poco::Thread::trySleep(10000); |             Poco::Thread::trySleep(2000); | ||||||
|             if(!Running_) |  | ||||||
|                 break; |  | ||||||
|             { |             { | ||||||
|                 std::lock_guard G(Mutex_); |                 SubMutexGuard G(Mutex_); | ||||||
|  |  | ||||||
|                 uint64_t Now = std::time(nullptr); |                 uint64_t Now = std::time(nullptr); | ||||||
|  |  | ||||||
| @@ -118,16 +106,11 @@ namespace OpenWifi { | |||||||
|             Message.addRecipient(Poco::Net::MailRecipient(Poco::Net::MailRecipient::PRIMARY_RECIPIENT, Recipient)); |             Message.addRecipient(Poco::Net::MailRecipient(Poco::Net::MailRecipient::PRIMARY_RECIPIENT, Recipient)); | ||||||
|             Message.setSubject(Msg.Attrs.find(SUBJECT)->second); |             Message.setSubject(Msg.Attrs.find(SUBJECT)->second); | ||||||
|  |  | ||||||
|             if(Msg.Attrs.find(TEXT) != Msg.Attrs.end()) { |             std::string Content = Utils::LoadFile(Msg.File); | ||||||
|                 std::string Content = Msg.Attrs.find(TEXT)->second; |             Types::StringPairVec    Variables; | ||||||
|                 Message.addContent(new Poco::Net::StringPartSource(Content)); |             FillVariables(Msg.Attrs, Variables); | ||||||
|             } else { |             Utils::ReplaceVariables(Content, Variables); | ||||||
|                 std::string Content = Utils::LoadFile(Msg.File); |             Message.addContent(new Poco::Net::StringPartSource(Content)); | ||||||
|                 Types::StringPairVec    Variables; |  | ||||||
|                 FillVariables(Msg.Attrs, Variables); |  | ||||||
|                 Utils::ReplaceVariables(Content, Variables); |  | ||||||
|                 Message.addContent(new Poco::Net::StringPartSource(Content)); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             auto Logo = Msg.Attrs.find(LOGO); |             auto Logo = Msg.Attrs.find(LOGO); | ||||||
|             if(Logo!=Msg.Attrs.end()) { |             if(Logo!=Msg.Attrs.end()) { | ||||||
| @@ -165,4 +148,4 @@ namespace OpenWifi { | |||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| } | } | ||||||
| @@ -9,7 +9,7 @@ | |||||||
|  |  | ||||||
| #include "Poco/File.h" | #include "Poco/File.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|  |  | ||||||
|     enum MESSAGE_ATTRIBUTES { |     enum MESSAGE_ATTRIBUTES { | ||||||
|         RECIPIENT_EMAIL, |         RECIPIENT_EMAIL, | ||||||
| @@ -22,8 +22,7 @@ namespace OpenWifi { | |||||||
|         SUBJECT, |         SUBJECT, | ||||||
|         TEMPLATE_TXT, |         TEMPLATE_TXT, | ||||||
|         TEMPLATE_HTML, |         TEMPLATE_HTML, | ||||||
|         LOGO, |         LOGO | ||||||
|         TEXT |  | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     static const std::map<MESSAGE_ATTRIBUTES,const std::string> |     static const std::map<MESSAGE_ATTRIBUTES,const std::string> | ||||||
| @@ -37,9 +36,7 @@ namespace OpenWifi { | |||||||
|                                  {  SUBJECT, "SUBJECT"}, |                                  {  SUBJECT, "SUBJECT"}, | ||||||
|                                  {  TEMPLATE_TXT, "TEMPLATE_TXT"}, |                                  {  TEMPLATE_TXT, "TEMPLATE_TXT"}, | ||||||
|                                  {  TEMPLATE_HTML, "TEMPLATE_HTML"}, |                                  {  TEMPLATE_HTML, "TEMPLATE_HTML"}, | ||||||
|                                  {  LOGO, "LOGO"}, |                                  {  LOGO, "LOGO"}}; | ||||||
|                                  {  TEXT, "TEXT"} |  | ||||||
|                                  }; |  | ||||||
|  |  | ||||||
|     inline const std::string & MessageAttributeToVar(MESSAGE_ATTRIBUTES Attr) { |     inline const std::string & MessageAttributeToVar(MESSAGE_ATTRIBUTES Attr) { | ||||||
|         static const std::string EmptyString{}; |         static const std::string EmptyString{}; | ||||||
| @@ -78,8 +75,7 @@ namespace OpenWifi { | |||||||
|             void Stop() override; |             void Stop() override; | ||||||
|             bool SendMessage(const std::string &Recipient, const std::string &Name, const MessageAttributes &Attrs); |             bool SendMessage(const std::string &Recipient, const std::string &Name, const MessageAttributes &Attrs); | ||||||
|             bool SendIt(const MessageEvent &Msg); |             bool SendIt(const MessageEvent &Msg); | ||||||
|             void LoadMyConfig(); |  | ||||||
|             void reinitialize(Poco::Util::Application &self) override; |  | ||||||
|         private: |         private: | ||||||
|             static SMTPMailerService * instance_; |             static SMTPMailerService * instance_; | ||||||
|             std::string             MailHost_; |             std::string             MailHost_; | ||||||
|   | |||||||
| @@ -11,10 +11,15 @@ | |||||||
| #include "Poco/Util/Application.h" | #include "Poco/Util/Application.h" | ||||||
| #include "Utils.h" | #include "Utils.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|  |  | ||||||
|     class Storage *Storage::instance_ = nullptr; |     class Storage *Storage::instance_ = nullptr; | ||||||
|  |  | ||||||
|  |     Storage::Storage() noexcept: | ||||||
|  |         SubSystemServer("Storage", "STORAGE-SVR", "storage") | ||||||
|  |     { | ||||||
|  |     } | ||||||
|  |  | ||||||
| 	std::string Storage::ConvertParams(const std::string & S) const { | 	std::string Storage::ConvertParams(const std::string & S) const { | ||||||
| 		std::string R; | 		std::string R; | ||||||
|  |  | ||||||
| @@ -38,7 +43,7 @@ namespace OpenWifi { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
|     int Storage::Start() { |     int Storage::Start() { | ||||||
| 		std::lock_guard		Guard(Mutex_); | 		SubMutexGuard		Guard(Mutex_); | ||||||
|  |  | ||||||
| 		Logger_.setLevel(Poco::Message::PRIO_NOTICE); | 		Logger_.setLevel(Poco::Message::PRIO_NOTICE); | ||||||
|         Logger_.notice("Starting."); |         Logger_.notice("Starting."); | ||||||
|   | |||||||
| @@ -24,7 +24,7 @@ | |||||||
| #include "RESTAPI_SecurityObjects.h" | #include "RESTAPI_SecurityObjects.h" | ||||||
| #include "SubSystemServer.h" | #include "SubSystemServer.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|  |  | ||||||
|     static const std::string AllActionLinksFieldsForSelect { |     static const std::string AllActionLinksFieldsForSelect { | ||||||
|             "Id, " |             "Id, " | ||||||
| @@ -154,13 +154,6 @@ namespace OpenWifi { | |||||||
|         bool GetAvatar(const std::string & Admin, std::string &Id, Poco::TemporaryFile &FileName, std::string &Type, std::string & Name); |         bool GetAvatar(const std::string & Admin, std::string &Id, Poco::TemporaryFile &FileName, std::string &Type, std::string & Name); | ||||||
|         bool DeleteAvatar(const std::string & Admin, std::string &Id); |         bool DeleteAvatar(const std::string & Admin, std::string &Id); | ||||||
|  |  | ||||||
|         bool AddToken(std::string &UserName, std::string &Token, std::string &RefreshToken, std::string & TokenType, uint64_t Expires, uint64_t TimeOut); |  | ||||||
|         bool RevokeToken( std::string & Token ); |  | ||||||
|         bool IsTokenRevoked( std::string & Token ); |  | ||||||
|         bool CleanRevokedTokens( uint64_t Oldest ); |  | ||||||
|         bool RevokeAllTokens( std::string & UserName ); |  | ||||||
|         bool GetToken(std::string &Token, SecurityObjects::UserInfoAndPolicy &UInfo); |  | ||||||
|  |  | ||||||
|         /* |         /* | ||||||
|          *  All ActionLinks functions |          *  All ActionLinks functions | ||||||
|          */ |          */ | ||||||
| @@ -183,29 +176,15 @@ namespace OpenWifi { | |||||||
|         int Create_Tables(); |         int Create_Tables(); | ||||||
|         int Create_UserTable(); |         int Create_UserTable(); | ||||||
|         int Create_AvatarTable(); |         int Create_AvatarTable(); | ||||||
|         int Create_TokensTable(); |  | ||||||
|  |  | ||||||
| 		[[nodiscard]] std::string ConvertParams(const std::string &S) const; |  | ||||||
| 		[[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) + " "; |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		Storage() noexcept: |  | ||||||
|             SubSystemServer("Storage", "STORAGE-SVR", "storage") |  | ||||||
|             { |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|         int 	Setup_SQLite(); |         int 	Setup_SQLite(); | ||||||
|  | 		[[nodiscard]] std::string ConvertParams(const std::string &S) const; | ||||||
|  |  | ||||||
|  | #ifndef SMALL_BUILD | ||||||
|         int 	Setup_MySQL(); |         int 	Setup_MySQL(); | ||||||
|         int 	Setup_PostgreSQL(); |         int 	Setup_PostgreSQL(); | ||||||
|  | #endif | ||||||
|  |         Storage() noexcept; | ||||||
|    }; |    }; | ||||||
|  |  | ||||||
|     inline Storage * Storage() { return Storage::instance(); }; |     inline Storage * Storage() { return Storage::instance(); }; | ||||||
|   | |||||||
| @@ -19,7 +19,7 @@ | |||||||
|  |  | ||||||
| #include "Daemon.h" | #include "Daemon.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
| SubSystemServer::SubSystemServer(std::string Name, const std::string &LoggingPrefix, | SubSystemServer::SubSystemServer(std::string Name, const std::string &LoggingPrefix, | ||||||
| 								 std::string SubSystemConfigPrefix) | 								 std::string SubSystemConfigPrefix) | ||||||
| 	: Name_(std::move(Name)), Logger_(Poco::Logger::get(LoggingPrefix)), | 	: Name_(std::move(Name)), Logger_(Poco::Logger::get(LoggingPrefix)), | ||||||
| @@ -32,7 +32,6 @@ void SubSystemServer::initialize(Poco::Util::Application &self) { | |||||||
| 	auto i = 0; | 	auto i = 0; | ||||||
| 	bool good = true; | 	bool good = true; | ||||||
|  |  | ||||||
| 	ConfigServersList_.clear(); |  | ||||||
| 	while (good) { | 	while (good) { | ||||||
| 		std::string root{SubSystemConfigPrefix_ + ".host." + std::to_string(i) + "."}; | 		std::string root{SubSystemConfigPrefix_ + ".host." + std::to_string(i) + "."}; | ||||||
|  |  | ||||||
| @@ -82,11 +81,10 @@ void SubSystemServer::initialize(Poco::Util::Application &self) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| void SubSystemServer::uninitialize() { | void SubSystemServer::uninitialize() {} | ||||||
| } |  | ||||||
|  |  | ||||||
| void SubSystemServer::reinitialize(Poco::Util::Application &self) { | void SubSystemServer::reinitialize(Poco::Util::Application &self) { | ||||||
| 	Logger_.information("Reloading of this subsystem is not supported."); | 	// add your own reinitialization code here | ||||||
| } | } | ||||||
|  |  | ||||||
| void SubSystemServer::defineOptions(Poco::Util::OptionSet &options) {} | void SubSystemServer::defineOptions(Poco::Util::OptionSet &options) {} | ||||||
|   | |||||||
| @@ -20,7 +20,10 @@ | |||||||
|  |  | ||||||
| #include "Poco/Net/X509Certificate.h" | #include "Poco/Net/X509Certificate.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | using SubMutex = std::recursive_mutex; | ||||||
|  | using SubMutexGuard = std::lock_guard<SubMutex>; | ||||||
|  |  | ||||||
|  | namespace uCentral { | ||||||
| class PropertiesFileServerEntry { | class PropertiesFileServerEntry { | ||||||
|   public: |   public: | ||||||
| 	PropertiesFileServerEntry(std::string Address, uint32_t port, std::string Key_file, | 	PropertiesFileServerEntry(std::string Address, uint32_t port, std::string Key_file, | ||||||
| @@ -76,8 +79,7 @@ class SubSystemServer : public Poco::Util::Application::Subsystem { | |||||||
| 	inline const std::string & Name() const { return Name_; }; | 	inline const std::string & Name() const { return Name_; }; | ||||||
| 	const char * name() const override { return Name_.c_str(); } | 	const char * name() const override { return Name_.c_str(); } | ||||||
|  |  | ||||||
| 	const PropertiesFileServerEntry & Host(uint64_t index) { return ConfigServersList_[index]; }; | 	const PropertiesFileServerEntry &Host(int index) { return ConfigServersList_[index]; }; | ||||||
| 	uint64_t HostSize() const { return ConfigServersList_.size(); } |  | ||||||
| 	Poco::Logger &Logger() { return Logger_; }; | 	Poco::Logger &Logger() { return Logger_; }; | ||||||
| 	void SetLoggingLevel(Poco::Message::Priority NewPriority) { Logger_.setLevel(NewPriority); } | 	void SetLoggingLevel(Poco::Message::Priority NewPriority) { Logger_.setLevel(NewPriority); } | ||||||
| 	int GetLoggingLevel() { return Logger_.getLevel(); } | 	int GetLoggingLevel() { return Logger_.getLevel(); } | ||||||
| @@ -85,11 +87,11 @@ class SubSystemServer : public Poco::Util::Application::Subsystem { | |||||||
| 	virtual void Stop() = 0; | 	virtual void Stop() = 0; | ||||||
|  |  | ||||||
|   protected: |   protected: | ||||||
| 	std::recursive_mutex Mutex_; | 	SubMutex Mutex_{}; | ||||||
| 	Poco::Logger 		&Logger_; | 	Poco::Logger &Logger_; | ||||||
| 	std::string 		Name_; | 	std::string Name_; | ||||||
| 	std::vector<PropertiesFileServerEntry> ConfigServersList_; | 	std::vector<PropertiesFileServerEntry> ConfigServersList_; | ||||||
| 	std::string 		SubSystemConfigPrefix_; | 	std::string SubSystemConfigPrefix_; | ||||||
| }; | }; | ||||||
| } | } | ||||||
| #endif //UCENTRAL_SUBSYSTEMSERVER_H | #endif //UCENTRAL_SUBSYSTEMSERVER_H | ||||||
|   | |||||||
| @@ -28,7 +28,7 @@ | |||||||
| #include "uCentralProtocol.h" | #include "uCentralProtocol.h" | ||||||
| #include "Daemon.h" | #include "Daemon.h" | ||||||
|  |  | ||||||
| namespace OpenWifi::Utils { | namespace uCentral::Utils { | ||||||
|  |  | ||||||
| 	[[nodiscard]] bool ValidSerialNumber(const std::string &Serial) { | 	[[nodiscard]] bool ValidSerialNumber(const std::string &Serial) { | ||||||
| 		return ((Serial.size() < uCentralProtocol::SERIAL_NUMBER_LENGTH) && | 		return ((Serial.size() < uCentralProtocol::SERIAL_NUMBER_LENGTH) && | ||||||
| @@ -151,7 +151,7 @@ namespace OpenWifi::Utils { | |||||||
| 		if(input.length() % 4) | 		if(input.length() % 4) | ||||||
| 			throw std::runtime_error("Invalid base64 length!"); | 			throw std::runtime_error("Invalid base64 length!"); | ||||||
|  |  | ||||||
| 		std::size_t padding=0; | 		std::size_t padding{}; | ||||||
|  |  | ||||||
| 		if(input.length()) | 		if(input.length()) | ||||||
| 		{ | 		{ | ||||||
| @@ -162,7 +162,7 @@ namespace OpenWifi::Utils { | |||||||
| 		std::vector<byte> decoded; | 		std::vector<byte> decoded; | ||||||
| 		decoded.reserve(((input.length() / 4) * 3) - padding); | 		decoded.reserve(((input.length() / 4) * 3) - padding); | ||||||
|  |  | ||||||
| 		std::uint32_t temp=0; | 		std::uint32_t temp{}; | ||||||
| 		auto it = input.begin(); | 		auto it = input.begin(); | ||||||
|  |  | ||||||
| 		while(it < input.end()) | 		while(it < input.end()) | ||||||
| @@ -488,4 +488,67 @@ namespace OpenWifi::Utils { | |||||||
| 	    return Result; | 	    return Result; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	static bool cidr_match(const in_addr &addr, const in_addr &net, uint8_t bits) { | ||||||
|  | 		if (bits == 0) { | ||||||
|  | 			return true; | ||||||
|  | 		} | ||||||
|  | 		return !((addr.s_addr ^ net.s_addr) & htonl(0xFFFFFFFFu << (32 - bits))); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	static bool cidr6_match(const in6_addr &address, const in6_addr &network, uint8_t bits) { | ||||||
|  | #ifdef __linux__ | ||||||
|  | 		const uint32_t *a = address.s6_addr32; | ||||||
|  | 		const uint32_t *n = network.s6_addr32; | ||||||
|  | #else | ||||||
|  | 		const uint32_t *a = address.__u6_addr.__u6_addr32; | ||||||
|  | 		const uint32_t *n = network.__u6_addr.__u6_addr32; | ||||||
|  | #endif | ||||||
|  | 		int bits_whole, bits_incomplete; | ||||||
|  | 		bits_whole = bits >> 5;         // number of whole u32 | ||||||
|  | 		bits_incomplete = bits & 0x1F;  // number of bits in incomplete u32 | ||||||
|  | 		if (bits_whole) { | ||||||
|  | 			if (memcmp(a, n, bits_whole << 2)!=0) { | ||||||
|  | 				return false; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		if (bits_incomplete) { | ||||||
|  | 			uint32_t mask = htonl((0xFFFFFFFFu) << (32 - bits_incomplete)); | ||||||
|  | 			if ((a[bits_whole] ^ n[bits_whole]) & mask) { | ||||||
|  | 				return false; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	static bool ConvertStringToLong(const char *S, unsigned long &L) { | ||||||
|  | 		char *end; | ||||||
|  | 		L = std::strtol(S,&end,10); | ||||||
|  | 		return end != S; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	bool IPinRange(const std::string &Range, const Poco::Net::IPAddress &IP) { | ||||||
|  | 		Poco::StringTokenizer	TimeTokens(Range,"/",Poco::StringTokenizer::TOK_TRIM); | ||||||
|  |  | ||||||
|  | 		Poco::Net::IPAddress	RangeIP; | ||||||
|  | 		if(Poco::Net::IPAddress::tryParse(TimeTokens[0],RangeIP)) { | ||||||
|  | 			if(TimeTokens.count()==2) { | ||||||
|  | 				if (RangeIP.family() == Poco::Net::IPAddress::IPv4) { | ||||||
|  | 					unsigned long MaskLength; | ||||||
|  | 					if (ConvertStringToLong(TimeTokens[1].c_str(), MaskLength)) { | ||||||
|  | 						return cidr_match(*static_cast<const in_addr *>(RangeIP.addr()), | ||||||
|  | 										  *static_cast<const in_addr *>(IP.addr()), MaskLength); | ||||||
|  | 					} | ||||||
|  | 				} else if (RangeIP.family() == Poco::Net::IPAddress::IPv6) { | ||||||
|  | 					unsigned long MaskLength; | ||||||
|  | 					if (ConvertStringToLong(TimeTokens[1].c_str(), MaskLength)) { | ||||||
|  | 						return cidr6_match(*static_cast<const in6_addr *>(RangeIP.addr()), | ||||||
|  | 										   *static_cast<const in6_addr *>(IP.addr()), MaskLength); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			return false; | ||||||
|  | 		} | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										18
									
								
								src/Utils.h
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								src/Utils.h
									
									
									
									
									
								
							| @@ -11,18 +11,16 @@ | |||||||
|  |  | ||||||
| #include <vector> | #include <vector> | ||||||
| #include <string> | #include <string> | ||||||
| #include <iomanip> |  | ||||||
| #include <sstream> |  | ||||||
|  |  | ||||||
| #include "Poco/Net/NetworkInterface.h" | #include "Poco/Net/NetworkInterface.h" | ||||||
| #include "Poco/Net/IPAddress.h" | #include "Poco/Net/IPAddress.h" | ||||||
| #include "Poco/String.h" | #include "Poco/String.h" | ||||||
| #include "Poco/File.h" | #include "Poco/File.h" | ||||||
| #include "OpenWifiTypes.h" | #include "uCentralTypes.h" | ||||||
|  |  | ||||||
| #define DBGLINE { std::cout << __FILE__ << ":" << __func__ << ":" << __LINE__ << std::endl; }; | #define DBGLINE { std::cout << __FILE__ << ":" << __func__ << ":" << __LINE__ << std::endl; }; | ||||||
|  |  | ||||||
| namespace OpenWifi::Utils { | namespace uCentral::Utils { | ||||||
|  |  | ||||||
|     enum MediaTypeEncodings { |     enum MediaTypeEncodings { | ||||||
|         PLAIN, |         PLAIN, | ||||||
| @@ -71,17 +69,9 @@ namespace OpenWifi::Utils { | |||||||
|  |  | ||||||
|     [[nodiscard]] MediaTypeEncoding FindMediaType(const Poco::File &F); |     [[nodiscard]] MediaTypeEncoding FindMediaType(const Poco::File &F); | ||||||
|     [[nodiscard]] std::string BinaryFileToHexString( const Poco::File &F); |     [[nodiscard]] std::string BinaryFileToHexString( const Poco::File &F); | ||||||
|  |  | ||||||
|     [[nodiscard]] std::string SecondsToNiceText(uint64_t Seconds); |     [[nodiscard]] std::string SecondsToNiceText(uint64_t Seconds); | ||||||
|  |  | ||||||
| 	template< typename T > | 	[[nodiscard]] bool IPinRange(const std::string &Range, const Poco::Net::IPAddress &IP); | ||||||
| 	std::string int_to_hex( T i ) |  | ||||||
| 	{ |  | ||||||
| 		std::stringstream stream; |  | ||||||
| 		stream << std::setfill ('0') << std::setw(12) |  | ||||||
| 		<< std::hex << i; |  | ||||||
| 		return stream.str(); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
|  |  | ||||||
| } | } | ||||||
| #endif // UCENTRALGW_UTILS_H | #endif // UCENTRALGW_UTILS_H | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ | |||||||
| #include "Poco/Data/LOBStream.h" | #include "Poco/Data/LOBStream.h" | ||||||
| #include "Daemon.h" | #include "Daemon.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|  |  | ||||||
|     /* |     /* | ||||||
|                             "Id			    VARCHAR(36) PRIMARY KEY, " |                             "Id			    VARCHAR(36) PRIMARY KEY, " | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
| #ifndef WLAN_CLOUD_UCENTRALSEC_STORAGE_AVATAR_H | #ifndef WLAN_CLOUD_UCENTRALSEC_STORAGE_AVATAR_H | ||||||
| #define WLAN_CLOUD_UCENTRALSEC_STORAGE_AVATAR_H | #define WLAN_CLOUD_UCENTRALSEC_STORAGE_AVATAR_H | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										46
									
								
								src/storage_mysql.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/storage_mysql.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | |||||||
|  | // | ||||||
|  | //	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 "Daemon.h" | ||||||
|  | #include "StorageService.h" | ||||||
|  |  | ||||||
|  | namespace uCentral { | ||||||
|  |  | ||||||
|  | #ifdef	SMALL_BUILD | ||||||
|  | 	int Service::Setup_MySQL() { uCentral::instance()->exit(Poco::Util::Application::EXIT_CONFIG);} | ||||||
|  | #else | ||||||
|  |  | ||||||
|  | 	int Storage::Setup_MySQL() { | ||||||
|  |  | ||||||
|  | 		dbType_ = mysql ; | ||||||
|  |  | ||||||
|  | 		Logger_.notice("MySQL Storage enabled."); | ||||||
|  | 		auto NumSessions = Daemon()->ConfigGetInt("storage.type.mysql.maxsessions", 64); | ||||||
|  | 		auto IdleTime = Daemon()->ConfigGetInt("storage.type.mysql.idletime", 60); | ||||||
|  | 		auto Host = Daemon()->ConfigGetString("storage.type.mysql.host"); | ||||||
|  | 		auto Username = Daemon()->ConfigGetString("storage.type.mysql.username"); | ||||||
|  | 		auto Password = Daemon()->ConfigGetString("storage.type.mysql.password"); | ||||||
|  | 		auto Database = Daemon()->ConfigGetString("storage.type.mysql.database"); | ||||||
|  | 		auto Port = Daemon()->ConfigGetString("storage.type.mysql.port"); | ||||||
|  |  | ||||||
|  | 		std::string ConnectionStr = | ||||||
|  | 			"host=" + Host + | ||||||
|  | 			";user=" + Username + | ||||||
|  | 			";password=" + Password + | ||||||
|  | 			";db=" + Database + | ||||||
|  | 			";port=" + Port + | ||||||
|  | 			";compress=true;auto-reconnect=true"; | ||||||
|  |  | ||||||
|  | 		MySQLConn_ = std::make_unique<Poco::Data::MySQL::Connector>(); | ||||||
|  | 		MySQLConn_->registerConnector(); | ||||||
|  | 		Pool_ = std::make_unique<Poco::Data::SessionPool>(MySQLConn_->name(), ConnectionStr, 4, NumSessions, IdleTime); | ||||||
|  |  | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | #endif | ||||||
|  | } | ||||||
							
								
								
									
										47
									
								
								src/storage_pgql.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								src/storage_pgql.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | |||||||
|  | // | ||||||
|  | //	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 "Daemon.h" | ||||||
|  | #include "StorageService.h" | ||||||
|  |  | ||||||
|  | namespace uCentral { | ||||||
|  |  | ||||||
|  | #ifdef SMALL_BUILD | ||||||
|  | 	int Service::Setup_PostgreSQL() { uCentral::instance()->exit(Poco::Util::Application::EXIT_CONFIG);} | ||||||
|  | #else | ||||||
|  | 	int Storage::Setup_PostgreSQL() { | ||||||
|  | 		Logger_.notice("PostgreSQL Storage enabled."); | ||||||
|  |  | ||||||
|  | 		dbType_ = pgsql ; | ||||||
|  |  | ||||||
|  | 		auto NumSessions = Daemon()->ConfigGetInt("storage.type.postgresql.maxsessions", 64); | ||||||
|  | 		auto IdleTime = Daemon()->ConfigGetInt("storage.type.postgresql.idletime", 60); | ||||||
|  | 		auto Host = Daemon()->ConfigGetString("storage.type.postgresql.host"); | ||||||
|  | 		auto Username = Daemon()->ConfigGetString("storage.type.postgresql.username"); | ||||||
|  | 		auto Password = Daemon()->ConfigGetString("storage.type.postgresql.password"); | ||||||
|  | 		auto Database = Daemon()->ConfigGetString("storage.type.postgresql.database"); | ||||||
|  | 		auto Port = Daemon()->ConfigGetString("storage.type.postgresql.port"); | ||||||
|  | 		auto ConnectionTimeout = Daemon()->ConfigGetString("storage.type.postgresql.connectiontimeout"); | ||||||
|  |  | ||||||
|  | 		std::string ConnectionStr = | ||||||
|  | 			"host=" + Host + | ||||||
|  | 			" user=" + Username + | ||||||
|  | 			" password=" + Password + | ||||||
|  | 			" dbname=" + Database + | ||||||
|  | 			" port=" + Port + | ||||||
|  | 			" connect_timeout=" + ConnectionTimeout; | ||||||
|  |  | ||||||
|  | 		PostgresConn_ = std::make_unique<Poco::Data::PostgreSQL::Connector>(); | ||||||
|  | 		PostgresConn_->registerConnector(); | ||||||
|  | 		Pool_ = std::make_unique<Poco::Data::SessionPool>(PostgresConn_->name(), ConnectionStr, 4, NumSessions, IdleTime); | ||||||
|  |  | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -1,82 +0,0 @@ | |||||||
| // |  | ||||||
| // Created by stephane bourque on 2021-08-22. |  | ||||||
| // |  | ||||||
|  |  | ||||||
| #include "StorageService.h" |  | ||||||
| #include "Daemon.h" |  | ||||||
|  |  | ||||||
| namespace OpenWifi { |  | ||||||
|  |  | ||||||
| #ifdef	SMALL_BUILD |  | ||||||
|     int Service::Setup_MySQL() { Daemon()->exit(Poco::Util::Application::EXIT_CONFIG); return 0; } |  | ||||||
|     int Service::Setup_PostgreSQL() { Daemon()->exit(Poco::Util::Application::EXIT_CONFIG); return 0; } |  | ||||||
| #else |  | ||||||
|  |  | ||||||
|     int Storage::Setup_SQLite() { |  | ||||||
|         Logger_.notice("SQLite Storage enabled."); |  | ||||||
|         auto DBName = Daemon()->DataDir() + "/" + Daemon()->ConfigGetString("storage.type.sqlite.db"); |  | ||||||
|         auto NumSessions = Daemon()->ConfigGetInt("storage.type.sqlite.maxsessions", 64); |  | ||||||
|         auto IdleTime = Daemon()->ConfigGetInt("storage.type.sqlite.idletime", 60); |  | ||||||
|         SQLiteConn_ = std::make_unique<Poco::Data::SQLite::Connector>(); |  | ||||||
|         SQLiteConn_->registerConnector(); |  | ||||||
|         Pool_ = std::make_unique<Poco::Data::SessionPool>(SQLiteConn_->name(), DBName, 4, NumSessions, IdleTime); |  | ||||||
|         return 0; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     int Storage::Setup_MySQL() { |  | ||||||
|  |  | ||||||
|         Logger_.notice("MySQL Storage enabled."); |  | ||||||
|         auto NumSessions = Daemon()->ConfigGetInt("storage.type.mysql.maxsessions", 64); |  | ||||||
|         auto IdleTime = Daemon()->ConfigGetInt("storage.type.mysql.idletime", 60); |  | ||||||
|         auto Host = Daemon()->ConfigGetString("storage.type.mysql.host"); |  | ||||||
|         auto Username = Daemon()->ConfigGetString("storage.type.mysql.username"); |  | ||||||
|         auto Password = Daemon()->ConfigGetString("storage.type.mysql.password"); |  | ||||||
|         auto Database = Daemon()->ConfigGetString("storage.type.mysql.database"); |  | ||||||
|         auto Port = Daemon()->ConfigGetString("storage.type.mysql.port"); |  | ||||||
|  |  | ||||||
|         std::string ConnectionStr = |  | ||||||
|                 "host=" + Host + |  | ||||||
|                 ";user=" + Username + |  | ||||||
|                 ";password=" + Password + |  | ||||||
|                 ";db=" + Database + |  | ||||||
|                 ";port=" + Port + |  | ||||||
|                 ";compress=true;auto-reconnect=true"; |  | ||||||
|  |  | ||||||
|         MySQLConn_ = std::make_unique<Poco::Data::MySQL::Connector>(); |  | ||||||
|         MySQLConn_->registerConnector(); |  | ||||||
|         Pool_ = std::make_unique<Poco::Data::SessionPool>(MySQLConn_->name(), ConnectionStr, 4, NumSessions, IdleTime); |  | ||||||
|  |  | ||||||
|         return 0; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     int Storage::Setup_PostgreSQL() { |  | ||||||
|         Logger_.notice("PostgreSQL Storage enabled."); |  | ||||||
|  |  | ||||||
|         auto NumSessions = Daemon()->ConfigGetInt("storage.type.postgresql.maxsessions", 64); |  | ||||||
|         auto IdleTime = Daemon()->ConfigGetInt("storage.type.postgresql.idletime", 60); |  | ||||||
|         auto Host = Daemon()->ConfigGetString("storage.type.postgresql.host"); |  | ||||||
|         auto Username = Daemon()->ConfigGetString("storage.type.postgresql.username"); |  | ||||||
|         auto Password = Daemon()->ConfigGetString("storage.type.postgresql.password"); |  | ||||||
|         auto Database = Daemon()->ConfigGetString("storage.type.postgresql.database"); |  | ||||||
|         auto Port = Daemon()->ConfigGetString("storage.type.postgresql.port"); |  | ||||||
|         auto ConnectionTimeout = Daemon()->ConfigGetString("storage.type.postgresql.connectiontimeout"); |  | ||||||
|  |  | ||||||
|         std::string ConnectionStr = |  | ||||||
|                 "host=" + Host + |  | ||||||
|                 " user=" + Username + |  | ||||||
|                 " password=" + Password + |  | ||||||
|                 " dbname=" + Database + |  | ||||||
|                 " port=" + Port + |  | ||||||
|                 " connect_timeout=" + ConnectionTimeout; |  | ||||||
|  |  | ||||||
|         PostgresConn_ = std::make_unique<Poco::Data::PostgreSQL::Connector>(); |  | ||||||
|         PostgresConn_->registerConnector(); |  | ||||||
|         Pool_ = std::make_unique<Poco::Data::SessionPool>(PostgresConn_->name(), ConnectionStr, 4, NumSessions, IdleTime); |  | ||||||
|  |  | ||||||
|         return 0; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
| } |  | ||||||
|  |  | ||||||
							
								
								
									
										26
									
								
								src/storage_sqlite.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/storage_sqlite.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | // | ||||||
|  | //	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 "Daemon.h" | ||||||
|  | #include "StorageService.h" | ||||||
|  |  | ||||||
|  | namespace uCentral { | ||||||
|  | 	int Storage::Setup_SQLite() { | ||||||
|  | 		Logger_.notice("SQLite Storage enabled."); | ||||||
|  |  | ||||||
|  |         auto DBName = Daemon()->DataDir() + "/" + Daemon()->ConfigGetString("storage.type.sqlite.db"); | ||||||
|  | 		auto NumSessions = Daemon()->ConfigGetInt("storage.type.sqlite.maxsessions", 64); | ||||||
|  | 		auto IdleTime = Daemon()->ConfigGetInt("storage.type.sqlite.idletime", 60); | ||||||
|  |  | ||||||
|  | 		SQLiteConn_ = std::make_unique<Poco::Data::SQLite::Connector>(); | ||||||
|  | 		SQLiteConn_->registerConnector(); | ||||||
|  | 		Pool_ = std::make_unique<Poco::Data::SessionPool>(SQLiteConn_->name(), DBName, 4, NumSessions, IdleTime); | ||||||
|  |  | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -7,12 +7,11 @@ | |||||||
| #include "storage_users.h" | #include "storage_users.h" | ||||||
| #include "storage_avatar.h" | #include "storage_avatar.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|  |  | ||||||
|     int Storage::Create_Tables() { |     int Storage::Create_Tables() { | ||||||
|         Create_UserTable(); |         Create_UserTable(); | ||||||
|         Create_AvatarTable(); |         Create_AvatarTable(); | ||||||
|         Create_TokensTable(); |  | ||||||
|         return 0; |         return 0; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -76,48 +75,4 @@ namespace OpenWifi { | |||||||
|             } |             } | ||||||
|             return 0; |             return 0; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         int Storage::Create_TokensTable() { |  | ||||||
|         try { |  | ||||||
|             Poco::Data::Session Sess = Pool_->get(); |  | ||||||
|             if(dbType_==sqlite) { |  | ||||||
|                 Sess << "CREATE TABLE IF NOT EXISTS Tokens (" |  | ||||||
|                         "Token			    TEXT PRIMARY KEY, " |  | ||||||
|                         "RefreshToken       TEXT, " |  | ||||||
|                         "TokenType          TEXT, " |  | ||||||
|                         "UserName           TEXT, " |  | ||||||
|                         "Created 		    BIGINT, " |  | ||||||
|                         "Expires 		    BIGINT, " |  | ||||||
|                         "IdleTimeOut        BIGINT, " |  | ||||||
|                         "RevocationDate 	BIGINT " |  | ||||||
|                         ") ", Poco::Data::Keywords::now; |  | ||||||
|             } else if(dbType_==mysql) { |  | ||||||
|                 Sess << "CREATE TABLE IF NOT EXISTS Tokens (" |  | ||||||
|                         "Token			    TEXT PRIMARY KEY, " |  | ||||||
|                         "RefreshToken       TEXT, " |  | ||||||
|                         "TokenType          TEXT, " |  | ||||||
|                         "UserName           TEXT, " |  | ||||||
|                         "Created 		    BIGINT, " |  | ||||||
|                         "Expires 		    BIGINT, " |  | ||||||
|                         "IdleTimeOut        BIGINT, " |  | ||||||
|                         "RevocationDate 	BIGINT " |  | ||||||
|                         ") ", Poco::Data::Keywords::now; |  | ||||||
|             } else if(dbType_==pgsql) { |  | ||||||
|                 Sess << "CREATE TABLE IF NOT EXISTS Tokens (" |  | ||||||
|                         "Token			    TEXT PRIMARY KEY, " |  | ||||||
|                         "RefreshToken       TEXT, " |  | ||||||
|                         "TokenType          TEXT, " |  | ||||||
|                         "UserName           TEXT, " |  | ||||||
|                         "Created 		    BIGINT, " |  | ||||||
|                         "Expires 		    BIGINT, " |  | ||||||
|                         "IdleTimeOut        BIGINT, " |  | ||||||
|                         "RevocationDate 	BIGINT " |  | ||||||
|                         ") ", Poco::Data::Keywords::now; |  | ||||||
|             } |  | ||||||
|             return 0; |  | ||||||
|         } catch(const Poco::Exception &E) { |  | ||||||
|             Logger_.log(E); |  | ||||||
|         } |  | ||||||
|         return 0; |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,152 +0,0 @@ | |||||||
|  |  | ||||||
| #include "StorageService.h" |  | ||||||
|  |  | ||||||
| namespace OpenWifi { |  | ||||||
|  |  | ||||||
| /* |  | ||||||
|     "Token			    TEXT PRIMARY KEY, " |  | ||||||
|     "RefreshToken       TEXT, " |  | ||||||
|     "TokenType          TEXT, " |  | ||||||
|     "UserName           TEXT, " |  | ||||||
|     "Created 		    BIGINT, " |  | ||||||
|     "Expires 		    BIGINT, " |  | ||||||
|     "IdleTimeOut        BIGINT, " |  | ||||||
|     "RevocationDate 	BIGINT " |  | ||||||
| */ |  | ||||||
|  |  | ||||||
|     bool Storage::AddToken(std::string &UserName, std::string &Token, std::string &RefreshToken, std::string & TokenType, uint64_t Expires, uint64_t TimeOut) { |  | ||||||
|         try { |  | ||||||
|             Poco::Data::Session Sess = Pool_->get(); |  | ||||||
|             Poco::Data::Statement Insert(Sess); |  | ||||||
|             uint64_t Now = std::time(nullptr); |  | ||||||
|             uint64_t Z = 0; |  | ||||||
|  |  | ||||||
|             std::string St2{ |  | ||||||
|                 "INSERT INTO Tokens (Token, RefreshToken, TokenType, Username, Created, Expires, IdleTimeOut, RevocationDate) VALUES(?,?,?,?,?,?,?,?)"}; |  | ||||||
|  |  | ||||||
|             Insert << ConvertParams(St2), |  | ||||||
|                 Poco::Data::Keywords::use(Token), |  | ||||||
|                 Poco::Data::Keywords::use(RefreshToken), |  | ||||||
|                 Poco::Data::Keywords::use(TokenType), |  | ||||||
|                 Poco::Data::Keywords::use(UserName), |  | ||||||
|                 Poco::Data::Keywords::use(Now), |  | ||||||
|                 Poco::Data::Keywords::use(Expires), |  | ||||||
|                 Poco::Data::Keywords::use(TimeOut), |  | ||||||
|                 Poco::Data::Keywords::use(Z); |  | ||||||
|             Insert.execute(); |  | ||||||
|             return true; |  | ||||||
|         } catch (const Poco::Exception &E) { |  | ||||||
|             Logger_.log(E); |  | ||||||
|         } |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     bool Storage::GetToken(std::string &Token, SecurityObjects::UserInfoAndPolicy &UInfo) { |  | ||||||
|         try { |  | ||||||
|  |  | ||||||
|             Poco::Data::Session Sess = Pool_->get(); |  | ||||||
|             Poco::Data::Statement Select(Sess); |  | ||||||
|  |  | ||||||
|             uint32_t RevocationDate = 0 ; |  | ||||||
|  |  | ||||||
|             std::string St2{"SELECT Token, RefreshToken, TokenType, Username, Created, Expires, IdleTimeOut, RevocationDate From Tokens WHERE Token=?"}; |  | ||||||
|             Select << ConvertParams(St2), |  | ||||||
|                 Poco::Data::Keywords::into(UInfo.webtoken.access_token_), |  | ||||||
|                 Poco::Data::Keywords::into(UInfo.webtoken.refresh_token_), |  | ||||||
|                 Poco::Data::Keywords::into(UInfo.webtoken.token_type_), |  | ||||||
|                 Poco::Data::Keywords::into(UInfo.userinfo.email), |  | ||||||
|                 Poco::Data::Keywords::into(UInfo.webtoken.created_), |  | ||||||
|                 Poco::Data::Keywords::into(UInfo.webtoken.expires_in_), |  | ||||||
|                 Poco::Data::Keywords::into(UInfo.webtoken.idle_timeout_), |  | ||||||
|                 Poco::Data::Keywords::into(RevocationDate), |  | ||||||
|                 Poco::Data::Keywords::use(Token); |  | ||||||
|             Select.execute(); |  | ||||||
|  |  | ||||||
|             if(RevocationDate>0) |  | ||||||
|                return false; |  | ||||||
|             return true; |  | ||||||
|         } catch (const Poco::Exception &E) { |  | ||||||
|             Logger_.log(E); |  | ||||||
|         } |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     bool Storage::IsTokenRevoked(std::string &Token) { |  | ||||||
|         try { |  | ||||||
|  |  | ||||||
|             Poco::Data::Session Sess = Pool_->get(); |  | ||||||
|             Poco::Data::Statement Select(Sess); |  | ||||||
|  |  | ||||||
|             uint32_t RevocationDate = 0 ; |  | ||||||
|  |  | ||||||
|             std::string St2{"SELECT Revoked From Tokens WHERE Token=?"}; |  | ||||||
|             Select << ConvertParams(St2), |  | ||||||
|                 Poco::Data::Keywords::into(RevocationDate), |  | ||||||
|                 Poco::Data::Keywords::use(Token); |  | ||||||
|             Select.execute(); |  | ||||||
|  |  | ||||||
|             if(Select.columnsExtracted()==0) |  | ||||||
|                 return false; |  | ||||||
|             return RevocationDate>0 ; |  | ||||||
|  |  | ||||||
|         } catch (const Poco::Exception &E) { |  | ||||||
|             Logger_.log(E); |  | ||||||
|         } |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     bool Storage::RevokeToken(std::string &Token) { |  | ||||||
|         try { |  | ||||||
|             Poco::Data::Session Sess = Pool_->get(); |  | ||||||
|             Poco::Data::Statement Update(Sess); |  | ||||||
|  |  | ||||||
|             uint32_t Revoked = 1 ; |  | ||||||
|             uint64_t Now = std::time(nullptr); |  | ||||||
|  |  | ||||||
|             // update users set lastLogin=? where id=? |  | ||||||
|             std::string St2{"UPDATE Tokens  Set RevocationDate=? WHERE Token=?"}; |  | ||||||
|             Update << ConvertParams(St2), |  | ||||||
|                 Poco::Data::Keywords::use(Now), |  | ||||||
|                 Poco::Data::Keywords::use(Token); |  | ||||||
|             Update.execute(); |  | ||||||
|             return true; |  | ||||||
|         } catch (const Poco::Exception &E) { |  | ||||||
|             Logger_.log(E); |  | ||||||
|         } |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     bool Storage::CleanRevokedTokens(uint64_t Oldest) { |  | ||||||
|         try { |  | ||||||
|             Poco::Data::Session Sess = Pool_->get(); |  | ||||||
|             Poco::Data::Statement Delete(Sess); |  | ||||||
|             uint64_t Now = std::time(nullptr); |  | ||||||
|  |  | ||||||
|             std::string St2{"DELETE From Tokens WHERE Created <= ?"}; |  | ||||||
|             Delete << ConvertParams(St2), |  | ||||||
|                 Poco::Data::Keywords::use(Oldest); |  | ||||||
|             Delete.execute(); |  | ||||||
|             return true; |  | ||||||
|         } catch (const Poco::Exception &E) { |  | ||||||
|             Logger_.log(E); |  | ||||||
|         } |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     bool Storage::RevokeAllTokens(std::string & username) { |  | ||||||
|         try { |  | ||||||
|             Poco::Data::Session Sess = Pool_->get(); |  | ||||||
|             Poco::Data::Statement Delete(Sess); |  | ||||||
|  |  | ||||||
|             std::string St2{"DELETE From Tokens WHERE Username=?"}; |  | ||||||
|             Delete << ConvertParams(St2), |  | ||||||
|                 Poco::Data::Keywords::use(username); |  | ||||||
|             Delete.execute(); |  | ||||||
|             return true; |  | ||||||
|         } catch(const Poco::Exception &E) { |  | ||||||
|             Logger_.log(E); |  | ||||||
|         } |  | ||||||
|         return false; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| } |  | ||||||
| @@ -9,7 +9,7 @@ | |||||||
| #include "Poco/Tuple.h" | #include "Poco/Tuple.h" | ||||||
| #include "storage_users.h" | #include "storage_users.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|  |  | ||||||
|     bool Convert(const UserInfoRecord &T, SecurityObjects::UserInfo &U) { |     bool Convert(const UserInfoRecord &T, SecurityObjects::UserInfo &U) { | ||||||
|         U.Id = T.get<0>(); |         U.Id = T.get<0>(); | ||||||
| @@ -221,16 +221,17 @@ namespace OpenWifi { | |||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool Storage::GetUsers( uint64_t Offset, uint64_t HowMany, SecurityObjects::UserInfoVec & Users) { |     bool Storage::GetUsers( uint64_t Offset, uint64_t Limit, SecurityObjects::UserInfoVec & Users) { | ||||||
|         try { |         try { | ||||||
|             Poco::Data::Session Sess = Pool_->get(); |             Poco::Data::Session Sess = Pool_->get(); | ||||||
|             Poco::Data::Statement Select(Sess); |             Poco::Data::Statement Select(Sess); | ||||||
|             UserInfoRecordList Records; |             UserInfoRecordList Records; | ||||||
|  |  | ||||||
|             std::string St1{"select " + AllUsersFieldsForSelect + " from users order by id ASC "}; |             std::string St1{"select " + AllUsersFieldsForSelect + " from users"}; | ||||||
|  |  | ||||||
|             Select << ConvertParams(St1) + ComputeRange(Offset, HowMany), |             Select << ConvertParams(St1) , | ||||||
|                         Poco::Data::Keywords::into(Records); |                     Poco::Data::Keywords::into(Records), | ||||||
|  |                     Poco::Data::Keywords::range(Offset, Offset + Limit); | ||||||
|             Select.execute(); |             Select.execute(); | ||||||
|  |  | ||||||
|             for(const auto &R:Records) { |             for(const auto &R:Records) { | ||||||
|   | |||||||
| @@ -5,9 +5,9 @@ | |||||||
| #ifndef UCENTRALSEC_STORAGE_USERS_H | #ifndef UCENTRALSEC_STORAGE_USERS_H | ||||||
| #define UCENTRALSEC_STORAGE_USERS_H | #define UCENTRALSEC_STORAGE_USERS_H | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace uCentral { | ||||||
|     static const std::string AllUsersFieldsForCreation{ |     static const std::string AllUsersFieldsForCreation{ | ||||||
|         " Id             varchar(36) UNIQUE PRIMARY KEY," |             "Id             varchar(36)," | ||||||
|             "name           varchar," |             "name           varchar," | ||||||
|             "description    varchar," |             "description    varchar," | ||||||
|             "avatar         varchar," |             "avatar         varchar," | ||||||
| @@ -116,9 +116,6 @@ namespace OpenWifi { | |||||||
|             "canceled       bigint" |             "canceled       bigint" | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     typedef Poco::Tuple < |     typedef Poco::Tuple < | ||||||
|         std::string,    // Id = 0; |         std::string,    // Id = 0; | ||||||
|         std::string,    // name; |         std::string,    // name; | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ | |||||||
|  |  | ||||||
| #include "Poco/String.h" | #include "Poco/String.h" | ||||||
|  |  | ||||||
| namespace OpenWifi::uCentralProtocol { | namespace uCentral::uCentralProtocol { | ||||||
|  |  | ||||||
| 	const int SERIAL_NUMBER_LENGTH = 30; | 	const int SERIAL_NUMBER_LENGTH = 30; | ||||||
|  |  | ||||||
| @@ -79,17 +79,6 @@ namespace OpenWifi::uCentralProtocol { | |||||||
| 	static const char * VERBOSE = "verbose"; | 	static const char * VERBOSE = "verbose"; | ||||||
| 	static const char * BANDS = "bands"; | 	static const char * BANDS = "bands"; | ||||||
| 	static const char * CHANNELS = "channels"; | 	static const char * CHANNELS = "channels"; | ||||||
| 	static const char * PASSWORD = "password"; |  | ||||||
| 	static const char * DEVICEUPDATE = "deviceupdate"; |  | ||||||
|  |  | ||||||
|     static const char * SERIALNUMBER = "serialNumber"; |  | ||||||
|     static const char * COMPATIBLE = "compatible"; |  | ||||||
|     static const char * DISCONNECTION = "disconnection"; |  | ||||||
|     static const char * TIMESTAMP = "timestamp"; |  | ||||||
|     static const char * SYSTEM = "system"; |  | ||||||
|     static const char * HOST = "host"; |  | ||||||
|     static const char * CONNECTIONIP = "connectionIp"; |  | ||||||
|     static const char * TELEMETRY = "telemetry"; |  | ||||||
|  |  | ||||||
| 	enum EVENT_MSG { | 	enum EVENT_MSG { | ||||||
| 			ET_UNKNOWN, | 			ET_UNKNOWN, | ||||||
| @@ -100,9 +89,7 @@ namespace OpenWifi::uCentralProtocol { | |||||||
| 			ET_CRASHLOG, | 			ET_CRASHLOG, | ||||||
| 			ET_PING, | 			ET_PING, | ||||||
| 			ET_CFGPENDING, | 			ET_CFGPENDING, | ||||||
| 			ET_RECOVERY, | 			ET_RECOVERY | ||||||
| 			ET_DEVICEUPDATE, |  | ||||||
| 			ET_TELEMETRY |  | ||||||
| 		}; | 		}; | ||||||
|  |  | ||||||
| 	static EVENT_MSG EventFromString(const std::string & Method) { | 	static EVENT_MSG EventFromString(const std::string & Method) { | ||||||
| @@ -122,10 +109,6 @@ namespace OpenWifi::uCentralProtocol { | |||||||
| 			return ET_CFGPENDING; | 			return ET_CFGPENDING; | ||||||
| 		} else if (!Poco::icompare(Method, RECOVERY)) { | 		} else if (!Poco::icompare(Method, RECOVERY)) { | ||||||
| 			return ET_RECOVERY; | 			return ET_RECOVERY; | ||||||
| 		} else if (!Poco::icompare(Method, DEVICEUPDATE)) { |  | ||||||
| 			return ET_DEVICEUPDATE; |  | ||||||
| 		} else if (!Poco::icompare(Method, TELEMETRY)) { |  | ||||||
| 			return ET_TELEMETRY; |  | ||||||
| 		} else | 		} else | ||||||
| 			return ET_UNKNOWN; | 			return ET_UNKNOWN; | ||||||
| 	}; | 	}; | ||||||
|   | |||||||
							
								
								
									
										40
									
								
								src/uCentralTypes.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/uCentralTypes.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2021-06-13. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #ifndef UCENTRALGW_UCENTRALTYPES_H | ||||||
|  | #define UCENTRALGW_UCENTRALTYPES_H | ||||||
|  |  | ||||||
|  | #include "SubSystemServer.h" | ||||||
|  |  | ||||||
|  | #include <vector> | ||||||
|  | #include <string> | ||||||
|  | #include <map> | ||||||
|  | #include <functional> | ||||||
|  | #include <list> | ||||||
|  | #include <utility> | ||||||
|  | #include <queue> | ||||||
|  |  | ||||||
|  | namespace uCentral::Types { | ||||||
|  |     typedef std::pair<std::string,std::string>              StringPair; | ||||||
|  | 	typedef std::vector<StringPair>	                        StringPairVec; | ||||||
|  |     typedef std::queue<StringPair>	                        StringPairQueue; | ||||||
|  | 	typedef std::vector<std::string>						StringVec; | ||||||
|  | 	typedef std::set<std::string>                           StringSet; | ||||||
|  | 	typedef std::vector<SubSystemServer*>					SubSystemVec; | ||||||
|  | 	typedef std::map<std::string,std::set<std::string>>		StringMapStringSet; | ||||||
|  | 	typedef std::function<void(std::string, std::string)>   TopicNotifyFunction; | ||||||
|  | 	typedef std::list<std::pair<TopicNotifyFunction,int>>   TopicNotifyFunctionList; | ||||||
|  | 	typedef std::map<std::string, TopicNotifyFunctionList>  NotifyTable; | ||||||
|  |     typedef std::map<std::string,uint64_t>                  CountedMap; | ||||||
|  |  | ||||||
|  |     inline void UpdateCountedMap(CountedMap &M, const std::string &S ) { | ||||||
|  |         auto it = M.find(S); | ||||||
|  |         if(it==M.end()) | ||||||
|  |             M[S]=1; | ||||||
|  |         else | ||||||
|  |             it->second += 1; | ||||||
|  |     } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | #endif // UCENTRALGW_UCENTRALTYPES_H | ||||||
| @@ -20,10 +20,10 @@ then | |||||||
|   exit 1 |   exit 1 | ||||||
| fi | fi | ||||||
|  |  | ||||||
| if [[ "${OWSEC}" == "" ]] | if [[ "${UCENTRALSEC}" == "" ]] | ||||||
| then | then | ||||||
|   echo "You must set the variable OWSEC in order to use this script. Something like" |   echo "You must set the variable UCENTRALSEC in order to use this script. Something like" | ||||||
|   echo "OWSEC=myauthgateway.isp.com:16001" |   echo "UCENTRALSEC=myauthgateway.isp.com:16001" | ||||||
|   exit 1 |   exit 1 | ||||||
| fi | fi | ||||||
|  |  | ||||||
| @@ -43,7 +43,7 @@ browser="" | |||||||
|  |  | ||||||
| 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://${UCENTRALSEC}/api/v1/oauth2" | jq -r '.access_token') | ||||||
|  |  | ||||||
|   if [[ "${token}" == "" ]] |   if [[ "${token}" == "" ]] | ||||||
|   then |   then | ||||||
| @@ -55,7 +55,7 @@ login() { | |||||||
|  |  | ||||||
| testlogin() { | testlogin() { | ||||||
|     payload="{ \"userId\" : \"$1\" , \"password\" : \"$2\" }" |     payload="{ \"userId\" : \"$1\" , \"password\" : \"$2\" }" | ||||||
|     curl ${FLAGS} -X POST "https://${OWSEC}/api/v1/oauth2" \ |     curl ${FLAGS} -X POST "https://${UCENTRALSEC}/api/v1/oauth2" \ | ||||||
|         -H "Content-Type: application/json" \ |         -H "Content-Type: application/json" \ | ||||||
|         -d "$payload" > ${result_file} |         -d "$payload" > ${result_file} | ||||||
|     userMustChangePassword=$(cat ${result_file} | jq -r '.userMustChangePassword') |     userMustChangePassword=$(cat ${result_file} | jq -r '.userMustChangePassword') | ||||||
| @@ -68,14 +68,14 @@ testlogin() { | |||||||
|             exit 1 |             exit 1 | ||||||
|         fi |         fi | ||||||
|         payload="{ \"userId\" : \"$1\" , \"password\" : \"$2\", \"newPassword\" : \"$3\" }" |         payload="{ \"userId\" : \"$1\" , \"password\" : \"$2\", \"newPassword\" : \"$3\" }" | ||||||
|         curl ${FLAGS} -X POST "https://${OWSEC}/api/v1/oauth2" \ |         curl ${FLAGS} -X POST "https://${UCENTRALSEC}/api/v1/oauth2" \ | ||||||
|             -H "Content-Type: application/json" \ |             -H "Content-Type: application/json" \ | ||||||
|             -d "$payload" > ${result_file} |             -d "$payload" > ${result_file} | ||||||
|         jq < ${result_file} |         jq < ${result_file} | ||||||
|     elif [[ "$3" != "" ]] |     elif [[ "$3" != "" ]] | ||||||
|     then |     then | ||||||
|         payload="{ \"userId\" : \"$1\" , \"password\" : \"$2\", \"newPassword\" : \"$3\" }" |         payload="{ \"userId\" : \"$1\" , \"password\" : \"$2\", \"newPassword\" : \"$3\" }" | ||||||
|         curl ${FLAGS} -X POST "https://${OWSEC}/api/v1/oauth2" \ |         curl ${FLAGS} -X POST "https://${UCENTRALSEC}/api/v1/oauth2" \ | ||||||
|                 -H "Content-Type: application/json" \ |                 -H "Content-Type: application/json" \ | ||||||
|                 -d "$payload" > ${result_file} |                 -d "$payload" > ${result_file} | ||||||
|         jq < ${result_file} |         jq < ${result_file} | ||||||
| @@ -85,7 +85,7 @@ testlogin() { | |||||||
|  |  | ||||||
| emailtest() { | emailtest() { | ||||||
|     payload="{ \"userId\" : \"$1\"  }" |     payload="{ \"userId\" : \"$1\"  }" | ||||||
|     curl ${FLAGS} -X POST "https://${OWSEC}/api/v1/oauth2?forgotPassword=true" \ |     curl ${FLAGS} -X POST "https://${UCENTRALSEC}/api/v1/oauth2?forgotPassword=true" \ | ||||||
|         -H "Content-Type: application/json" \ |         -H "Content-Type: application/json" \ | ||||||
|         -d "$payload" > ${result_file} |         -d "$payload" > ${result_file} | ||||||
|     jq < ${result_file} |     jq < ${result_file} | ||||||
| @@ -114,19 +114,18 @@ findbrowser() { | |||||||
| logout() { | logout() { | ||||||
|   curl  ${FLAGS} -X DELETE -H "Content-Type: application/json" \ |   curl  ${FLAGS} -X DELETE -H "Content-Type: application/json" \ | ||||||
|         -H "Authorization: Bearer ${token}" \ |         -H "Authorization: Bearer ${token}" \ | ||||||
|         "https://${OWSEC}/api/v1/oauth2/${token}" |         "https://${UCENTRALSEC}/api/v1/oauth2/${token}" | ||||||
|   token="" |  | ||||||
|   rm -rf token.json |   rm -rf token.json | ||||||
| } | } | ||||||
|  |  | ||||||
| me() { | me() { | ||||||
|     curl  ${FLAGS} -X GET -H "Content-Type: application/json" \ |     curl  ${FLAGS} -X GET -H "Content-Type: application/json" \ | ||||||
|     -H "Authorization: Bearer ${token}" \ |     -H "Authorization: Bearer ${token}" \ | ||||||
|     "https://${OWSEC}/api/v1/oauth2?me=true" |     "https://${UCENTRALSEC}/api/v1/oauth2?me=true" | ||||||
| } | } | ||||||
|  |  | ||||||
| listendpoints() { | listendpoints() { | ||||||
|     curl  ${FLAGS} -X GET "https://${OWSEC}/api/v1/systemEndpoints" \ |     curl  ${FLAGS} -X GET "https://${UCENTRALSEC}/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} |     jq < ${result_file} | ||||||
| @@ -162,12 +161,12 @@ listendpoints() { | |||||||
| } | } | ||||||
|  |  | ||||||
| getlogo() { | getlogo() { | ||||||
| 	curl ${FLAGS} -X GET "https://${OWSEC}/wwwassets/open-wifi.svg" | 	curl ${FLAGS} -X GET "https://${UCENTRALSEC}/wwwassets/open-wifi.svg" | ||||||
| } | } | ||||||
|  |  | ||||||
| createuser() { | createuser() { | ||||||
|     payload="{ \"id\": \"0\", \"email\" : \"$1\", \"currentPassword\" : \"$2\", \"changePassword\" : true}" |     payload="{ \"id\": \"0\", \"email\" : \"$1\", \"currentPassword\" : \"$2\", \"changePassword\" : true}" | ||||||
|     curl  ${FLAGS} -X POST "https://${OWSEC}/api/v1/user/0" \ |     curl  ${FLAGS} -X POST "https://${UCENTRALSEC}/api/v1/user/0" \ | ||||||
|     -H "accept: application/json" \ |     -H "accept: application/json" \ | ||||||
|     -H "Authorization: Bearer ${token}" \ |     -H "Authorization: Bearer ${token}" \ | ||||||
|     -d "$payload"  > ${result_file} |     -d "$payload"  > ${result_file} | ||||||
| @@ -176,7 +175,7 @@ createuser() { | |||||||
|  |  | ||||||
| createuser_v() { | createuser_v() { | ||||||
|     payload="{ \"id\": \"0\", \"email\" : \"$1\", \"currentPassword\" : \"$2\", \"changePassword\" : true}" |     payload="{ \"id\": \"0\", \"email\" : \"$1\", \"currentPassword\" : \"$2\", \"changePassword\" : true}" | ||||||
|     curl  ${FLAGS} -X POST "https://${OWSEC}/api/v1/user/0?email_verification=true" \ |     curl  ${FLAGS} -X POST "https://${UCENTRALSEC}/api/v1/user/0?email_verification=true" \ | ||||||
|     -H "accept: application/json" \ |     -H "accept: application/json" \ | ||||||
|     -H "Authorization: Bearer ${token}" \ |     -H "Authorization: Bearer ${token}" \ | ||||||
|     -d "$payload"  > ${result_file} |     -d "$payload"  > ${result_file} | ||||||
| @@ -184,7 +183,7 @@ createuser_v() { | |||||||
| } | } | ||||||
|  |  | ||||||
| deleteuser() { | deleteuser() { | ||||||
|     curl  ${FLAGS} -X DELETE "https://${OWSEC}/api/v1/user/$1" \ |     curl  ${FLAGS} -X DELETE "https://${UCENTRALSEC}/api/v1/user/$1" \ | ||||||
|     -H "accept: application/json" \ |     -H "accept: application/json" \ | ||||||
|     -H "Authorization: Bearer ${token}" \ |     -H "Authorization: Bearer ${token}" \ | ||||||
|     -d "$payload"  > ${result_file} |     -d "$payload"  > ${result_file} | ||||||
| @@ -192,7 +191,7 @@ deleteuser() { | |||||||
| } | } | ||||||
|  |  | ||||||
| getuser() { | getuser() { | ||||||
|     curl  ${FLAGS} -X GET "https://${OWSEC}/api/v1/user/$1" \ |     curl  ${FLAGS} -X GET "https://${UCENTRALSEC}/api/v1/user/$1" \ | ||||||
|     -H "accept: application/json" \ |     -H "accept: application/json" \ | ||||||
|     -H "Authorization: Bearer ${token}" \ |     -H "Authorization: Bearer ${token}" \ | ||||||
|     -d "$payload"  > ${result_file} |     -d "$payload"  > ${result_file} | ||||||
| @@ -200,7 +199,7 @@ getuser() { | |||||||
| } | } | ||||||
|  |  | ||||||
| listusers() { | listusers() { | ||||||
|     curl  ${FLAGS} -X GET "https://${OWSEC}/api/v1/users" \ |     curl  ${FLAGS} -X GET "https://${UCENTRALSEC}/api/v1/users" \ | ||||||
|     -H "accept: application/json" \ |     -H "accept: application/json" \ | ||||||
|     -H "Authorization: Bearer ${token}" \ |     -H "Authorization: Bearer ${token}" \ | ||||||
|     -d "$payload"  > ${result_file} |     -d "$payload"  > ${result_file} | ||||||
| @@ -209,127 +208,53 @@ listusers() { | |||||||
|  |  | ||||||
| policies() { | policies() { | ||||||
|     payload="{}" |     payload="{}" | ||||||
|     curl ${FLAGS} -X POST "https://${OWSEC}/api/v1/oauth2?requirements=true" \ |     curl ${FLAGS} -X POST "https://${UCENTRALSEC}/api/v1/oauth2?requirements=true" \ | ||||||
|         -H "Content-Type: application/json" \ |         -H "Content-Type: application/json" \ | ||||||
|         -d "$payload" > ${result_file} |         -d "$payload" > ${result_file} | ||||||
|     jq < ${result_file} |     jq < ${result_file} | ||||||
| } | } | ||||||
|  |  | ||||||
| setavatar() { | setavatar() { | ||||||
|     curl ${FLAGS} -F 'data=@$2' "https://${OWSEC}/api/v1/avatar/$1" \ |     curl ${FLAGS} -F 'data=@open-wifi.svg' "https://${UCENTRALSEC}/api/v1/avatar/$1" \ | ||||||
|         -H "Authorization: Bearer ${token}" > ${result_file}; |         -H "Authorization: Bearer ${token}" > ${result_file}; | ||||||
|     jq < ${result_file} |     jq < ${result_file} | ||||||
| } | } | ||||||
|  |  | ||||||
| getavatar() { | getavatar() { | ||||||
|     curl  ${FLAGS} -X GET "https://${OWSEC}/api/v1/avatar/$1" \ |     curl  ${FLAGS} -X GET "https://${UCENTRALSEC}/api/v1/avatar/$1" \ | ||||||
|         -H "accept: application/octet-stream" \ |         -H "accept: application/octet-stream" \ | ||||||
|         -H "Authorization: Bearer ${token}" \ |         -H "Authorization: Bearer ${token}" \ | ||||||
| 		-o "user.svg" | 		-o "user.svg" | ||||||
| } | } | ||||||
|  |  | ||||||
| deleteavatar() { | deleteavatar() { | ||||||
|     curl  ${FLAGS} -X DELETE "https://${OWSEC}/api/v1/avatar/$1" \ |     curl  ${FLAGS} -X DELETE "https://${UCENTRALSEC}/api/v1/avatar/$1" \ | ||||||
|         -H "Authorization: Bearer ${token}" \ |         -H "Authorization: Bearer ${token}" \ | ||||||
|         -H "Content-Type: application/json" > ${result_file} |         -H "Content-Type: application/json" > ${result_file} | ||||||
|     jq < ${result_file} |     jq < ${result_file} | ||||||
| } | } | ||||||
|  |  | ||||||
| sendemail() { | secversion() { | ||||||
|     payload="{ \"recipients\" : [ \"$1\" ] , \"subject\" : \"test1\" , \"from\" : \"$2\" , \"text\" : \"This is a test from SES.\" }" |     curl  ${FLAGS} -X GET "https://${UCENTRALSEC}/api/v1/system?command=version" \ | ||||||
|             curl ${FLAGS} -X POST "https://${OWSEC}/api/v1/email" \ |         -H "accept: application/json" \ | ||||||
|             -H "Content-Type: application/json" \ |         -H "Authorization: Bearer ${token}" > ${result_file} | ||||||
|             -H "Authorization: Bearer ${token}" \ |  | ||||||
|             -d "$payload" > ${result_file} |  | ||||||
|             jq < ${result_file} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| testlogout() { |  | ||||||
|     echo "Logged in..." |  | ||||||
|     oldtoken=${token} |  | ||||||
|     listusers |  | ||||||
|     logout |  | ||||||
|     echo "Logged out..." |  | ||||||
|     token=${oldtoken} |  | ||||||
|     echo "This should be en error" |  | ||||||
|     listusers |  | ||||||
| } |  | ||||||
|  |  | ||||||
| setloglevel() { |  | ||||||
|     payload="{ \"command\" : \"setloglevel\" , \"subsystems\" : [ { \"tag\" : \"$1\" , \"value\" : \"$2\" } ] }" |  | ||||||
|             curl  ${FLAGS} -X POST "https://${OWSEC}/api/v1/system" \ |  | ||||||
|             -H  "accept: application/json" \ |  | ||||||
|             -H "Authorization: Bearer ${token}" \ |  | ||||||
|             -d "$payload" |  | ||||||
| } |  | ||||||
|  |  | ||||||
| getloglevels() { |  | ||||||
|     payload="{ \"command\" : \"getloglevels\" }" |  | ||||||
|             curl  ${FLAGS} -X POST "https://${OWSEC}/api/v1/system" \ |  | ||||||
|             -H  "accept: application/json" \ |  | ||||||
|             -H "Authorization: Bearer ${token}" \ |  | ||||||
|             -d "$payload" |  | ||||||
| } |  | ||||||
|  |  | ||||||
| getloglevelnames() { |  | ||||||
|     payload="{ \"command\" : \"getloglevelnames\" }" |  | ||||||
|             curl  ${FLAGS} -X POST "https://${OWSEC}/api/v1/system" \ |  | ||||||
|             -H  "accept: application/json" \ |  | ||||||
|             -H "Authorization: Bearer ${token}" \ |  | ||||||
|             -d "$payload" |  | ||||||
| } |  | ||||||
|  |  | ||||||
| getsubsystemnames() { |  | ||||||
|     payload="{ \"command\" : \"getsubsystemnames\" }" |  | ||||||
|             curl  ${FLAGS} -X POST "https://${OWSEC}/api/v1/system" \ |  | ||||||
|             -H  "accept: application/json" \ |  | ||||||
|             -H "Authorization: Bearer ${token}" \ |  | ||||||
|             -d "$payload" |  | ||||||
| } |  | ||||||
|  |  | ||||||
| systeminfo() { |  | ||||||
|     curl  ${FLAGS} -X GET "https://${OWSEC}/api/v1/system?command=info" \ |  | ||||||
|     -H "accept: application/json" \ |  | ||||||
|     -H "Authorization: Bearer ${token}" > ${result_file} |  | ||||||
|     jq < ${result_file} |     jq < ${result_file} | ||||||
| } | } | ||||||
|  |  | ||||||
| reloadsubsystem() { | sectimes() { | ||||||
|     payload="{ \"command\" : \"reload\", \"subsystems\" : [ \"$1\" ] }" |     curl  ${FLAGS} -X GET "https://${UCENTRALSEC}/api/v1/system?command=times" \ | ||||||
|             curl  ${FLAGS} -X POST "https://${OWSEC}/api/v1/system" \ |         -H "accept: application/json" \ | ||||||
|             -H  "accept: application/json" \ |         -H "Authorization: Bearer ${token}" > ${result_file} | ||||||
|             -H "Authorization: Bearer ${token}" \ |     jq < ${result_file} | ||||||
|             -d "$payload" |  | ||||||
| } | } | ||||||
|  |  | ||||||
| help() { | help() { | ||||||
|     echo |   echo | ||||||
|     echo    "Usage: cli <cmd> [args]" |   echo "listendpoints                     Get all the system endpoints." | ||||||
|     echo |   echo | ||||||
|     echo    "listendpoints                          Get all the system endpoints." |  | ||||||
|     echo    "emailtest                              Generate a forgot Password e-amil to the logged in user." |  | ||||||
|     echo    "me                                     Show information about the logged user." |  | ||||||
|     echo    "createuser <email> <password>          Create a user with an initial password and force the user to change password." |  | ||||||
|     echo    "createuser_v <email> <password>        Same as create user but also force an e-mail verification." |  | ||||||
|     echo    "deleteuser <user UUID>                 Delete the user." |  | ||||||
|     echo    "getuser <user UUID>                    Get the user information." |  | ||||||
|     echo    "listusers                              List users." |  | ||||||
|     echo    "policies                               List the login and access policies." |  | ||||||
|     echo    "setavatar <user UUID> <filename>       Sets the avatar for user to the image in filename." |  | ||||||
|     echo    "getavatar <user UUID>                  Get the avatar for the user." |  | ||||||
|     echo    "deleteavatar <user UUID>               Remove the avatar for a user." |  | ||||||
|     echo    "sendemail <recipient> <from>           Sends a test email to see if the e-mail system is working." |  | ||||||
|     echo    "setloglevel <subsystem> <loglevel>     Set the log level for s specific subsystem." |  | ||||||
|     echo    "getloglevels                           Get the current log levels for all subsystems." |  | ||||||
|     echo    "getloglevelnames                       Get the log level names available." |  | ||||||
|     echo    "getsubsystemnames                      Get the list of subsystems." |  | ||||||
|     echo    "systeminfo                             Get basic system information." |  | ||||||
|     echo    "reloadsubsystem <subsystem name>       Reload the configuration for a subsystem." |  | ||||||
|     echo |  | ||||||
| } | } | ||||||
|  |  | ||||||
| shopt -s nocasematch | shopt -s nocasematch | ||||||
|  |  | ||||||
| case "$1" in | case "$1" in | ||||||
|     "createuser") login; createuser "$2" "$3"; logout;; |     "createuser") login; createuser "$2" "$3"; logout;; | ||||||
|     "createuser_v") login; createuser_v "$2" "$3"; logout;; |     "createuser_v") login; createuser_v "$2" "$3"; logout;; | ||||||
| @@ -345,14 +270,8 @@ case "$1" in | |||||||
|     "setavatar") login; setavatar "$2"; logout;; |     "setavatar") login; setavatar "$2"; logout;; | ||||||
|     "getavatar") login; getavatar "$2"; logout;; |     "getavatar") login; getavatar "$2"; logout;; | ||||||
|     "deleteavatar") login; deleteavatar "$2"; logout;; |     "deleteavatar") login; deleteavatar "$2"; logout;; | ||||||
|     "sendemail") login; sendemail ; logout;; |     "secversion") login; secversion ; logout;; | ||||||
|     "testlogout") login; testlogout ;; |     "sectimes") login; sectimes ; logout;; | ||||||
|     "setloglevel") login; setloglevel "$2" "$3"  ; logout ;; |  | ||||||
|     "getloglevels") login; getloglevels; logout ;; |  | ||||||
|     "getloglevelnames") login; getloglevelnames; logout ;; |  | ||||||
|     "getsubsystemnames") login; getsubsystemnames; logout ;; |  | ||||||
|     "reloadsubsystem") login; reloadsubsystem "$2"; logout ;; |  | ||||||
|     "systeminfo") login; systeminfo ; logout;; |  | ||||||
|     "help") login; help  ; logout ;; |     "help") login; help  ; logout ;; | ||||||
|     *) help ;; |     *) help ;; | ||||||
| esac | esac | ||||||
|   | |||||||
| @@ -7,24 +7,24 @@ | |||||||
| # | # | ||||||
| # REST API access | # REST API access | ||||||
| # | # | ||||||
| openwifi.restapi.host.0.backlog = 100 | ucentral.restapi.host.0.backlog = 100 | ||||||
| openwifi.restapi.host.0.security = relaxed | ucentral.restapi.host.0.security = relaxed | ||||||
| openwifi.restapi.host.0.rootca = $OWSEC_ROOT/certs/restapi-ca.pem | ucentral.restapi.host.0.rootca = $UCENTRALSEC_ROOT/certs/restapi-ca.pem | ||||||
| openwifi.restapi.host.0.address = * | ucentral.restapi.host.0.address = * | ||||||
| openwifi.restapi.host.0.port = 16001 | ucentral.restapi.host.0.port = 16001 | ||||||
| openwifi.restapi.host.0.cert = $OWSEC_ROOT/certs/restapi-cert.pem | ucentral.restapi.host.0.cert = $UCENTRALSEC_ROOT/certs/restapi-cert.pem | ||||||
| openwifi.restapi.host.0.key = $OWSEC_ROOT/certs/restapi-key.pem | ucentral.restapi.host.0.key = $UCENTRALSEC_ROOT/certs/restapi-key.pem | ||||||
| openwifi.restapi.host.0.key.password = mypassword | ucentral.restapi.host.0.key.password = mypassword | ||||||
| openwifi.restapi.wwwassets = $OWSEC_ROOT/wwwassets | ucentral.restapi.wwwassets = $UCENTRALSEC_ROOT/wwwassets | ||||||
| 
 | 
 | ||||||
| openwifi.internal.restapi.host.0.backlog = 100 | ucentral.internal.restapi.host.0.backlog = 100 | ||||||
| openwifi.internal.restapi.host.0.security = relaxed | ucentral.internal.restapi.host.0.security = relaxed | ||||||
| openwifi.internal.restapi.host.0.rootca = $OWSEC_ROOT/certs/restapi-ca.pem | ucentral.internal.restapi.host.0.rootca = $UCENTRALSEC_ROOT/certs/restapi-ca.pem | ||||||
| openwifi.internal.restapi.host.0.address = * | ucentral.internal.restapi.host.0.address = * | ||||||
| openwifi.internal.restapi.host.0.port = 17001 | ucentral.internal.restapi.host.0.port = 17001 | ||||||
| openwifi.internal.restapi.host.0.cert = $OWSEC_ROOT/certs/restapi-cert.pem | ucentral.internal.restapi.host.0.cert = $UCENTRALSEC_ROOT/certs/restapi-cert.pem | ||||||
| openwifi.internal.restapi.host.0.key = $OWSEC_ROOT/certs/restapi-key.pem | ucentral.internal.restapi.host.0.key = $UCENTRALSEC_ROOT/certs/restapi-key.pem | ||||||
| openwifi.internal.restapi.host.0.key.password = mypassword | ucentral.internal.restapi.host.0.key.password = mypassword | ||||||
| 
 | 
 | ||||||
| # | # | ||||||
| # Generic section that all microservices must have | # Generic section that all microservices must have | ||||||
| @@ -32,13 +32,13 @@ openwifi.internal.restapi.host.0.key.password = mypassword | |||||||
| authentication.enabled = true | authentication.enabled = true | ||||||
| authentication.default.username = tip@ucentral.com | authentication.default.username = tip@ucentral.com | ||||||
| authentication.default.password = 13268b7daa751240369d125e79c873bd8dd3bef7981bdfd38ea03dbb1fbe7dcf | authentication.default.password = 13268b7daa751240369d125e79c873bd8dd3bef7981bdfd38ea03dbb1fbe7dcf | ||||||
| openwifi.system.data = $OWSEC_ROOT/data | ucentral.system.data = $UCENTRALSEC_ROOT/data | ||||||
| openwifi.system.uri.private = https://localhost:17001 | ucentral.system.uri.private = https://localhost:17001 | ||||||
| openwifi.system.uri.public = https://local.dpaas.arilia.com:16001 | ucentral.system.uri.public = https://local.dpaas.arilia.com:16001 | ||||||
| openwifi.system.uri.ui = https://ucentral-ui.arilia.com | ucentral.system.uri.ui = https://ucentral-ui.arilia.com | ||||||
| openwifi.system.commandchannel = /tmp/app.ucentralsec | ucentral.system.commandchannel = /tmp/app.ucentralsec | ||||||
| openwifi.service.key = $OWSEC_ROOT/certs/restapi-key.pem | ucentral.service.key = $UCENTRALSEC_ROOT/certs/restapi-key.pem | ||||||
| openwifi.service.key.password = mypassword | ucentral.service.key.password = mypassword | ||||||
| 
 | 
 | ||||||
| # | # | ||||||
| # Security Microservice Specific Section | # Security Microservice Specific Section | ||||||
| @@ -46,10 +46,9 @@ openwifi.service.key.password = mypassword | |||||||
| mailer.hostname = smtp.gmail.com | mailer.hostname = smtp.gmail.com | ||||||
| mailer.username = ************************ | mailer.username = ************************ | ||||||
| mailer.password = ************************ | mailer.password = ************************ | ||||||
| mailer.sender = OpenWIFI |  | ||||||
| mailer.loginmethod = login | mailer.loginmethod = login | ||||||
| mailer.port = 587 | mailer.port = 587 | ||||||
| mailer.templates = $OWSEC_ROOT/templates | mailer.templates = $UCENTRALSEC_ROOT/templates | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| ############################# | ############################# | ||||||
| @@ -64,15 +63,16 @@ alb.port = 16101 | |||||||
| # | # | ||||||
| # Kafka | # Kafka | ||||||
| # | # | ||||||
| openwifi.kafka.group.id = security | ucentral.kafka.group.id = security | ||||||
| openwifi.kafka.client.id = security1 | ucentral.kafka.client.id = security1 | ||||||
| openwifi.kafka.enable = true | ucentral.kafka.enable = true | ||||||
| openwifi.kafka.brokerlist = a1.arilia.com:9092 | # ucentral.kafka.brokerlist = a1.arilia.com:9092 | ||||||
| openwifi.kafka.auto.commit = false | ucentral.kafka.brokerlist = debfarm1-node-c.arilia.com:9092 | ||||||
| openwifi.kafka.queue.buffering.max.ms = 50 | ucentral.kafka.auto.commit = false | ||||||
| openwifi.document.policy.access = /wwwassets/access_policy.html | ucentral.kafka.queue.buffering.max.ms = 50 | ||||||
| openwifi.document.policy.password = /wwwassets/password_policy.html | 
 | ||||||
| openwifi.avatar.maxsize = 2000000 | ucentral.document.policy.access = /wwwassets/access_policy.html | ||||||
|  | ucentral.document.policy.password = /wwwassets/password_policy.html | ||||||
| 
 | 
 | ||||||
| # | # | ||||||
| # This section select which form of persistence you need | # This section select which form of persistence you need | ||||||
| @@ -121,7 +121,7 @@ logging.channels.c1.formatter = f1 | |||||||
| 
 | 
 | ||||||
| # This is where the logs will be written. This path MUST exist | # This is where the logs will be written. This path MUST exist | ||||||
| logging.channels.c2.class = FileChannel | logging.channels.c2.class = FileChannel | ||||||
| logging.channels.c2.path = $OWSEC_ROOT/logs/log | logging.channels.c2.path = $UCENTRALSEC_ROOT/logs/log | ||||||
| logging.channels.c2.formatter.class = PatternFormatter | logging.channels.c2.formatter.class = PatternFormatter | ||||||
| logging.channels.c2.formatter.pattern = %Y-%m-%d %H:%M:%S %s: [%p] %t | logging.channels.c2.formatter.pattern = %Y-%m-%d %H:%M:%S %s: [%p] %t | ||||||
| logging.channels.c2.rotation = 20 M | logging.channels.c2.rotation = 20 M | ||||||
							
								
								
									
										45
									
								
								ucentralsec.service
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								ucentralsec.service
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | |||||||
|  | [Unit] | ||||||
|  | Description=OpenWiFi Security Service | ||||||
|  | After=network-online.target docker.service | ||||||
|  | Wants=network-online.target | ||||||
|  |  | ||||||
|  | [Service] | ||||||
|  | Type=simple | ||||||
|  | # the default is not to use systemd for cgroups because the delegate issues still | ||||||
|  | # exists and systemd currently does not support the cgroup feature set required | ||||||
|  | # for containers run by docker | ||||||
|  | Environment="UCENTRALSEC_ROOT=/home/admin/dev/wlan-cloud-ucentralsec" | ||||||
|  | ExecStart=/home/admin/dev/wlan-cloud-ucentralsec/cmake-build/ucentralsec | ||||||
|  | WorkingDirectory=/home/admin/dev/wlan-cloud-ucentralsec | ||||||
|  | ExecReload=/bin/kill -s HUP $MAINPID | ||||||
|  | User=admin | ||||||
|  | TimeoutSec=0 | ||||||
|  | RestartSec=2 | ||||||
|  | Restart=always | ||||||
|  |  | ||||||
|  | # Note that StartLimit* options were moved from "Service" to "Unit" in systemd 229. | ||||||
|  | # Both the old, and new location are accepted by systemd 229 and up, so using the old location | ||||||
|  | # to make them work for either version of systemd. | ||||||
|  | StartLimitBurst=3 | ||||||
|  |  | ||||||
|  | # Note that StartLimitInterval was renamed to StartLimitIntervalSec in systemd 230. | ||||||
|  | # Both the old, and new name are accepted by systemd 230 and up, so using the old name to make | ||||||
|  | # this option work for either version of systemd. | ||||||
|  | # StartLimitInterval=60s | ||||||
|  |  | ||||||
|  | # Having non-zero Limit*s causes performance problems due to accounting overhead | ||||||
|  | # in the kernel. We recommend using cgroups to do container-local accounting. | ||||||
|  | LimitNOFILE=infinity | ||||||
|  | LimitNPROC=infinity | ||||||
|  | LimitCORE=infinity | ||||||
|  |  | ||||||
|  | # Comment TasksMax if your systemd version does not support it. | ||||||
|  | # Only systemd 226 and above support this option. | ||||||
|  | TasksMax=infinity | ||||||
|  |  | ||||||
|  | # set delegate yes so that systemd does not reset the cgroups of docker containers | ||||||
|  | Delegate=yes | ||||||
|  |  | ||||||
|  | # kill only the docker process, not all processes in the cgroup | ||||||
|  | KillMode=process | ||||||
|  | OOMScoreAdjust=-500 | ||||||
		Reference in New Issue
	
	Block a user