mirror of
				https://github.com/Telecominfraproject/wlan-cloud-ucentralsec.git
				synced 2025-11-03 20:27:45 +00:00 
			
		
		
		
	Compare commits
	
		
			191 Commits
		
	
	
		
			release/v2
			...
			v2.5.0
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					96b712eba1 | ||
| 
						 | 
					8b45bfd812 | ||
| 
						 | 
					e0a57a4846 | ||
| 
						 | 
					a72e286a83 | ||
| 
						 | 
					2fb80c68dd | ||
| 
						 | 
					0652c13139 | ||
| 
						 | 
					feb5ff1f2c | ||
| 
						 | 
					5a9a62ff7e | ||
| 
						 | 
					bd331913e1 | ||
| 
						 | 
					5756e31ae6 | ||
| 
						 | 
					884b91af63 | ||
| 
						 | 
					fed43efadf | ||
| 
						 | 
					48d3e56b79 | ||
| 
						 | 
					a0f9abea88 | ||
| 
						 | 
					3e0ecda9d6 | ||
| 
						 | 
					ad38d8e84c | ||
| 
						 | 
					27c581750c | ||
| 
						 | 
					e09ee35940 | ||
| 
						 | 
					3c4d9612d3 | ||
| 
						 | 
					6485b2426c | ||
| 
						 | 
					3d3dbc6b4d | ||
| 
						 | 
					8965b3c590 | ||
| 
						 | 
					77941c4775 | ||
| 
						 | 
					ef9cd80df6 | ||
| 
						 | 
					042f7619ec | ||
| 
						 | 
					8a371d7eaf | ||
| 
						 | 
					ac92c7da85 | ||
| 
						 | 
					7a8449efbf | ||
| 
						 | 
					8365aa5463 | ||
| 
						 | 
					1c4f961971 | ||
| 
						 | 
					19c92edfcc | ||
| 
						 | 
					3fd6e6b849 | ||
| 
						 | 
					bc6d8a8a79 | ||
| 
						 | 
					29da9b4b8e | ||
| 
						 | 
					b3f1f35bb4 | ||
| 
						 | 
					a9bd44b3b2 | ||
| 
						 | 
					01f457dd0c | ||
| 
						 | 
					f27f036e62 | ||
| 
						 | 
					27f8d06cab | ||
| 
						 | 
					7960cda46e | ||
| 
						 | 
					9907f91c49 | ||
| 
						 | 
					b3b98d90ca | ||
| 
						 | 
					ef947c3e33 | ||
| 
						 | 
					a5eb0d792b | ||
| 
						 | 
					151585f6e5 | ||
| 
						 | 
					7fc7daf595 | ||
| 
						 | 
					ebe2df4dc7 | ||
| 
						 | 
					9dcc19f4fe | ||
| 
						 | 
					984ba88341 | ||
| 
						 | 
					b14eba63c3 | ||
| 
						 | 
					b8c02906ea | ||
| 
						 | 
					f3c3539f62 | ||
| 
						 | 
					5fef83d726 | ||
| 
						 | 
					874e28ffff | ||
| 
						 | 
					f84b8c4b5c | ||
| 
						 | 
					ae6a986e57 | ||
| 
						 | 
					04cffd13c8 | ||
| 
						 | 
					28635dcbdd | ||
| 
						 | 
					6a67bf80af | ||
| 
						 | 
					9460cc1e5b | ||
| 
						 | 
					6d20c8408f | ||
| 
						 | 
					fd21917a93 | ||
| 
						 | 
					c47e9bc98d | ||
| 
						 | 
					30431ab954 | ||
| 
						 | 
					76175d8bbb | ||
| 
						 | 
					36e16e3c8e | ||
| 
						 | 
					cc4e5848a5 | ||
| 
						 | 
					8425950da7 | ||
| 
						 | 
					cf903a57ab | ||
| 
						 | 
					d38e4ca2fc | ||
| 
						 | 
					584254cb07 | ||
| 
						 | 
					dcf7ff5f48 | ||
| 
						 | 
					1039a53925 | ||
| 
						 | 
					a80bcd16d8 | ||
| 
						 | 
					fce18f6238 | ||
| 
						 | 
					f8c6dad974 | ||
| 
						 | 
					eec8662a3c | ||
| 
						 | 
					f26c6e1454 | ||
| 
						 | 
					08a50db13c | ||
| 
						 | 
					7b741048ff | ||
| 
						 | 
					7fcd451e3b | ||
| 
						 | 
					c545be6ae9 | ||
| 
						 | 
					b1f489bf4f | ||
| 
						 | 
					92910fe0c5 | ||
| 
						 | 
					eda30b3dc3 | ||
| 
						 | 
					51dd7bdfa7 | ||
| 
						 | 
					2eccf1ef06 | ||
| 
						 | 
					b37edca02c | ||
| 
						 | 
					e831619673 | ||
| 
						 | 
					78ae79b1d5 | ||
| 
						 | 
					2bc6d7c325 | ||
| 
						 | 
					0f6a95a330 | ||
| 
						 | 
					83a1d80d77 | ||
| 
						 | 
					84bcb28328 | ||
| 
						 | 
					4d03faf523 | ||
| 
						 | 
					73096153b4 | ||
| 
						 | 
					1cf9894f7d | ||
| 
						 | 
					f54cd95fc4 | ||
| 
						 | 
					882226ccdb | ||
| 
						 | 
					e5f10ccd17 | ||
| 
						 | 
					c500ae36b1 | ||
| 
						 | 
					6ead810ec6 | ||
| 
						 | 
					c6ac384cdb | ||
| 
						 | 
					f28e07a615 | ||
| 
						 | 
					c7c5401bc2 | ||
| 
						 | 
					6264c7f3bb | ||
| 
						 | 
					c078bdb555 | ||
| 
						 | 
					81131b8038 | ||
| 
						 | 
					4633db416d | ||
| 
						 | 
					6c14337333 | ||
| 
						 | 
					784fc3256b | ||
| 
						 | 
					2c513d8374 | ||
| 
						 | 
					d202b9e365 | ||
| 
						 | 
					b869da3b09 | ||
| 
						 | 
					f31195e854 | ||
| 
						 | 
					ec4ab520d8 | ||
| 
						 | 
					a9ade83094 | ||
| 
						 | 
					977742d802 | ||
| 
						 | 
					b69b90b243 | ||
| 
						 | 
					ec0aa4e15a | ||
| 
						 | 
					5fc313aa50 | ||
| 
						 | 
					a3975829e4 | ||
| 
						 | 
					e8cf7a6f21 | ||
| 
						 | 
					d27441d793 | ||
| 
						 | 
					ae5c32a8ec | ||
| 
						 | 
					96c684fe5e | ||
| 
						 | 
					8609990551 | ||
| 
						 | 
					4566bb942c | ||
| 
						 | 
					e5d6f42433 | ||
| 
						 | 
					524f79e825 | ||
| 
						 | 
					be46b46340 | ||
| 
						 | 
					5ff0841112 | ||
| 
						 | 
					a6c115adb5 | ||
| 
						 | 
					4d474fe92c | ||
| 
						 | 
					4b46e0c9c9 | ||
| 
						 | 
					de0ddc769b | ||
| 
						 | 
					4a11602fb9 | ||
| 
						 | 
					ef1f7098a6 | ||
| 
						 | 
					38eebe6162 | ||
| 
						 | 
					5124ed016c | ||
| 
						 | 
					fb632b6ce1 | ||
| 
						 | 
					775d0c0a65 | ||
| 
						 | 
					fb2ddaa136 | ||
| 
						 | 
					f51e00c50c | ||
| 
						 | 
					da49bebb15 | ||
| 
						 | 
					916d5cdf13 | ||
| 
						 | 
					5eecfbfd30 | ||
| 
						 | 
					32a5c81f1d | ||
| 
						 | 
					a72189f854 | ||
| 
						 | 
					2be40d5d17 | ||
| 
						 | 
					f8407f7b7c | ||
| 
						 | 
					2ec792a74b | ||
| 
						 | 
					72f0b11f81 | ||
| 
						 | 
					00965b78c7 | ||
| 
						 | 
					b2c06affa8 | ||
| 
						 | 
					7b467850b6 | ||
| 
						 | 
					be89574363 | ||
| 
						 | 
					e4d3855251 | ||
| 
						 | 
					57bd712634 | ||
| 
						 | 
					797f4e9c80 | ||
| 
						 | 
					309a856cd0 | ||
| 
						 | 
					937a20beea | ||
| 
						 | 
					2217a428c1 | ||
| 
						 | 
					ec82bdec24 | ||
| 
						 | 
					40faa84d2b | ||
| 
						 | 
					cb3efcecb5 | ||
| 
						 | 
					e11d955529 | ||
| 
						 | 
					5a4eafee7d | ||
| 
						 | 
					2df45c26a4 | ||
| 
						 | 
					311786f8d8 | ||
| 
						 | 
					829de62967 | ||
| 
						 | 
					55d1f9571d | ||
| 
						 | 
					80a520c4cc | ||
| 
						 | 
					040623fc8c | ||
| 
						 | 
					dc6eaaeb89 | ||
| 
						 | 
					4953aa02dc | ||
| 
						 | 
					e794647469 | ||
| 
						 | 
					e87bdc9440 | ||
| 
						 | 
					a8f59e0fb5 | ||
| 
						 | 
					2730a8c5e4 | ||
| 
						 | 
					b3ef448628 | ||
| 
						 | 
					13fe7d295b | ||
| 
						 | 
					ef1eb190a2 | ||
| 
						 | 
					370d4aca47 | ||
| 
						 | 
					a575d95b91 | ||
| 
						 | 
					0477ab5349 | ||
| 
						 | 
					730f8d169a | ||
| 
						 | 
					be7f50ccbb | ||
| 
						 | 
					8d681988a9 | ||
| 
						 | 
					8842f23a8e | ||
| 
						 | 
					5e5150a73f | 
							
								
								
									
										79
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										79
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							@@ -25,45 +25,46 @@ jobs:
 | 
				
			|||||||
      DOCKER_REGISTRY_URL: tip-tip-wlan-cloud-ucentral.jfrog.io
 | 
					      DOCKER_REGISTRY_URL: tip-tip-wlan-cloud-ucentral.jfrog.io
 | 
				
			||||||
      DOCKER_REGISTRY_USERNAME: ucentral
 | 
					      DOCKER_REGISTRY_USERNAME: ucentral
 | 
				
			||||||
    steps:
 | 
					    steps:
 | 
				
			||||||
    - uses: actions/checkout@v2
 | 
					    - name: Checkout actions repo
 | 
				
			||||||
 | 
					      uses: actions/checkout@v2
 | 
				
			||||||
    - name: Build Docker image
 | 
					 | 
				
			||||||
      run: docker build -t wlan-cloud-owsec:${{ github.sha }} .
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    - name: Tag Docker image
 | 
					 | 
				
			||||||
      run: |
 | 
					 | 
				
			||||||
        TAGS="${{ github.sha }}"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if [[ ${GITHUB_REF} == "refs/heads/"* ]]
 | 
					 | 
				
			||||||
        then
 | 
					 | 
				
			||||||
          CURRENT_TAG=$(echo ${GITHUB_REF#refs/heads/} | tr '/' '-')
 | 
					 | 
				
			||||||
          TAGS="$TAGS $CURRENT_TAG"
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
          if [[ ${GITHUB_REF} == "refs/tags/"* ]]
 | 
					 | 
				
			||||||
          then
 | 
					 | 
				
			||||||
            CURRENT_TAG=$(echo ${GITHUB_REF#refs/tags/} | tr '/' '-')
 | 
					 | 
				
			||||||
            TAGS="$TAGS $CURRENT_TAG"
 | 
					 | 
				
			||||||
          else # PR build
 | 
					 | 
				
			||||||
            CURRENT_TAG=$(echo ${GITHUB_HEAD_REF#refs/heads/} | tr '/' '-')
 | 
					 | 
				
			||||||
            TAGS="$TAGS $CURRENT_TAG"
 | 
					 | 
				
			||||||
          fi
 | 
					 | 
				
			||||||
        fi
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        echo "Result tags: $TAGS"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for tag in $TAGS; do
 | 
					 | 
				
			||||||
          docker tag wlan-cloud-owsec:${{ github.sha }} ${{ env.DOCKER_REGISTRY_URL }}/owsec:$tag
 | 
					 | 
				
			||||||
        done
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    - name: Log into Docker registry
 | 
					 | 
				
			||||||
      if: startsWith(github.ref, 'refs/tags/') || startsWith(github.ref, 'refs/pull/') || github.ref == 'refs/heads/main'
 | 
					 | 
				
			||||||
      uses: docker/login-action@v1
 | 
					 | 
				
			||||||
      with:
 | 
					      with:
 | 
				
			||||||
        registry: ${{ env.DOCKER_REGISTRY_URL }}
 | 
					        repository: Telecominfraproject/.github
 | 
				
			||||||
        username: ${{ env.DOCKER_REGISTRY_USERNAME }}
 | 
					        path: github
 | 
				
			||||||
        password: ${{ secrets.DOCKER_REGISTRY_PASSWORD }}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    - name: Push Docker images
 | 
					    - name: Build and push Docker image
 | 
				
			||||||
      if: startsWith(github.ref, 'refs/tags/') || startsWith(github.ref, 'refs/pull/') || github.ref == 'refs/heads/main'
 | 
					      uses: ./github/composite-actions/docker-image-build
 | 
				
			||||||
 | 
					      with:
 | 
				
			||||||
 | 
					        image_name: owsec
 | 
				
			||||||
 | 
					        registry: tip-tip-wlan-cloud-ucentral.jfrog.io
 | 
				
			||||||
 | 
					        registry_user: ucentral
 | 
				
			||||||
 | 
					        registry_password: ${{ secrets.DOCKER_REGISTRY_PASSWORD }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  trigger-testing:
 | 
				
			||||||
 | 
					    if: startsWith(github.ref, 'refs/pull/')
 | 
				
			||||||
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
 | 
					    needs: docker
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					    - name: Get base branch name and set as output
 | 
				
			||||||
 | 
					      id: get_base_branch
 | 
				
			||||||
      run: |
 | 
					      run: |
 | 
				
			||||||
        docker images | grep ${{ env.DOCKER_REGISTRY_URL }}/owsec | awk -F ' ' '{print $1":"$2}' | xargs -I {} docker push {}
 | 
					        echo ::set-output name=branch::$(echo ${GITHUB_BASE_REF##*/})
 | 
				
			||||||
 | 
					        echo ::set-output name=owgw_branch::$(echo ${GITHUB_BASE_REF##*/} | sed 's/main/master/g')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - name: Checkout actions repo
 | 
				
			||||||
 | 
					      uses: actions/checkout@v2
 | 
				
			||||||
 | 
					      with:
 | 
				
			||||||
 | 
					        repository: Telecominfraproject/.github
 | 
				
			||||||
 | 
					        path: github
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - name: Trigger testing of OpenWifi Docker Compose deployment and wait for result
 | 
				
			||||||
 | 
					      uses: ./github/composite-actions/trigger-workflow-and-wait
 | 
				
			||||||
 | 
					      env:
 | 
				
			||||||
 | 
					        BASE_BRANCH: ${{ steps.get_base_branch.outputs.branch }}
 | 
				
			||||||
 | 
					        OWGW_BASE_BRANCH: ${{ steps.get_base_branch.outputs.owgw_branch }}
 | 
				
			||||||
 | 
					      with:
 | 
				
			||||||
 | 
					        owner: Telecominfraproject
 | 
				
			||||||
 | 
					        repo: wlan-testing
 | 
				
			||||||
 | 
					        workflow: ow_docker-compose.yml
 | 
				
			||||||
 | 
					        token: ${{ secrets.WLAN_TESTING_PAT }}
 | 
				
			||||||
 | 
					        ref: master
 | 
				
			||||||
 | 
					        inputs: '{"owgw_version": "${{ env.OWGW_BASE_BRANCH }}", "owgwui_version": "${{ env.BASE_BRANCH }}", "owsec_version": "${{ github.sha }}", "owfms_version": "${{ env.BASE_BRANCH }}", "owprov_version": "main", "owprovui_version": "main"}'
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										24
									
								
								.github/workflows/enforce-jira-issue-key.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								.github/workflows/enforce-jira-issue-key.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					name: Ensure Jira issue is linked
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					on:
 | 
				
			||||||
 | 
					  pull_request:
 | 
				
			||||||
 | 
					    types: [opened, edited, reopened, synchronize]
 | 
				
			||||||
 | 
					    branches:
 | 
				
			||||||
 | 
					      - 'release/*'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					jobs:
 | 
				
			||||||
 | 
					  check_for_issue_key:
 | 
				
			||||||
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
 | 
					    steps:
 | 
				
			||||||
 | 
					      - name: Checkout actions repo
 | 
				
			||||||
 | 
					        uses: actions/checkout@v2
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          repository: Telecominfraproject/.github
 | 
				
			||||||
 | 
					          path: github
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      - name: Run JIRA check
 | 
				
			||||||
 | 
					        uses: ./github/composite-actions/enforce-jira-issue-key
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          jira_base_url: ${{ secrets.TIP_JIRA_URL }}
 | 
				
			||||||
 | 
					          jira_user_email: ${{ secrets.TIP_JIRA_USER_EMAIL }}
 | 
				
			||||||
 | 
					          jira_api_token: ${{ secrets.TIP_JIRA_API_TOKEN }}
 | 
				
			||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
cmake_minimum_required(VERSION 3.13)
 | 
					cmake_minimum_required(VERSION 3.13)
 | 
				
			||||||
project(owsec VERSION 2.4.0)
 | 
					project(owsec VERSION 2.5.0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set(CMAKE_CXX_STANDARD 17)
 | 
					set(CMAKE_CXX_STANDARD 17)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -20,19 +20,32 @@ endif()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# Auto build increment. You must define BUILD_INCREMENT with cmake -DBUILD_INCREMENT=1
 | 
					# Auto build increment. You must define BUILD_INCREMENT with cmake -DBUILD_INCREMENT=1
 | 
				
			||||||
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/build)
 | 
					if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/build)
 | 
				
			||||||
    file(READ build BUILD_NUM)
 | 
					    file(READ ${CMAKE_CURRENT_SOURCE_DIR}/build BUILD_NUM)
 | 
				
			||||||
    if(BUILD_INCREMENT)
 | 
					    if(BUILD_INCREMENT)
 | 
				
			||||||
        MATH(EXPR BUILD_NUM "${BUILD_NUM}+1")
 | 
					        MATH(EXPR BUILD_NUM "${BUILD_NUM}+1")
 | 
				
			||||||
        file(WRITE build ${BUILD_NUM})
 | 
					        file(WRITE ${CMAKE_CURRENT_SOURCE_DIR}/build ${BUILD_NUM})
 | 
				
			||||||
    endif()
 | 
					    endif()
 | 
				
			||||||
else()
 | 
					else()
 | 
				
			||||||
    set(BUILD_NUM 1)
 | 
					    set(BUILD_NUM 1)
 | 
				
			||||||
    file(WRITE build ${BUILD_NUM})
 | 
					    file(WRITE ${CMAKE_CURRENT_SOURCE_DIR}/build ${BUILD_NUM})
 | 
				
			||||||
endif()
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					find_package(Git QUIET)
 | 
				
			||||||
 | 
					if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git")
 | 
				
			||||||
 | 
					    execute_process(COMMAND ${GIT_EXECUTABLE} describe --always --tags
 | 
				
			||||||
 | 
					            WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
 | 
				
			||||||
 | 
					            RESULT_VARIABLE GIT_RESULT
 | 
				
			||||||
 | 
					            OUTPUT_VARIABLE GIT_HASH)
 | 
				
			||||||
 | 
					    if(NOT GIT_RESULT EQUAL "0")
 | 
				
			||||||
 | 
					        message(FATAL_ERROR "git describe --always --tags failed with ${GIT_RESULT}")
 | 
				
			||||||
 | 
					    endif()
 | 
				
			||||||
 | 
					    string(REGEX REPLACE "\n$" "" GIT_HASH "${GIT_HASH}")
 | 
				
			||||||
 | 
					endif()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					add_definitions(-DAWS_CUSTOM_MEMORY_MANAGEMENT)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set(BUILD_SHARED_LIBS 1)
 | 
					set(BUILD_SHARED_LIBS 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
add_definitions(-DAPP_VERSION="${CMAKE_PROJECT_VERSION}" -DBUILD_NUMBER="${BUILD_NUM}")
 | 
					 | 
				
			||||||
add_definitions(-DTIP_SECURITY_SERVICE="1")
 | 
					add_definitions(-DTIP_SECURITY_SERVICE="1")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set(Boost_USE_STATIC_LIBS OFF)
 | 
					set(Boost_USE_STATIC_LIBS OFF)
 | 
				
			||||||
@@ -50,35 +63,48 @@ find_package(Poco REQUIRED COMPONENTS JSON Crypto JWT Net Util NetSSL Data DataS
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
include_directories(/usr/local/include  /usr/local/opt/openssl/include src include/kafka /usr/local/opt/mysql-client/include)
 | 
					include_directories(/usr/local/include  /usr/local/opt/openssl/include src include/kafka /usr/local/opt/mysql-client/include)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					configure_file(src/ow_version.h.in ${PROJECT_SOURCE_DIR}/src/ow_version.h @ONLY)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
add_executable( owsec
 | 
					add_executable( owsec
 | 
				
			||||||
        build
 | 
					        build
 | 
				
			||||||
 | 
					        src/ow_version.h.in
 | 
				
			||||||
        src/framework/CountryCodes.h
 | 
					        src/framework/CountryCodes.h
 | 
				
			||||||
        src/framework/KafkaTopics.h
 | 
					        src/framework/KafkaTopics.h
 | 
				
			||||||
        src/framework/MicroService.h
 | 
					        src/framework/MicroService.h
 | 
				
			||||||
        src/framework/OpenWifiTypes.h
 | 
					 | 
				
			||||||
        src/framework/orm.h
 | 
					        src/framework/orm.h
 | 
				
			||||||
        src/framework/RESTAPI_errors.h
 | 
					        src/framework/RESTAPI_errors.h
 | 
				
			||||||
        src/framework/RESTAPI_protocol.h
 | 
					        src/framework/RESTAPI_protocol.h
 | 
				
			||||||
        src/framework/StorageClass.h
 | 
					        src/framework/StorageClass.h
 | 
				
			||||||
        src/framework/uCentral_Protocol.h
 | 
					        src/framework/uCentral_Protocol.h
 | 
				
			||||||
 | 
					        src/seclibs/qrcode/qrcodegen.hpp src/seclibs/qrcode/qrcodegen.cpp
 | 
				
			||||||
 | 
					        src/seclibs/cpptotp/bytes.cpp src/seclibs/cpptotp/bytes.h
 | 
				
			||||||
 | 
					        src/seclibs/cpptotp/otp.cpp src/seclibs/cpptotp/otp.h
 | 
				
			||||||
 | 
					        src/seclibs/cpptotp/sha1.cpp src/seclibs/cpptotp/sha1.h
 | 
				
			||||||
        src/RESTObjects/RESTAPI_SecurityObjects.h src/RESTObjects/RESTAPI_SecurityObjects.cpp
 | 
					        src/RESTObjects/RESTAPI_SecurityObjects.h src/RESTObjects/RESTAPI_SecurityObjects.cpp
 | 
				
			||||||
        src/RESTObjects/RESTAPI_ProvObjects.cpp src/RESTObjects/RESTAPI_ProvObjects.h
 | 
					        src/RESTObjects/RESTAPI_ProvObjects.cpp src/RESTObjects/RESTAPI_ProvObjects.h
 | 
				
			||||||
        src/RESTObjects/RESTAPI_GWobjects.h src/RESTObjects/RESTAPI_GWobjects.cpp
 | 
					        src/RESTObjects/RESTAPI_GWobjects.h src/RESTObjects/RESTAPI_GWobjects.cpp
 | 
				
			||||||
        src/RESTObjects/RESTAPI_FMSObjects.h src/RESTObjects/RESTAPI_FMSObjects.cpp
 | 
					        src/RESTObjects/RESTAPI_FMSObjects.h src/RESTObjects/RESTAPI_FMSObjects.cpp
 | 
				
			||||||
        src/RESTAPI/RESTAPI_oauth2Handler.h src/RESTAPI/RESTAPI_oauth2Handler.cpp
 | 
					        src/RESTAPI/RESTAPI_oauth2_handler.h src/RESTAPI/RESTAPI_oauth2_handler.cpp
 | 
				
			||||||
        src/RESTAPI/RESTAPI_users_handler.cpp src/RESTAPI/RESTAPI_users_handler.h
 | 
					        src/RESTAPI/RESTAPI_users_handler.cpp src/RESTAPI/RESTAPI_users_handler.h
 | 
				
			||||||
        src/RESTAPI/RESTAPI_user_handler.cpp src/RESTAPI/RESTAPI_user_handler.h
 | 
					        src/RESTAPI/RESTAPI_user_handler.cpp src/RESTAPI/RESTAPI_user_handler.h
 | 
				
			||||||
        src/RESTAPI/RESTAPI_action_links.cpp src/RESTAPI/RESTAPI_action_links.h
 | 
					        src/RESTAPI/RESTAPI_action_links.cpp src/RESTAPI/RESTAPI_action_links.h
 | 
				
			||||||
        src/RESTAPI/RESTAPI_validateToken_handler.cpp src/RESTAPI/RESTAPI_validateToken_handler.h
 | 
					        src/RESTAPI/RESTAPI_validate_token_handler.cpp src/RESTAPI/RESTAPI_validate_token_handler.h
 | 
				
			||||||
        src/RESTAPI/RESTAPI_systemEndpoints_handler.cpp src/RESTAPI/RESTAPI_systemEndpoints_handler.h
 | 
					        src/RESTAPI/RESTAPI_system_endpoints_handler.cpp src/RESTAPI/RESTAPI_system_endpoints_handler.h
 | 
				
			||||||
        src/RESTAPI/RESTAPI_AssetServer.cpp src/RESTAPI/RESTAPI_AssetServer.h
 | 
					        src/RESTAPI/RESTAPI_asset_server.cpp src/RESTAPI/RESTAPI_asset_server.h
 | 
				
			||||||
        src/RESTAPI/RESTAPI_avatarHandler.cpp src/RESTAPI/RESTAPI_avatarHandler.h
 | 
					        src/RESTAPI/RESTAPI_avatar_handler.cpp src/RESTAPI/RESTAPI_avatar_handler.h
 | 
				
			||||||
 | 
					        src/RESTAPI/RESTAPI_subavatar_handler.cpp src/RESTAPI/RESTAPI_subavatar_handler.h
 | 
				
			||||||
        src/RESTAPI/RESTAPI_email_handler.cpp src/RESTAPI/RESTAPI_email_handler.h
 | 
					        src/RESTAPI/RESTAPI_email_handler.cpp src/RESTAPI/RESTAPI_email_handler.h
 | 
				
			||||||
        src/RESTAPI/RESTAPI_sms_handler.cpp src/RESTAPI/RESTAPI_sms_handler.h
 | 
					        src/RESTAPI/RESTAPI_sms_handler.cpp src/RESTAPI/RESTAPI_sms_handler.h
 | 
				
			||||||
        src/storage/storage_avatar.cpp src/storage/storage_avatar.h src/storage/storage_users.h
 | 
					        src/RESTAPI/RESTAPI_suboauth2_handler.h src/RESTAPI/RESTAPI_suboauth2_handler.cpp
 | 
				
			||||||
        src/storage/storage_tables.cpp src/storage/storage_users.cpp src/storage/storage_tokens.cpp
 | 
					        src/RESTAPI/RESTAPI_subuser_handler.h src/RESTAPI/RESTAPI_subuser_handler.cpp
 | 
				
			||||||
        src/APIServers.cpp
 | 
					        src/RESTAPI/RESTAPI_subusers_handler.h src/RESTAPI/RESTAPI_subusers_handler.cpp
 | 
				
			||||||
 | 
					        src/RESTAPI/RESTAPI_validate_sub_token_handler.cpp src/RESTAPI/RESTAPI_validate_sub_token_handler.h
 | 
				
			||||||
 | 
					        src/RESTAPI/RESTAPI_submfa_handler.cpp src/RESTAPI/RESTAPI_submfa_handler.h
 | 
				
			||||||
 | 
					        src/RESTAPI/RESTAPI_preferences.cpp src/RESTAPI/RESTAPI_preferences.h
 | 
				
			||||||
 | 
					        src/RESTAPI/RESTAPI_subpreferences.cpp src/RESTAPI/RESTAPI_subpreferences.h
 | 
				
			||||||
 | 
					        src/RESTAPI/RESTAPI_routers.cpp
 | 
				
			||||||
        src/Daemon.h src/Daemon.cpp
 | 
					        src/Daemon.h src/Daemon.cpp
 | 
				
			||||||
 | 
					        src/SpecialUserHelpers.h
 | 
				
			||||||
        src/AuthService.h src/AuthService.cpp
 | 
					        src/AuthService.h src/AuthService.cpp
 | 
				
			||||||
        src/StorageService.cpp src/StorageService.h
 | 
					        src/StorageService.cpp src/StorageService.h
 | 
				
			||||||
        src/SMTPMailerService.cpp src/SMTPMailerService.h
 | 
					        src/SMTPMailerService.cpp src/SMTPMailerService.h
 | 
				
			||||||
@@ -87,10 +113,16 @@ add_executable( owsec
 | 
				
			|||||||
        src/SMS_provider_aws.cpp src/SMS_provider_aws.h
 | 
					        src/SMS_provider_aws.cpp src/SMS_provider_aws.h
 | 
				
			||||||
        src/SMS_provider.cpp src/SMS_provider.h
 | 
					        src/SMS_provider.cpp src/SMS_provider.h
 | 
				
			||||||
        src/SMS_provider_twilio.cpp src/SMS_provider_twilio.h
 | 
					        src/SMS_provider_twilio.cpp src/SMS_provider_twilio.h
 | 
				
			||||||
        src/storage/storage_actionLinks.cpp src/storage/storage_actionLinks.h
 | 
					 | 
				
			||||||
        src/storage/storage_tokens.h
 | 
					 | 
				
			||||||
        src/ActionLinkManager.cpp src/ActionLinkManager.h
 | 
					        src/ActionLinkManager.cpp src/ActionLinkManager.h
 | 
				
			||||||
        src/ACLProcessor.h)
 | 
					        src/ACLProcessor.h
 | 
				
			||||||
 | 
					        src/framework/OpenWifiTypes.h
 | 
				
			||||||
 | 
					        src/storage/orm_users.cpp src/storage/orm_users.h
 | 
				
			||||||
 | 
					        src/storage/orm_tokens.cpp src/storage/orm_tokens.h
 | 
				
			||||||
 | 
					        src/storage/orm_preferences.cpp src/storage/orm_preferences.h
 | 
				
			||||||
 | 
					        src/storage/orm_actionLinks.cpp src/storage/orm_actionLinks.h
 | 
				
			||||||
 | 
					        src/storage/orm_avatar.cpp src/storage/orm_avatar.h
 | 
				
			||||||
 | 
					        src/SpecialUserHelpers.h
 | 
				
			||||||
 | 
					        src/RESTAPI/RESTAPI_db_helpers.h src/storage/orm_logins.cpp src/storage/orm_logins.h src/RESTAPI/RESTAPI_totp_handler.cpp src/RESTAPI/RESTAPI_totp_handler.h src/TotpCache.h src/RESTAPI/RESTAPI_subtotp_handler.cpp src/RESTAPI/RESTAPI_subtotp_handler.h)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if(NOT SMALL_BUILD)
 | 
					if(NOT SMALL_BUILD)
 | 
				
			||||||
    target_link_libraries(owsec PUBLIC
 | 
					    target_link_libraries(owsec PUBLIC
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										113
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										113
									
								
								Dockerfile
									
									
									
									
									
								
							@@ -1,18 +1,51 @@
 | 
				
			|||||||
FROM alpine AS builder
 | 
					FROM alpine:3.15 AS build-base
 | 
				
			||||||
 | 
					
 | 
				
			||||||
RUN apk add --update --no-cache \
 | 
					RUN apk add --update --no-cache \
 | 
				
			||||||
    openssl openssh \
 | 
					    make cmake g++ git \
 | 
				
			||||||
    ncurses-libs \
 | 
					    unixodbc-dev postgresql-dev mariadb-dev \
 | 
				
			||||||
    bash util-linux coreutils curl libcurl \
 | 
					    librdkafka-dev boost-dev openssl-dev \
 | 
				
			||||||
    make cmake gcc g++ libstdc++ libgcc git zlib-dev \
 | 
					    zlib-dev nlohmann-json \
 | 
				
			||||||
    openssl-dev boost-dev curl-dev unixodbc-dev postgresql-dev mariadb-dev \
 | 
					    curl-dev
 | 
				
			||||||
    apache2-utils yaml-dev apr-util-dev \
 | 
					 | 
				
			||||||
    librdkafka-dev
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FROM build-base AS poco-build
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ADD https://api.github.com/repos/stephb9959/poco/git/refs/heads/master version.json
 | 
				
			||||||
RUN git clone https://github.com/stephb9959/poco /poco
 | 
					RUN git clone https://github.com/stephb9959/poco /poco
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					WORKDIR /poco
 | 
				
			||||||
 | 
					RUN mkdir cmake-build
 | 
				
			||||||
 | 
					WORKDIR cmake-build
 | 
				
			||||||
 | 
					RUN cmake ..
 | 
				
			||||||
 | 
					RUN cmake --build . --config Release -j8
 | 
				
			||||||
 | 
					RUN cmake --build . --target install
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FROM build-base AS cppkafka-build
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ADD https://api.github.com/repos/stephb9959/cppkafka/git/refs/heads/master version.json
 | 
				
			||||||
RUN git clone https://github.com/stephb9959/cppkafka /cppkafka
 | 
					RUN git clone https://github.com/stephb9959/cppkafka /cppkafka
 | 
				
			||||||
RUN git clone https://github.com/nlohmann/json /json
 | 
					
 | 
				
			||||||
 | 
					WORKDIR /cppkafka
 | 
				
			||||||
 | 
					RUN mkdir cmake-build
 | 
				
			||||||
 | 
					WORKDIR cmake-build
 | 
				
			||||||
 | 
					RUN cmake ..
 | 
				
			||||||
 | 
					RUN cmake --build . --config Release -j8
 | 
				
			||||||
 | 
					RUN cmake --build . --target install
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FROM build-base AS json-schema-validator-build
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ADD https://api.github.com/repos/pboettch/json-schema-validator/git/refs/heads/master version.json
 | 
				
			||||||
RUN git clone https://github.com/pboettch/json-schema-validator /json-schema-validator
 | 
					RUN git clone https://github.com/pboettch/json-schema-validator /json-schema-validator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					WORKDIR /json-schema-validator
 | 
				
			||||||
 | 
					RUN mkdir cmake-build
 | 
				
			||||||
 | 
					WORKDIR cmake-build
 | 
				
			||||||
 | 
					RUN cmake ..
 | 
				
			||||||
 | 
					RUN make
 | 
				
			||||||
 | 
					RUN make install
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FROM build-base AS aws-sdk-cpp-build
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ADD https://api.github.com/repos/aws/aws-sdk-cpp/git/refs/heads/main version.json
 | 
				
			||||||
RUN git clone --recurse-submodules https://github.com/aws/aws-sdk-cpp /aws-sdk-cpp
 | 
					RUN git clone --recurse-submodules https://github.com/aws/aws-sdk-cpp /aws-sdk-cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
WORKDIR /aws-sdk-cpp
 | 
					WORKDIR /aws-sdk-cpp
 | 
				
			||||||
@@ -25,37 +58,21 @@ RUN cmake .. -DBUILD_ONLY="sns;s3" \
 | 
				
			|||||||
RUN cmake --build . --config Release -j8
 | 
					RUN cmake --build . --config Release -j8
 | 
				
			||||||
RUN cmake --build . --target install
 | 
					RUN cmake --build . --target install
 | 
				
			||||||
 | 
					
 | 
				
			||||||
WORKDIR /cppkafka
 | 
					FROM build-base AS owsec-build
 | 
				
			||||||
RUN mkdir cmake-build
 | 
					 | 
				
			||||||
WORKDIR cmake-build
 | 
					 | 
				
			||||||
RUN cmake ..
 | 
					 | 
				
			||||||
RUN cmake --build . --config Release -j8
 | 
					 | 
				
			||||||
RUN cmake --build . --target install
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
WORKDIR /poco
 | 
					 | 
				
			||||||
RUN mkdir cmake-build
 | 
					 | 
				
			||||||
WORKDIR cmake-build
 | 
					 | 
				
			||||||
RUN cmake ..
 | 
					 | 
				
			||||||
RUN cmake --build . --config Release -j8
 | 
					 | 
				
			||||||
RUN cmake --build . --target install
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
WORKDIR /json
 | 
					 | 
				
			||||||
RUN mkdir cmake-build
 | 
					 | 
				
			||||||
WORKDIR cmake-build
 | 
					 | 
				
			||||||
RUN cmake ..
 | 
					 | 
				
			||||||
RUN make
 | 
					 | 
				
			||||||
RUN make install
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
WORKDIR /json-schema-validator
 | 
					 | 
				
			||||||
RUN mkdir cmake-build
 | 
					 | 
				
			||||||
WORKDIR cmake-build
 | 
					 | 
				
			||||||
RUN cmake ..
 | 
					 | 
				
			||||||
RUN make
 | 
					 | 
				
			||||||
RUN make install
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
ADD CMakeLists.txt build /owsec/
 | 
					ADD CMakeLists.txt build /owsec/
 | 
				
			||||||
ADD cmake /owsec/cmake
 | 
					ADD cmake /owsec/cmake
 | 
				
			||||||
ADD src /owsec/src
 | 
					ADD src /owsec/src
 | 
				
			||||||
 | 
					ADD .git /owsec/.git
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					COPY --from=poco-build /usr/local/include /usr/local/include
 | 
				
			||||||
 | 
					COPY --from=poco-build /usr/local/lib /usr/local/lib
 | 
				
			||||||
 | 
					COPY --from=cppkafka-build /usr/local/include /usr/local/include
 | 
				
			||||||
 | 
					COPY --from=cppkafka-build /usr/local/lib /usr/local/lib
 | 
				
			||||||
 | 
					COPY --from=json-schema-validator-build /usr/local/include /usr/local/include
 | 
				
			||||||
 | 
					COPY --from=json-schema-validator-build /usr/local/lib /usr/local/lib
 | 
				
			||||||
 | 
					COPY --from=aws-sdk-cpp-build /usr/local/include /usr/local/include
 | 
				
			||||||
 | 
					COPY --from=aws-sdk-cpp-build /usr/local/lib /usr/local/lib
 | 
				
			||||||
 | 
					
 | 
				
			||||||
WORKDIR /owsec
 | 
					WORKDIR /owsec
 | 
				
			||||||
RUN mkdir cmake-build
 | 
					RUN mkdir cmake-build
 | 
				
			||||||
@@ -63,7 +80,7 @@ WORKDIR /owsec/cmake-build
 | 
				
			|||||||
RUN cmake ..
 | 
					RUN cmake ..
 | 
				
			||||||
RUN cmake --build . --config Release -j8
 | 
					RUN cmake --build . --config Release -j8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
FROM alpine
 | 
					FROM alpine:3.15
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ENV OWSEC_USER=owsec \
 | 
					ENV OWSEC_USER=owsec \
 | 
				
			||||||
    OWSEC_ROOT=/owsec-data \
 | 
					    OWSEC_ROOT=/owsec-data \
 | 
				
			||||||
@@ -75,23 +92,27 @@ RUN addgroup -S "$OWSEC_USER" && \
 | 
				
			|||||||
RUN mkdir /openwifi
 | 
					RUN mkdir /openwifi
 | 
				
			||||||
RUN mkdir -p "$OWSEC_ROOT" "$OWSEC_CONFIG" && \
 | 
					RUN mkdir -p "$OWSEC_ROOT" "$OWSEC_CONFIG" && \
 | 
				
			||||||
    chown "$OWSEC_USER": "$OWSEC_ROOT" "$OWSEC_CONFIG"
 | 
					    chown "$OWSEC_USER": "$OWSEC_ROOT" "$OWSEC_CONFIG"
 | 
				
			||||||
RUN apk add --update --no-cache librdkafka mariadb-connector-c libpq unixodbc su-exec gettext ca-certificates libcurl curl-dev bash jq curl
 | 
					
 | 
				
			||||||
COPY --from=builder /owsec/cmake-build/owsec /openwifi/owsec
 | 
					RUN apk add --update --no-cache librdkafka su-exec gettext ca-certificates bash jq curl \
 | 
				
			||||||
COPY --from=builder /cppkafka/cmake-build/src/lib/* /lib/
 | 
					    mariadb-connector-c libpq unixodbc postgresql-client
 | 
				
			||||||
COPY --from=builder /poco/cmake-build/lib/* /lib/
 | 
					
 | 
				
			||||||
COPY --from=builder /aws-sdk-cpp/cmake-build/aws-cpp-sdk-core/libaws-cpp-sdk-core.so /lib/
 | 
					COPY readiness_check /readiness_check
 | 
				
			||||||
COPY --from=builder /aws-sdk-cpp/cmake-build/aws-cpp-sdk-s3/libaws-cpp-sdk-s3.so /lib/
 | 
					COPY test_scripts/curl/cli /cli
 | 
				
			||||||
COPY --from=builder /aws-sdk-cpp/cmake-build/aws-cpp-sdk-sns/libaws-cpp-sdk-sns.so /lib/
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
COPY owsec.properties.tmpl /
 | 
					COPY owsec.properties.tmpl /
 | 
				
			||||||
COPY wwwassets /dist/wwwassets
 | 
					COPY wwwassets /dist/wwwassets
 | 
				
			||||||
COPY templates /dist/templates
 | 
					COPY templates /dist/templates
 | 
				
			||||||
COPY docker-entrypoint.sh /
 | 
					COPY docker-entrypoint.sh /
 | 
				
			||||||
 | 
					COPY wait-for-postgres.sh /
 | 
				
			||||||
RUN wget https://raw.githubusercontent.com/Telecominfraproject/wlan-cloud-ucentral-deploy/main/docker-compose/certs/restapi-ca.pem \
 | 
					RUN wget https://raw.githubusercontent.com/Telecominfraproject/wlan-cloud-ucentral-deploy/main/docker-compose/certs/restapi-ca.pem \
 | 
				
			||||||
    -O /usr/local/share/ca-certificates/restapi-ca-selfsigned.pem
 | 
					    -O /usr/local/share/ca-certificates/restapi-ca-selfsigned.pem
 | 
				
			||||||
 | 
					
 | 
				
			||||||
COPY readiness_check /readiness_check
 | 
					COPY --from=owsec-build /owsec/cmake-build/owsec /openwifi/owsec
 | 
				
			||||||
COPY test_scripts/curl/cli /cli
 | 
					COPY --from=cppkafka-build /cppkafka/cmake-build/src/lib/* /usr/local/lib
 | 
				
			||||||
 | 
					COPY --from=poco-build /poco/cmake-build/lib/* /usr/local/lib
 | 
				
			||||||
 | 
					COPY --from=aws-sdk-cpp-build /aws-sdk-cpp/cmake-build/aws-cpp-sdk-core/libaws-cpp-sdk-core.so /usr/local/lib
 | 
				
			||||||
 | 
					COPY --from=aws-sdk-cpp-build /aws-sdk-cpp/cmake-build/aws-cpp-sdk-s3/libaws-cpp-sdk-s3.so /usr/local/lib
 | 
				
			||||||
 | 
					COPY --from=aws-sdk-cpp-build /aws-sdk-cpp/cmake-build/aws-cpp-sdk-sns/libaws-cpp-sdk-sns.so /usr/local/lib
 | 
				
			||||||
 | 
					
 | 
				
			||||||
EXPOSE 16001 17001 16101
 | 
					EXPOSE 16001 17001 16101
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										12
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								README.md
									
									
									
									
									
								
							@@ -218,7 +218,7 @@ This is the FQDN used externally serving the OpenAPI interface.
 | 
				
			|||||||
`owsec` hs the ability to send SMS messages to users during login or to send notifications. In order to do so,
 | 
					`owsec` hs the ability to send SMS messages to users during login or to send notifications. In order to do so,
 | 
				
			||||||
an SMS provider must be configured. At present time, 2 providers are supported: Tilio and AWS SNS
 | 
					an SMS provider must be configured. At present time, 2 providers are supported: Tilio and AWS SNS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### AWS SNS
 | 
					#### AWS SMS
 | 
				
			||||||
For SNS you must create an IAM ID that has sns:sendmessage rights.  
 | 
					For SNS you must create an IAM ID that has sns:sendmessage rights.  
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```asm
 | 
					```asm
 | 
				
			||||||
@@ -252,3 +252,13 @@ mailer.loginmethod = login
 | 
				
			|||||||
mailer.port = 587
 | 
					mailer.port = 587
 | 
				
			||||||
mailer.templates = $OWSEC_ROOT/templates
 | 
					mailer.templates = $OWSEC_ROOT/templates
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### Google Authenticator
 | 
				
			||||||
 | 
					In order to use the Google Time-based One-Time Password (TOTP), the user must down load the Goole Authenticator 
 | 
				
			||||||
 | 
					on any other app that support the TOTP protocol. You should include the following in your configuration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```asm
 | 
				
			||||||
 | 
					totp.issuer = OrgName
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					It is very important that you not use spaces in your OrgName.
 | 
				
			||||||
@@ -25,9 +25,18 @@ if [[ "$TEMPLATE_CONFIG" = 'true' && ! -f "$OWSEC_CONFIG"/owsec.properties ]]; t
 | 
				
			|||||||
  SYSTEM_URI_UI=${SYSTEM_URI_UI:-"http://localhost"} \
 | 
					  SYSTEM_URI_UI=${SYSTEM_URI_UI:-"http://localhost"} \
 | 
				
			||||||
  SERVICE_KEY=${SERVICE_KEY:-"\$OWSEC_ROOT/certs/restapi-key.pem"} \
 | 
					  SERVICE_KEY=${SERVICE_KEY:-"\$OWSEC_ROOT/certs/restapi-key.pem"} \
 | 
				
			||||||
  SERVICE_KEY_PASSWORD=${SERVICE_KEY_PASSWORD:-"mypassword"} \
 | 
					  SERVICE_KEY_PASSWORD=${SERVICE_KEY_PASSWORD:-"mypassword"} \
 | 
				
			||||||
  MAILER_HOSTNAME=${MAILER_HOSTNAME:-"smtp.gmail.com"} \
 | 
					  SMSSENDER_ENABLED=${SMSSENDER_ENABLED:-"false"} \
 | 
				
			||||||
  MAILER_USERNAME=${MAILER_USERNAME:-"************************"} \
 | 
					  SMSSENDER_PROVIDER=${SMSSENDER_PROVIDER:-""} \
 | 
				
			||||||
  MAILER_PASSWORD=${MAILER_PASSWORD:-"************************"} \
 | 
					  SMSSENDER_AWS_SECRETKEY=${SMSSENDER_AWS_SECRETKEY:-""} \
 | 
				
			||||||
 | 
					  SMSSENDER_AWS_ACCESSKEY=${SMSSENDER_AWS_ACCESSKEY:-""} \
 | 
				
			||||||
 | 
					  SMSSENDER_AWS_REGION=${SMSSENDER_AWS_REGION:-""} \
 | 
				
			||||||
 | 
					  SMSSENDER_TWILIO_SID=${SMSSENDER_TWILIO_SID:-""} \
 | 
				
			||||||
 | 
					  SMSSENDER_TWILIO_TOKEN=${SMSSENDER_TWILIO_TOKEN:-""} \
 | 
				
			||||||
 | 
					  SMSSENDER_TWILIO_PHONENUMBER=${SMSSENDER_TWILIO_PHONENUMBER:-""} \
 | 
				
			||||||
 | 
					  MAILER_ENABLED=${MAILER_ENABLED:-"false"} \
 | 
				
			||||||
 | 
					  MAILER_HOSTNAME=${MAILER_HOSTNAME:-"localhost"} \
 | 
				
			||||||
 | 
					  MAILER_USERNAME=${MAILER_USERNAME:-""} \
 | 
				
			||||||
 | 
					  MAILER_PASSWORD=${MAILER_PASSWORD:-""} \
 | 
				
			||||||
  MAILER_SENDER=${MAILER_SENDER:-"OpenWIFI"} \
 | 
					  MAILER_SENDER=${MAILER_SENDER:-"OpenWIFI"} \
 | 
				
			||||||
  MAILER_PORT=${MAILER_PORT:-"587"} \
 | 
					  MAILER_PORT=${MAILER_PORT:-"587"} \
 | 
				
			||||||
  MAILER_TEMPLATES=${MAILER_TEMPLATES:-"\$OWSEC_ROOT/persist/templates"} \
 | 
					  MAILER_TEMPLATES=${MAILER_TEMPLATES:-"\$OWSEC_ROOT/persist/templates"} \
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,14 +5,14 @@ name: owsec
 | 
				
			|||||||
version: 0.1.0
 | 
					version: 0.1.0
 | 
				
			||||||
dependencies:
 | 
					dependencies:
 | 
				
			||||||
- name: postgresql
 | 
					- name: postgresql
 | 
				
			||||||
  repository: https://charts.bitnami.com/bitnami
 | 
					  repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
 | 
				
			||||||
  version: 10.9.2
 | 
					  version: 10.9.2
 | 
				
			||||||
  condition: postgresql.enabled
 | 
					  condition: postgresql.enabled
 | 
				
			||||||
- name: mysql
 | 
					- name: mysql
 | 
				
			||||||
  repository: https://charts.bitnami.com/bitnami
 | 
					  repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
 | 
				
			||||||
  version: 8.8.3
 | 
					  version: 8.8.3
 | 
				
			||||||
  condition: mysql.enabled
 | 
					  condition: mysql.enabled
 | 
				
			||||||
- name: mariadb
 | 
					- name: mariadb
 | 
				
			||||||
  repository: https://charts.bitnami.com/bitnami
 | 
					  repository: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/
 | 
				
			||||||
  version: 9.4.2
 | 
					  version: 9.4.2
 | 
				
			||||||
  condition: mariadb.enabled
 | 
					  condition: mariadb.enabled
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,6 +13,7 @@ spec:
 | 
				
			|||||||
  replicas: {{ .Values.replicaCount }}
 | 
					  replicas: {{ .Values.replicaCount }}
 | 
				
			||||||
  strategy:
 | 
					  strategy:
 | 
				
			||||||
    type: {{ .Values.strategyType }}
 | 
					    type: {{ .Values.strategyType }}
 | 
				
			||||||
 | 
					  revisionHistoryLimit: {{ .Values.revisionHistoryLimit }}
 | 
				
			||||||
  selector:
 | 
					  selector:
 | 
				
			||||||
    matchLabels:
 | 
					    matchLabels:
 | 
				
			||||||
      app.kubernetes.io/name: {{ include "owsec.name" . }}
 | 
					      app.kubernetes.io/name: {{ include "owsec.name" . }}
 | 
				
			||||||
@@ -35,6 +36,16 @@ spec:
 | 
				
			|||||||
        {{- end }}
 | 
					        {{- end }}
 | 
				
			||||||
    spec:
 | 
					    spec:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      initContainers:
 | 
				
			||||||
 | 
					        - name: wait-kafka
 | 
				
			||||||
 | 
					          image: "{{ .Values.images.dockerize.repository }}:{{ .Values.images.dockerize.tag }}"
 | 
				
			||||||
 | 
					          imagePullPolicy: {{ .Values.images.dockerize.pullPolicy }}
 | 
				
			||||||
 | 
					          args:
 | 
				
			||||||
 | 
					            - -wait
 | 
				
			||||||
 | 
					            - tcp://{{ index .Values.configProperties "openwifi.kafka.brokerlist" }}
 | 
				
			||||||
 | 
					            - -timeout
 | 
				
			||||||
 | 
					            - 600s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      containers:
 | 
					      containers:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        - name: owsec
 | 
					        - name: owsec
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
# System
 | 
					# System
 | 
				
			||||||
replicaCount: 1
 | 
					replicaCount: 1
 | 
				
			||||||
strategyType: Recreate
 | 
					strategyType: Recreate
 | 
				
			||||||
 | 
					revisionHistoryLimit: 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
nameOverride: ""
 | 
					nameOverride: ""
 | 
				
			||||||
fullnameOverride: ""
 | 
					fullnameOverride: ""
 | 
				
			||||||
@@ -8,16 +9,20 @@ fullnameOverride: ""
 | 
				
			|||||||
images:
 | 
					images:
 | 
				
			||||||
  owsec:
 | 
					  owsec:
 | 
				
			||||||
    repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owsec
 | 
					    repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owsec
 | 
				
			||||||
    tag: main
 | 
					    tag: v2.5.0
 | 
				
			||||||
    pullPolicy: Always
 | 
					    pullPolicy: Always
 | 
				
			||||||
#    regcred:
 | 
					#    regcred:
 | 
				
			||||||
#      registry: tip-tip-wlan-cloud-ucentral.jfrog.io
 | 
					#      registry: tip-tip-wlan-cloud-ucentral.jfrog.io
 | 
				
			||||||
#      username: username
 | 
					#      username: username
 | 
				
			||||||
#      password: password
 | 
					#      password: password
 | 
				
			||||||
 | 
					  dockerize:
 | 
				
			||||||
 | 
					    repository: tip-tip-wlan-cloud-ucentral.jfrog.io/dockerize
 | 
				
			||||||
 | 
					    tag: 0.16.0
 | 
				
			||||||
 | 
					    pullPolicy: IfNotPresent
 | 
				
			||||||
 | 
					
 | 
				
			||||||
services:
 | 
					services:
 | 
				
			||||||
  owsec:
 | 
					  owsec:
 | 
				
			||||||
    type: LoadBalancer
 | 
					    type: ClusterIP
 | 
				
			||||||
    ports:
 | 
					    ports:
 | 
				
			||||||
      restapi:
 | 
					      restapi:
 | 
				
			||||||
        servicePort: 16001
 | 
					        servicePort: 16001
 | 
				
			||||||
@@ -38,7 +43,6 @@ checks:
 | 
				
			|||||||
      exec:
 | 
					      exec:
 | 
				
			||||||
        command:
 | 
					        command:
 | 
				
			||||||
          - /readiness_check
 | 
					          - /readiness_check
 | 
				
			||||||
      failureThreshold: 1
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
ingresses:
 | 
					ingresses:
 | 
				
			||||||
  restapi:
 | 
					  restapi:
 | 
				
			||||||
@@ -141,11 +145,17 @@ configProperties:
 | 
				
			|||||||
  authentication.default.access: master
 | 
					  authentication.default.access: master
 | 
				
			||||||
  authentication.service.type: internal
 | 
					  authentication.service.type: internal
 | 
				
			||||||
  # Mailer
 | 
					  # Mailer
 | 
				
			||||||
 | 
					  mailer.enabled: "false"
 | 
				
			||||||
  mailer.hostname: smtp.gmail.com
 | 
					  mailer.hostname: smtp.gmail.com
 | 
				
			||||||
  mailer.sender: OpenWIFI
 | 
					  mailer.sender: OpenWIFI
 | 
				
			||||||
  mailer.loginmethod: login
 | 
					  mailer.loginmethod: login
 | 
				
			||||||
  mailer.port: 587
 | 
					  mailer.port: 587
 | 
				
			||||||
  mailer.templates: $OWSEC_ROOT/persist/templates
 | 
					  mailer.templates: $OWSEC_ROOT/persist/templates
 | 
				
			||||||
 | 
					  # SMS
 | 
				
			||||||
 | 
					  smssender.enabled: "false"
 | 
				
			||||||
 | 
					  smssender.provider: "aws"
 | 
				
			||||||
 | 
					  #smssender.aws.region: ""
 | 
				
			||||||
 | 
					  #smssender.twilio.phonenumber: ""
 | 
				
			||||||
  # ALB
 | 
					  # ALB
 | 
				
			||||||
  alb.enable: "true"
 | 
					  alb.enable: "true"
 | 
				
			||||||
  alb.port: 16101
 | 
					  alb.port: 16101
 | 
				
			||||||
@@ -185,22 +195,9 @@ configProperties:
 | 
				
			|||||||
  openwifi.system.uri.ui: https://localhost
 | 
					  openwifi.system.uri.ui: https://localhost
 | 
				
			||||||
  openwifi.system.commandchannel: /tmp/app_owsec
 | 
					  openwifi.system.commandchannel: /tmp/app_owsec
 | 
				
			||||||
  # Logging
 | 
					  # Logging
 | 
				
			||||||
  logging.formatters.f1.class: PatternFormatter
 | 
					  logging.type: console
 | 
				
			||||||
  logging.formatters.f1.pattern: "%Y-%m-%d %H:%M:%S %s: [%p] %t"
 | 
					  logging.path: $OWSEC_ROOT/logs
 | 
				
			||||||
  logging.formatters.f1.times: UTC
 | 
					  logging.level: debug
 | 
				
			||||||
  logging.channels.c1.class: ConsoleChannel
 | 
					 | 
				
			||||||
  logging.channels.c1.formatter: f1
 | 
					 | 
				
			||||||
  logging.channels.c2.class: FileChannel
 | 
					 | 
				
			||||||
  logging.channels.c2.path: /tmp/log_owsec
 | 
					 | 
				
			||||||
  logging.channels.c2.formatter.class: PatternFormatter
 | 
					 | 
				
			||||||
  logging.channels.c2.formatter.pattern: "%Y-%m-%d %H:%M:%S %s: [%p] %t"
 | 
					 | 
				
			||||||
  logging.channels.c2.rotation: "20 M"
 | 
					 | 
				
			||||||
  logging.channels.c2.archive: timestamp
 | 
					 | 
				
			||||||
  logging.channels.c2.purgeCount: 20
 | 
					 | 
				
			||||||
  logging.channels.c3.class: ConsoleChannel
 | 
					 | 
				
			||||||
  logging.channels.c3.pattern: "%s: [%p] %t"
 | 
					 | 
				
			||||||
  logging.loggers.root.channel: c1
 | 
					 | 
				
			||||||
  logging.loggers.root.level: debug
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # -> Secret part
 | 
					  # -> Secret part
 | 
				
			||||||
  # REST API
 | 
					  # REST API
 | 
				
			||||||
@@ -212,6 +209,12 @@ configProperties:
 | 
				
			|||||||
  # Mailer
 | 
					  # Mailer
 | 
				
			||||||
  mailer.username: no-reply@arilia.com
 | 
					  mailer.username: no-reply@arilia.com
 | 
				
			||||||
  mailer.password: "**************************"
 | 
					  mailer.password: "**************************"
 | 
				
			||||||
 | 
					  # SMS
 | 
				
			||||||
 | 
					  #smssender.aws.secretkey: ""
 | 
				
			||||||
 | 
					  #smssender.aws.accesskey: ""
 | 
				
			||||||
 | 
					  #smssender.twilio.sid: ""
 | 
				
			||||||
 | 
					  #smssender.twilio.token: ""
 | 
				
			||||||
 | 
					  #
 | 
				
			||||||
  # Storage
 | 
					  # Storage
 | 
				
			||||||
  ## PostgreSQL
 | 
					  ## PostgreSQL
 | 
				
			||||||
  storage.type.postgresql.username: stephb
 | 
					  storage.type.postgresql.username: stephb
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,7 @@ openapi: 3.0.1
 | 
				
			|||||||
info:
 | 
					info:
 | 
				
			||||||
  title: uCentral Security API
 | 
					  title: uCentral Security API
 | 
				
			||||||
  description: A process to manage security logins.
 | 
					  description: A process to manage security logins.
 | 
				
			||||||
  version: 2.0.0
 | 
					  version: 2.5.0
 | 
				
			||||||
  license:
 | 
					  license:
 | 
				
			||||||
    name: BSD3
 | 
					    name: BSD3
 | 
				
			||||||
    url: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
 | 
					    url: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
 | 
				
			||||||
@@ -61,8 +61,11 @@ components:
 | 
				
			|||||||
                  - 6     # INTERNAL_ERROR,
 | 
					                  - 6     # INTERNAL_ERROR,
 | 
				
			||||||
                  - 7     # ACCESS_DENIED,
 | 
					                  - 7     # ACCESS_DENIED,
 | 
				
			||||||
                  - 8     # INVALID_TOKEN
 | 
					                  - 8     # INVALID_TOKEN
 | 
				
			||||||
                  - 9     # expired token
 | 
					                  - 9     # EXPIRED_TOKEN
 | 
				
			||||||
                  - 10    # rate limit exceeded
 | 
					                  - 10    # RATE_LIMIT_EXCEEDED
 | 
				
			||||||
 | 
					                  - 11    # BAD_MFA_TRANSACTION
 | 
				
			||||||
 | 
					                  - 12    # MFA_FAILURE
 | 
				
			||||||
 | 
					                  - 13    # SECURITY_SERVICE_UNREACHABLE
 | 
				
			||||||
              ErrorDetails:
 | 
					              ErrorDetails:
 | 
				
			||||||
                type: string
 | 
					                type: string
 | 
				
			||||||
              ErrorDescription:
 | 
					              ErrorDescription:
 | 
				
			||||||
@@ -81,8 +84,20 @@ components:
 | 
				
			|||||||
              Code:
 | 
					              Code:
 | 
				
			||||||
                type: integer
 | 
					                type: integer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  schemas:
 | 
					    BadRequest:
 | 
				
			||||||
 | 
					      description: The requested operation failed.
 | 
				
			||||||
 | 
					      content:
 | 
				
			||||||
 | 
					        application/json:
 | 
				
			||||||
 | 
					          schema:
 | 
				
			||||||
 | 
					            properties:
 | 
				
			||||||
 | 
					              ErrorCode:
 | 
				
			||||||
 | 
					                type: integer
 | 
				
			||||||
 | 
					              ErrorDetails:
 | 
				
			||||||
 | 
					                type: string
 | 
				
			||||||
 | 
					              ErrorDescription:
 | 
				
			||||||
 | 
					                type: integer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  schemas:
 | 
				
			||||||
    WebTokenRequest:
 | 
					    WebTokenRequest:
 | 
				
			||||||
      description: User Id and password.
 | 
					      description: User Id and password.
 | 
				
			||||||
      type: object
 | 
					      type: object
 | 
				
			||||||
@@ -228,7 +243,7 @@ components:
 | 
				
			|||||||
          enum:
 | 
					          enum:
 | 
				
			||||||
            - sms
 | 
					            - sms
 | 
				
			||||||
            - email
 | 
					            - email
 | 
				
			||||||
            - voice
 | 
					            - authenticator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    UserLoginLoginExtensions:
 | 
					    UserLoginLoginExtensions:
 | 
				
			||||||
      type: object
 | 
					      type: object
 | 
				
			||||||
@@ -237,6 +252,8 @@ components:
 | 
				
			|||||||
          type: array
 | 
					          type: array
 | 
				
			||||||
          items:
 | 
					          items:
 | 
				
			||||||
            $ref: '#/components/schemas/MobilePhoneNumber'
 | 
					            $ref: '#/components/schemas/MobilePhoneNumber'
 | 
				
			||||||
 | 
					        authenticatorSecret:
 | 
				
			||||||
 | 
					          type: string
 | 
				
			||||||
        mfa:
 | 
					        mfa:
 | 
				
			||||||
          $ref: '#/components/schemas/MfaAuthInfo'
 | 
					          $ref: '#/components/schemas/MfaAuthInfo'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -333,6 +350,9 @@ components:
 | 
				
			|||||||
        securityPolicyChange:
 | 
					        securityPolicyChange:
 | 
				
			||||||
          type: integer
 | 
					          type: integer
 | 
				
			||||||
          format: int64
 | 
					          format: int64
 | 
				
			||||||
 | 
					        modified:
 | 
				
			||||||
 | 
					          type: integer
 | 
				
			||||||
 | 
					          format: int64
 | 
				
			||||||
        userTypeProprietaryInfo:
 | 
					        userTypeProprietaryInfo:
 | 
				
			||||||
          $ref: '#/components/schemas/UserLoginLoginExtensions'
 | 
					          $ref: '#/components/schemas/UserLoginLoginExtensions'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -393,6 +413,24 @@ components:
 | 
				
			|||||||
        answer:
 | 
					        answer:
 | 
				
			||||||
          type: string
 | 
					          type: string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SubMfaConfig:
 | 
				
			||||||
 | 
					      type: object
 | 
				
			||||||
 | 
					      properties:
 | 
				
			||||||
 | 
					        id:
 | 
				
			||||||
 | 
					          type: string
 | 
				
			||||||
 | 
					          format: uuid
 | 
				
			||||||
 | 
					        type:
 | 
				
			||||||
 | 
					          type: string
 | 
				
			||||||
 | 
					          enum:
 | 
				
			||||||
 | 
					            - disabled
 | 
				
			||||||
 | 
					            - sms
 | 
				
			||||||
 | 
					            - email
 | 
				
			||||||
 | 
					        email:
 | 
				
			||||||
 | 
					          type: string
 | 
				
			||||||
 | 
					          format: email
 | 
				
			||||||
 | 
					        sms:
 | 
				
			||||||
 | 
					          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
 | 
				
			||||||
@@ -637,6 +675,22 @@ components:
 | 
				
			|||||||
          items:
 | 
					          items:
 | 
				
			||||||
            $ref: '#/components/schemas/TagValuePair'
 | 
					            $ref: '#/components/schemas/TagValuePair'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Preferences:
 | 
				
			||||||
 | 
					      type: object
 | 
				
			||||||
 | 
					      properties:
 | 
				
			||||||
 | 
					        modified:
 | 
				
			||||||
 | 
					          type: integer
 | 
				
			||||||
 | 
					          format: int64
 | 
				
			||||||
 | 
					        data:
 | 
				
			||||||
 | 
					          type: array
 | 
				
			||||||
 | 
					          items:
 | 
				
			||||||
 | 
					            type: object
 | 
				
			||||||
 | 
					            properties:
 | 
				
			||||||
 | 
					              tag:
 | 
				
			||||||
 | 
					                type: string
 | 
				
			||||||
 | 
					              value:
 | 
				
			||||||
 | 
					                type: string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #########################################################################################
 | 
					    #########################################################################################
 | 
				
			||||||
    ##
 | 
					    ##
 | 
				
			||||||
    ## End of uCentral system wide values
 | 
					    ## End of uCentral system wide values
 | 
				
			||||||
@@ -702,6 +756,64 @@ paths:
 | 
				
			|||||||
        404:
 | 
					        404:
 | 
				
			||||||
          $ref: '#/components/responses/NotFound'
 | 
					          $ref: '#/components/responses/NotFound'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /suboauth2:
 | 
				
			||||||
 | 
					    post:
 | 
				
			||||||
 | 
					      tags:
 | 
				
			||||||
 | 
					        - Authentication
 | 
				
			||||||
 | 
					      summary: Get access token - to be used as Bearer token header for all other API requests.
 | 
				
			||||||
 | 
					      operationId: getSubAccessToken
 | 
				
			||||||
 | 
					      parameters:
 | 
				
			||||||
 | 
					        - in: query
 | 
				
			||||||
 | 
					          name: newPassword
 | 
				
			||||||
 | 
					          description: used when a user is trying to change her password. This will be the new password.
 | 
				
			||||||
 | 
					          schema:
 | 
				
			||||||
 | 
					            type: string
 | 
				
			||||||
 | 
					          required: false
 | 
				
			||||||
 | 
					        - in: query
 | 
				
			||||||
 | 
					          name: forgotPassword
 | 
				
			||||||
 | 
					          description: A user forgot her password. She needs to present her e-mail address in the userId and set this to true
 | 
				
			||||||
 | 
					          schema:
 | 
				
			||||||
 | 
					            type: boolean
 | 
				
			||||||
 | 
					          required: false
 | 
				
			||||||
 | 
					        - in: query
 | 
				
			||||||
 | 
					          name: requirements
 | 
				
			||||||
 | 
					          description: A user forgot her password. She needs to present her e-mail address in the userId and set this to true
 | 
				
			||||||
 | 
					          schema:
 | 
				
			||||||
 | 
					            type: boolean
 | 
				
			||||||
 | 
					          required: false
 | 
				
			||||||
 | 
					        - in: query
 | 
				
			||||||
 | 
					          name: resendMFACode
 | 
				
			||||||
 | 
					          schema:
 | 
				
			||||||
 | 
					            type: boolean
 | 
				
			||||||
 | 
					          required: false
 | 
				
			||||||
 | 
					        - in: query
 | 
				
			||||||
 | 
					          name: completeMFAChallenge
 | 
				
			||||||
 | 
					          schema:
 | 
				
			||||||
 | 
					            type: boolean
 | 
				
			||||||
 | 
					          required: false
 | 
				
			||||||
 | 
					      requestBody:
 | 
				
			||||||
 | 
					        description: User id and password
 | 
				
			||||||
 | 
					        required: true
 | 
				
			||||||
 | 
					        content:
 | 
				
			||||||
 | 
					          application/json:
 | 
				
			||||||
 | 
					            schema:
 | 
				
			||||||
 | 
					              oneOf:
 | 
				
			||||||
 | 
					                - $ref: '#/components/schemas/WebTokenRequest'
 | 
				
			||||||
 | 
					                - $ref: '#/components/schemas/MFAChallengeResponse'
 | 
				
			||||||
 | 
					      responses:
 | 
				
			||||||
 | 
					        200:
 | 
				
			||||||
 | 
					          description: successful operation
 | 
				
			||||||
 | 
					          content:
 | 
				
			||||||
 | 
					            application/json:
 | 
				
			||||||
 | 
					              schema:
 | 
				
			||||||
 | 
					                oneOf:
 | 
				
			||||||
 | 
					                  - $ref: '#/components/schemas/WebTokenResult'
 | 
				
			||||||
 | 
					                  - $ref: '#/components/schemas/MFAChallengeRequest'
 | 
				
			||||||
 | 
					        403:
 | 
				
			||||||
 | 
					          $ref: '#/components/responses/Unauthorized'
 | 
				
			||||||
 | 
					        404:
 | 
				
			||||||
 | 
					          $ref: '#/components/responses/NotFound'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /oauth2/{token}:
 | 
					  /oauth2/{token}:
 | 
				
			||||||
    delete:
 | 
					    delete:
 | 
				
			||||||
      tags:
 | 
					      tags:
 | 
				
			||||||
@@ -727,6 +839,31 @@ paths:
 | 
				
			|||||||
        404:
 | 
					        404:
 | 
				
			||||||
          $ref: '#/components/responses/NotFound'
 | 
					          $ref: '#/components/responses/NotFound'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /suboauth2/{token}:
 | 
				
			||||||
 | 
					    delete:
 | 
				
			||||||
 | 
					      tags:
 | 
				
			||||||
 | 
					        - Authentication
 | 
				
			||||||
 | 
					      summary: Revoke a token.
 | 
				
			||||||
 | 
					      operationId: removeSubAccessToken
 | 
				
			||||||
 | 
					      parameters:
 | 
				
			||||||
 | 
					        - in: path
 | 
				
			||||||
 | 
					          name: token
 | 
				
			||||||
 | 
					          schema:
 | 
				
			||||||
 | 
					            type:
 | 
				
			||||||
 | 
					              string
 | 
				
			||||||
 | 
					          required: true
 | 
				
			||||||
 | 
					      responses:
 | 
				
			||||||
 | 
					        204:
 | 
				
			||||||
 | 
					          description: successful operation
 | 
				
			||||||
 | 
					          content:
 | 
				
			||||||
 | 
					            application/json:
 | 
				
			||||||
 | 
					              schema:
 | 
				
			||||||
 | 
					                $ref: '#/components/responses/Success'
 | 
				
			||||||
 | 
					        403:
 | 
				
			||||||
 | 
					          $ref: '#/components/responses/Unauthorized'
 | 
				
			||||||
 | 
					        404:
 | 
				
			||||||
 | 
					          $ref: '#/components/responses/NotFound'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /systemEndpoints:
 | 
					  /systemEndpoints:
 | 
				
			||||||
    get:
 | 
					    get:
 | 
				
			||||||
      tags:
 | 
					      tags:
 | 
				
			||||||
@@ -791,6 +928,52 @@ paths:
 | 
				
			|||||||
        404:
 | 
					        404:
 | 
				
			||||||
          $ref: '#/components/responses/NotFound'
 | 
					          $ref: '#/components/responses/NotFound'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /subusers:
 | 
				
			||||||
 | 
					    get:
 | 
				
			||||||
 | 
					      tags:
 | 
				
			||||||
 | 
					        - Subscribers
 | 
				
			||||||
 | 
					      summary: Retrieve a list of existing users as well as some information about them.
 | 
				
			||||||
 | 
					      operationId: getSubUsers
 | 
				
			||||||
 | 
					      parameters:
 | 
				
			||||||
 | 
					        - in: query
 | 
				
			||||||
 | 
					          name: offset
 | 
				
			||||||
 | 
					          schema:
 | 
				
			||||||
 | 
					            type: integer
 | 
				
			||||||
 | 
					            format: int64
 | 
				
			||||||
 | 
					          required: false
 | 
				
			||||||
 | 
					        - in: query
 | 
				
			||||||
 | 
					          name: limit
 | 
				
			||||||
 | 
					          schema:
 | 
				
			||||||
 | 
					            type: integer
 | 
				
			||||||
 | 
					            format: int64
 | 
				
			||||||
 | 
					          required: false
 | 
				
			||||||
 | 
					        - in: query
 | 
				
			||||||
 | 
					          description: Selecting this option means the newest record will be returned. Use limit to select how many.
 | 
				
			||||||
 | 
					          name: filter
 | 
				
			||||||
 | 
					          schema:
 | 
				
			||||||
 | 
					            type: string
 | 
				
			||||||
 | 
					          required: false
 | 
				
			||||||
 | 
					        - in: query
 | 
				
			||||||
 | 
					          description: Return only the ids.
 | 
				
			||||||
 | 
					          name: idOnly
 | 
				
			||||||
 | 
					          schema:
 | 
				
			||||||
 | 
					            type: boolean
 | 
				
			||||||
 | 
					          required: false
 | 
				
			||||||
 | 
					        - in: query
 | 
				
			||||||
 | 
					          description: Return only the ids.
 | 
				
			||||||
 | 
					          name: select
 | 
				
			||||||
 | 
					          schema:
 | 
				
			||||||
 | 
					            type: string
 | 
				
			||||||
 | 
					            example: id1,id2,id3,id4,id5
 | 
				
			||||||
 | 
					          required: false
 | 
				
			||||||
 | 
					      responses:
 | 
				
			||||||
 | 
					        200:
 | 
				
			||||||
 | 
					          $ref: '#/components/schemas/UserList'
 | 
				
			||||||
 | 
					        403:
 | 
				
			||||||
 | 
					          $ref: '#/components/responses/Unauthorized'
 | 
				
			||||||
 | 
					        404:
 | 
				
			||||||
 | 
					          $ref: '#/components/responses/NotFound'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /user/{id}:
 | 
					  /user/{id}:
 | 
				
			||||||
    get:
 | 
					    get:
 | 
				
			||||||
      tags:
 | 
					      tags:
 | 
				
			||||||
@@ -895,6 +1078,110 @@ paths:
 | 
				
			|||||||
        404:
 | 
					        404:
 | 
				
			||||||
          $ref: '#/components/responses/NotFound'
 | 
					          $ref: '#/components/responses/NotFound'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /subuser/{id}:
 | 
				
			||||||
 | 
					    get:
 | 
				
			||||||
 | 
					      tags:
 | 
				
			||||||
 | 
					        - Subscribers
 | 
				
			||||||
 | 
					      operationId: getSubUser
 | 
				
			||||||
 | 
					      summary: Retrieve the information for a single user.
 | 
				
			||||||
 | 
					      parameters:
 | 
				
			||||||
 | 
					        - in: path
 | 
				
			||||||
 | 
					          name: id
 | 
				
			||||||
 | 
					          schema:
 | 
				
			||||||
 | 
					            type: string
 | 
				
			||||||
 | 
					            format: uuid
 | 
				
			||||||
 | 
					          required: true
 | 
				
			||||||
 | 
					      responses:
 | 
				
			||||||
 | 
					        200:
 | 
				
			||||||
 | 
					          $ref: '#/components/schemas/UserInfo'
 | 
				
			||||||
 | 
					        403:
 | 
				
			||||||
 | 
					          $ref: '#/components/responses/Unauthorized'
 | 
				
			||||||
 | 
					        404:
 | 
				
			||||||
 | 
					          $ref: '#/components/responses/NotFound'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    delete:
 | 
				
			||||||
 | 
					      tags:
 | 
				
			||||||
 | 
					        - Subscribers
 | 
				
			||||||
 | 
					      operationId: deleteSubUser
 | 
				
			||||||
 | 
					      summary: Delete a single user.
 | 
				
			||||||
 | 
					      parameters:
 | 
				
			||||||
 | 
					        - in: path
 | 
				
			||||||
 | 
					          name: id
 | 
				
			||||||
 | 
					          schema:
 | 
				
			||||||
 | 
					            type: integer
 | 
				
			||||||
 | 
					            format: int64
 | 
				
			||||||
 | 
					          required: true
 | 
				
			||||||
 | 
					      responses:
 | 
				
			||||||
 | 
					        204:
 | 
				
			||||||
 | 
					          $ref: '#/components/responses/Success'
 | 
				
			||||||
 | 
					        403:
 | 
				
			||||||
 | 
					          $ref: '#/components/responses/Unauthorized'
 | 
				
			||||||
 | 
					        404:
 | 
				
			||||||
 | 
					          $ref: '#/components/responses/NotFound'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    post:
 | 
				
			||||||
 | 
					      tags:
 | 
				
			||||||
 | 
					        - Subscribers
 | 
				
			||||||
 | 
					      operationId: createSubUser
 | 
				
			||||||
 | 
					      summary: Create a single user.
 | 
				
			||||||
 | 
					      parameters:
 | 
				
			||||||
 | 
					        - in: path
 | 
				
			||||||
 | 
					          name: id
 | 
				
			||||||
 | 
					          #must be set to 0 for user creation
 | 
				
			||||||
 | 
					          schema:
 | 
				
			||||||
 | 
					            type: integer
 | 
				
			||||||
 | 
					            format: int64
 | 
				
			||||||
 | 
					          required: true
 | 
				
			||||||
 | 
					        - in: query
 | 
				
			||||||
 | 
					          name: email_verification
 | 
				
			||||||
 | 
					          schema:
 | 
				
			||||||
 | 
					            type: boolean
 | 
				
			||||||
 | 
					          required: false
 | 
				
			||||||
 | 
					      requestBody:
 | 
				
			||||||
 | 
					        description: User details (some fields are ignored during creation)
 | 
				
			||||||
 | 
					        content:
 | 
				
			||||||
 | 
					          application/json:
 | 
				
			||||||
 | 
					            schema:
 | 
				
			||||||
 | 
					              $ref: '#/components/schemas/UserInfo'
 | 
				
			||||||
 | 
					      responses:
 | 
				
			||||||
 | 
					        200:
 | 
				
			||||||
 | 
					          $ref: '#/components/schemas/UserInfo'
 | 
				
			||||||
 | 
					        403:
 | 
				
			||||||
 | 
					          $ref: '#/components/responses/Unauthorized'
 | 
				
			||||||
 | 
					        404:
 | 
				
			||||||
 | 
					          $ref: '#/components/responses/NotFound'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    put:
 | 
				
			||||||
 | 
					      tags:
 | 
				
			||||||
 | 
					        - Subscribers
 | 
				
			||||||
 | 
					      operationId: updateSubUser
 | 
				
			||||||
 | 
					      summary: Modify a single user.
 | 
				
			||||||
 | 
					      parameters:
 | 
				
			||||||
 | 
					        - in: path
 | 
				
			||||||
 | 
					          name: id
 | 
				
			||||||
 | 
					          schema:
 | 
				
			||||||
 | 
					            type: integer
 | 
				
			||||||
 | 
					            format: int64
 | 
				
			||||||
 | 
					          required: true
 | 
				
			||||||
 | 
					        - in: query
 | 
				
			||||||
 | 
					          name: email_verification
 | 
				
			||||||
 | 
					          schema:
 | 
				
			||||||
 | 
					            type: boolean
 | 
				
			||||||
 | 
					          required: false
 | 
				
			||||||
 | 
					      requestBody:
 | 
				
			||||||
 | 
					        description: User details (some fields are ignored during update)
 | 
				
			||||||
 | 
					        content:
 | 
				
			||||||
 | 
					          application/json:
 | 
				
			||||||
 | 
					            schema:
 | 
				
			||||||
 | 
					              $ref: '#/components/schemas/UserInfo'
 | 
				
			||||||
 | 
					      responses:
 | 
				
			||||||
 | 
					        200:
 | 
				
			||||||
 | 
					          $ref: '#/components/schemas/UserInfo'
 | 
				
			||||||
 | 
					        403:
 | 
				
			||||||
 | 
					          $ref: '#/components/responses/Unauthorized'
 | 
				
			||||||
 | 
					        404:
 | 
				
			||||||
 | 
					          $ref: '#/components/responses/NotFound'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /avatar/{id}:
 | 
					  /avatar/{id}:
 | 
				
			||||||
    get:
 | 
					    get:
 | 
				
			||||||
      tags:
 | 
					      tags:
 | 
				
			||||||
@@ -1065,6 +1352,138 @@ paths:
 | 
				
			|||||||
                    items:
 | 
					                    items:
 | 
				
			||||||
                      type: string
 | 
					                      type: string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /userPreferences:
 | 
				
			||||||
 | 
					    get:
 | 
				
			||||||
 | 
					      tags:
 | 
				
			||||||
 | 
					        - Preferences
 | 
				
			||||||
 | 
					      operationId: getUserPreferences
 | 
				
			||||||
 | 
					      summary: Get the list of recorded preferences for a user
 | 
				
			||||||
 | 
					      responses:
 | 
				
			||||||
 | 
					        200:
 | 
				
			||||||
 | 
					          $ref: '#/components/schemas/Preferences'
 | 
				
			||||||
 | 
					        400:
 | 
				
			||||||
 | 
					          $ref: '#/components/responses/BadRequest'
 | 
				
			||||||
 | 
					    post:
 | 
				
			||||||
 | 
					      tags:
 | 
				
			||||||
 | 
					        - Preferences
 | 
				
			||||||
 | 
					      operationId: setUserPreferences
 | 
				
			||||||
 | 
					      summary: Set the list of recorded preferences for a user
 | 
				
			||||||
 | 
					      requestBody:
 | 
				
			||||||
 | 
					        description: Setting the list of preferences
 | 
				
			||||||
 | 
					        content:
 | 
				
			||||||
 | 
					          application/json:
 | 
				
			||||||
 | 
					            schema:
 | 
				
			||||||
 | 
					              $ref: '#/components/schemas/Preferences'
 | 
				
			||||||
 | 
					      responses:
 | 
				
			||||||
 | 
					        200:
 | 
				
			||||||
 | 
					          $ref: '#/components/schemas/Preferences'
 | 
				
			||||||
 | 
					        400:
 | 
				
			||||||
 | 
					          $ref: '#/components/responses/BadRequest'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /submfa:
 | 
				
			||||||
 | 
					    get:
 | 
				
			||||||
 | 
					      tags:
 | 
				
			||||||
 | 
					        - MFA
 | 
				
			||||||
 | 
					      summary: Retrieve the cyrrent setting for MFA
 | 
				
			||||||
 | 
					      operationId: getMFS
 | 
				
			||||||
 | 
					      responses:
 | 
				
			||||||
 | 
					        200:
 | 
				
			||||||
 | 
					          $ref: '#/components/schemas/SubMfaConfig'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    put:
 | 
				
			||||||
 | 
					      tags:
 | 
				
			||||||
 | 
					        - MFA
 | 
				
			||||||
 | 
					      summary: Retrieve the cyrrent setting for MFA
 | 
				
			||||||
 | 
					      operationId: modifyMFS
 | 
				
			||||||
 | 
					      parameters:
 | 
				
			||||||
 | 
					        - in: query
 | 
				
			||||||
 | 
					          name: startValidation
 | 
				
			||||||
 | 
					          schema:
 | 
				
			||||||
 | 
					            type: boolean
 | 
				
			||||||
 | 
					          required: false
 | 
				
			||||||
 | 
					        - in: query
 | 
				
			||||||
 | 
					          name: completeValidation
 | 
				
			||||||
 | 
					          schema:
 | 
				
			||||||
 | 
					            type: boolean
 | 
				
			||||||
 | 
					          required: false
 | 
				
			||||||
 | 
					        - in: query
 | 
				
			||||||
 | 
					          name: challengeCode
 | 
				
			||||||
 | 
					          schema:
 | 
				
			||||||
 | 
					            type: string
 | 
				
			||||||
 | 
					          required: false
 | 
				
			||||||
 | 
					      requestBody:
 | 
				
			||||||
 | 
					        content:
 | 
				
			||||||
 | 
					          application/json:
 | 
				
			||||||
 | 
					            schema:
 | 
				
			||||||
 | 
					              $ref: '#/components/schemas/SubMfaConfig'
 | 
				
			||||||
 | 
					      responses:
 | 
				
			||||||
 | 
					        200:
 | 
				
			||||||
 | 
					          $ref: '#/components/schemas/SubMfaConfig'
 | 
				
			||||||
 | 
					        400:
 | 
				
			||||||
 | 
					          $ref: '#/components/responses/BadRequest'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /totp:
 | 
				
			||||||
 | 
					    get:
 | 
				
			||||||
 | 
					      tags:
 | 
				
			||||||
 | 
					        - Security
 | 
				
			||||||
 | 
					      summary: Retrieve the Authenticator QR Code
 | 
				
			||||||
 | 
					      operationId: getTotpQrCode
 | 
				
			||||||
 | 
					      parameters:
 | 
				
			||||||
 | 
					        - in: query
 | 
				
			||||||
 | 
					          name: reset
 | 
				
			||||||
 | 
					          schema:
 | 
				
			||||||
 | 
					            type: boolean
 | 
				
			||||||
 | 
					            default: false
 | 
				
			||||||
 | 
					          required: false
 | 
				
			||||||
 | 
					      responses:
 | 
				
			||||||
 | 
					        200:
 | 
				
			||||||
 | 
					          description: QRCode
 | 
				
			||||||
 | 
					          content:
 | 
				
			||||||
 | 
					            image/svg+xml:
 | 
				
			||||||
 | 
					              schema:
 | 
				
			||||||
 | 
					                type: string
 | 
				
			||||||
 | 
					                format: binary
 | 
				
			||||||
 | 
					        400:
 | 
				
			||||||
 | 
					          $ref: '#/components/responses/BadRequest'
 | 
				
			||||||
 | 
					        403:
 | 
				
			||||||
 | 
					          $ref: '#/components/responses/Unauthorized'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    put:
 | 
				
			||||||
 | 
					      tags:
 | 
				
			||||||
 | 
					        - Security
 | 
				
			||||||
 | 
					      summary: Send the first security code to validate your setup
 | 
				
			||||||
 | 
					      operationId: sendToptTestCode
 | 
				
			||||||
 | 
					      parameters:
 | 
				
			||||||
 | 
					        - in: query
 | 
				
			||||||
 | 
					          name: value
 | 
				
			||||||
 | 
					          schema:
 | 
				
			||||||
 | 
					            type: integer
 | 
				
			||||||
 | 
					            format: int64
 | 
				
			||||||
 | 
					          required: true
 | 
				
			||||||
 | 
					        - in: query
 | 
				
			||||||
 | 
					          name: index
 | 
				
			||||||
 | 
					          schema:
 | 
				
			||||||
 | 
					            type: integer
 | 
				
			||||||
 | 
					            format: int64
 | 
				
			||||||
 | 
					          required: required
 | 
				
			||||||
 | 
					          example: 1,2,3
 | 
				
			||||||
 | 
					      responses:
 | 
				
			||||||
 | 
					        200:
 | 
				
			||||||
 | 
					          description: Succesful posting of response.
 | 
				
			||||||
 | 
					          content:
 | 
				
			||||||
 | 
					            application/json:
 | 
				
			||||||
 | 
					              schema:
 | 
				
			||||||
 | 
					                type: object
 | 
				
			||||||
 | 
					                properties:
 | 
				
			||||||
 | 
					                  nextIndex:
 | 
				
			||||||
 | 
					                    type: integer
 | 
				
			||||||
 | 
					                  moreCodes:
 | 
				
			||||||
 | 
					                    type: boolean
 | 
				
			||||||
 | 
					        400:
 | 
				
			||||||
 | 
					          $ref: '#/components/responses/BadRequest'
 | 
				
			||||||
 | 
					        403:
 | 
				
			||||||
 | 
					          $ref: '#/components/responses/Unauthorized'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  #########################################################################################
 | 
					  #########################################################################################
 | 
				
			||||||
  ##
 | 
					  ##
 | 
				
			||||||
  ## These are endpoints that all services in the uCentral stack must provide
 | 
					  ## These are endpoints that all services in the uCentral stack must provide
 | 
				
			||||||
@@ -1140,6 +1559,27 @@ paths:
 | 
				
			|||||||
        404:
 | 
					        404:
 | 
				
			||||||
          $ref: '#/components/responses/NotFound'
 | 
					          $ref: '#/components/responses/NotFound'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /validateSubToken:
 | 
				
			||||||
 | 
					    get:
 | 
				
			||||||
 | 
					      tags:
 | 
				
			||||||
 | 
					        - Security
 | 
				
			||||||
 | 
					        - Subscribers
 | 
				
			||||||
 | 
					      summary: Allows any microservice to validate a token and get security policy for a specific user.
 | 
				
			||||||
 | 
					      operationId: validateSubToken
 | 
				
			||||||
 | 
					      parameters:
 | 
				
			||||||
 | 
					        - in: query
 | 
				
			||||||
 | 
					          name: token
 | 
				
			||||||
 | 
					          schema:
 | 
				
			||||||
 | 
					            type: string
 | 
				
			||||||
 | 
					          required: true
 | 
				
			||||||
 | 
					      responses:
 | 
				
			||||||
 | 
					        200:
 | 
				
			||||||
 | 
					          $ref: '#/components/schemas/TokenValidationResult'
 | 
				
			||||||
 | 
					        403:
 | 
				
			||||||
 | 
					          $ref: '#/components/responses/Unauthorized'
 | 
				
			||||||
 | 
					        404:
 | 
				
			||||||
 | 
					          $ref: '#/components/responses/NotFound'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /system:
 | 
					  /system:
 | 
				
			||||||
    post:
 | 
					    post:
 | 
				
			||||||
      tags:
 | 
					      tags:
 | 
				
			||||||
@@ -86,6 +86,7 @@ openwifi.document.policy.access = /wwwassets/access_policy.html
 | 
				
			|||||||
openwifi.document.policy.password = /wwwassets/password_policy.html
 | 
					openwifi.document.policy.password = /wwwassets/password_policy.html
 | 
				
			||||||
openwifi.avatar.maxsize = 2000000
 | 
					openwifi.avatar.maxsize = 2000000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					totp.issuer = OpenWiFi
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# This section select which form of persistence you need
 | 
					# 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
 | 
					# Only one selected at a time. If you select multiple, this service will die if a horrible
 | 
				
			||||||
@@ -118,44 +119,12 @@ 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
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
########################################################################
 | 
					########################################################################
 | 
				
			||||||
########################################################################
 | 
					########################################################################
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# Logging: please leave as is for now.
 | 
					# Logging: please leave as is for now.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
########################################################################
 | 
					########################################################################
 | 
				
			||||||
logging.formatters.f1.class = PatternFormatter
 | 
					logging.type = file
 | 
				
			||||||
logging.formatters.f1.pattern = %s: [%p] %t
 | 
					logging.path = $OWSEC_ROOT/logs
 | 
				
			||||||
logging.formatters.f1.times = UTC
 | 
					logging.level = debug
 | 
				
			||||||
logging.channels.c1.class = ConsoleChannel
 | 
					 | 
				
			||||||
logging.channels.c1.formatter = f1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# This is where the logs will be written. This path MUST exist
 | 
					 | 
				
			||||||
logging.channels.c2.class = FileChannel
 | 
					 | 
				
			||||||
logging.channels.c2.path = $OWSEC_ROOT/logs/log
 | 
					 | 
				
			||||||
logging.channels.c2.formatter.class = PatternFormatter
 | 
					 | 
				
			||||||
logging.channels.c2.formatter.pattern = %Y-%m-%d %H:%M:%S %s: [%p] %t
 | 
					 | 
				
			||||||
logging.channels.c2.rotation = 20 M
 | 
					 | 
				
			||||||
logging.channels.c2.archive = timestamp
 | 
					 | 
				
			||||||
logging.channels.c2.purgeCount = 20
 | 
					 | 
				
			||||||
logging.channels.c3.class = ConsoleChannel
 | 
					 | 
				
			||||||
logging.channels.c3.pattern = %s: [%p] %t
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# External Channel
 | 
					 | 
				
			||||||
logging.loggers.root.channel = c2
 | 
					 | 
				
			||||||
logging.loggers.root.level = debug
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Inline Channel with PatternFormatter
 | 
					 | 
				
			||||||
# logging.loggers.l1.name = logger1
 | 
					 | 
				
			||||||
# logging.loggers.l1.channel.class = ConsoleChannel
 | 
					 | 
				
			||||||
# logging.loggers.l1.channel.pattern = %s: [%p] %t
 | 
					 | 
				
			||||||
# logging.loggers.l1.level = information
 | 
					 | 
				
			||||||
# SplitterChannel
 | 
					 | 
				
			||||||
# logging.channels.splitter.class = SplitterChannel
 | 
					 | 
				
			||||||
# logging.channels.splitter.channels = l1,l2
 | 
					 | 
				
			||||||
# logging.loggers.l2.name = logger2
 | 
					 | 
				
			||||||
# logging.loggers.l2.channel = splitter
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@@ -40,9 +40,21 @@ openwifi.system.commandchannel = /tmp/app.ucentralsec
 | 
				
			|||||||
openwifi.service.key = ${SERVICE_KEY}
 | 
					openwifi.service.key = ${SERVICE_KEY}
 | 
				
			||||||
openwifi.service.key.password = ${SERVICE_KEY_PASSWORD}
 | 
					openwifi.service.key.password = ${SERVICE_KEY_PASSWORD}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					smssender.enabled = ${SMSSENDER_ENABLED}
 | 
				
			||||||
 | 
					smssender.provider = ${SMSSENDER_PROVIDER}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					smssender.aws.secretkey = ${SMSSENDER_AWS_SECRETKEY}
 | 
				
			||||||
 | 
					smssender.aws.accesskey = ${SMSSENDER_AWS_ACCESSKEY}
 | 
				
			||||||
 | 
					smssender.aws.region = ${SMSSENDER_AWS_REGION}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					smssender.twilio.sid = ${SMSSENDER_TWILIO_SID}
 | 
				
			||||||
 | 
					smssender.twilio.token = ${SMSSENDER_TWILIO_TOKEN}
 | 
				
			||||||
 | 
					smssender.twilio.phonenumber = ${SMSSENDER_TWILIO_PHONENUMBER}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# Security Microservice Specific Section
 | 
					# Security Microservice Specific Section
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					mailer.enabled = ${MAILER_ENABLED}
 | 
				
			||||||
mailer.hostname = ${MAILER_HOSTNAME}
 | 
					mailer.hostname = ${MAILER_HOSTNAME}
 | 
				
			||||||
mailer.username = ${MAILER_USERNAME}
 | 
					mailer.username = ${MAILER_USERNAME}
 | 
				
			||||||
mailer.password = ${MAILER_PASSWORD}
 | 
					mailer.password = ${MAILER_PASSWORD}
 | 
				
			||||||
@@ -110,37 +122,6 @@ storage.type.mysql.connectiontimeout = 60
 | 
				
			|||||||
# Logging: please leave as is for now.
 | 
					# Logging: please leave as is for now.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
########################################################################
 | 
					########################################################################
 | 
				
			||||||
logging.formatters.f1.class = PatternFormatter
 | 
					logging.type = console
 | 
				
			||||||
logging.formatters.f1.pattern = %Y-%m-%d %H:%M:%S %s: [%p] %t
 | 
					logging.path = $OWSEC_ROOT/logs
 | 
				
			||||||
logging.formatters.f1.times = UTC
 | 
					logging.level = debug
 | 
				
			||||||
logging.channels.c1.class = ConsoleChannel
 | 
					 | 
				
			||||||
logging.channels.c1.formatter = f1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# This is where the logs will be written. This path MUST exist
 | 
					 | 
				
			||||||
logging.channels.c2.class = FileChannel
 | 
					 | 
				
			||||||
logging.channels.c2.path = $OWSEC_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
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,22 +13,23 @@ then
 | 
				
			|||||||
  exit 1
 | 
					  exit 1
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if [[ "${OWSEC_USERNAME}" == "" ]]
 | 
					 | 
				
			||||||
then
 | 
					 | 
				
			||||||
  echo "You must set the variable OWSEC_USERNAME in order to use this script. Something like"
 | 
					 | 
				
			||||||
  echo "OWSEC_USERNAME=tip@ucentral.com"
 | 
					 | 
				
			||||||
  exit 1
 | 
					 | 
				
			||||||
fi
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if [[ "${OWSEC_PASSWORD}" == "" ]]
 | 
					 | 
				
			||||||
then
 | 
					 | 
				
			||||||
  echo "You must set the variable OWSEC_PASSWORD in order to use this script. Something like"
 | 
					 | 
				
			||||||
  echo "OWSEC_PASSWORD=openwifi"
 | 
					 | 
				
			||||||
  exit 1
 | 
					 | 
				
			||||||
fi
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
if [[ "${READINESS_METHOD}" == "systeminfo" ]]
 | 
					if [[ "${READINESS_METHOD}" == "systeminfo" ]]
 | 
				
			||||||
then
 | 
					then
 | 
				
			||||||
 | 
					  if [[ "${OWSEC_USERNAME}" == "" ]]
 | 
				
			||||||
 | 
					  then
 | 
				
			||||||
 | 
					    echo "You must set the variable OWSEC_USERNAME in order to use this script. Something like"
 | 
				
			||||||
 | 
					    echo "OWSEC_USERNAME=tip@ucentral.com"
 | 
				
			||||||
 | 
					    exit 1
 | 
				
			||||||
 | 
					  fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if [[ "${OWSEC_PASSWORD}" == "" ]]
 | 
				
			||||||
 | 
					  then
 | 
				
			||||||
 | 
					    echo "You must set the variable OWSEC_PASSWORD in order to use this script. Something like"
 | 
				
			||||||
 | 
					    echo "OWSEC_PASSWORD=openwifi"
 | 
				
			||||||
 | 
					    exit 1
 | 
				
			||||||
 | 
					  fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  export RESTAPI_PORT=$(grep 'openwifi.restapi.host.0.port' $OWSEC_CONFIG/owsec.properties | awk -F '=' '{print $2}' | xargs | envsubst)
 | 
					  export RESTAPI_PORT=$(grep 'openwifi.restapi.host.0.port' $OWSEC_CONFIG/owsec.properties | awk -F '=' '{print $2}' | xargs | envsubst)
 | 
				
			||||||
  # Get OAuth token from OWSEC and cache it or use cached one
 | 
					  # Get OAuth token from OWSEC and cache it or use cached one
 | 
				
			||||||
  payload="{ \"userId\" : \"$OWSEC_USERNAME\" , \"password\" : \"$OWSEC_PASSWORD\" }"
 | 
					  payload="{ \"userId\" : \"$OWSEC_USERNAME\" , \"password\" : \"$OWSEC_PASSWORD\" }"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,22 +17,61 @@ namespace OpenWifi {
 | 
				
			|||||||
            DELETE,
 | 
					            DELETE,
 | 
				
			||||||
            CREATE
 | 
					            CREATE
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					    1) You cannot delete yourself
 | 
				
			||||||
 | 
					    2) If you are root, you can do anything.
 | 
				
			||||||
 | 
					    3) You can do anything to yourself
 | 
				
			||||||
 | 
					    4) Nobody can touch a root, unless they are a root, unless it is to get information on a ROOT
 | 
				
			||||||
 | 
					    5) Creation rules:
 | 
				
			||||||
 | 
					        ROOT -> create anything
 | 
				
			||||||
 | 
					        PARTNER -> (multi-tenant owner) admin,subs,csr,installer,noc,accounting - matches to an entity in provisioning
 | 
				
			||||||
 | 
					        ADMIN -> admin-subs-csr-installer-noc-accounting
 | 
				
			||||||
 | 
					        ACCOUNTING -> subs-installer-csr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
        static inline bool Can( const SecurityObjects::UserInfo & User, const SecurityObjects::UserInfo & Target, ACL_OPS Op) {
 | 
					        static inline bool Can( const SecurityObjects::UserInfo & User, const SecurityObjects::UserInfo & Target, ACL_OPS Op) {
 | 
				
			||||||
            if(User.Id == Target.Id && Op==DELETE)
 | 
					            //  rule 1
 | 
				
			||||||
 | 
					            if(User.id == Target.id && Op==DELETE)
 | 
				
			||||||
                return false;
 | 
					                return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            //  rule 2
 | 
				
			||||||
            if(User.userRole==SecurityObjects::ROOT)
 | 
					            if(User.userRole==SecurityObjects::ROOT)
 | 
				
			||||||
                return true;
 | 
					                return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(User.Id == Target.Id)
 | 
					            //  rule 3
 | 
				
			||||||
 | 
					            if(User.id == Target.id)
 | 
				
			||||||
                return true;
 | 
					                return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(User.userRole!=SecurityObjects::ADMIN && User.userRole!=SecurityObjects::ROOT && Op!=READ)
 | 
					            //  rule 4
 | 
				
			||||||
                return false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if(Target.userRole==SecurityObjects::ROOT && Op!=READ)
 | 
					            if(Target.userRole==SecurityObjects::ROOT && Op!=READ)
 | 
				
			||||||
                return false;
 | 
					                return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(Op==CREATE) {
 | 
				
			||||||
 | 
					                if(User.userRole==SecurityObjects::ROOT)
 | 
				
			||||||
 | 
					                    return true;
 | 
				
			||||||
 | 
					                if(User.userRole==SecurityObjects::PARTNER && (Target.userRole==SecurityObjects::ADMIN ||
 | 
				
			||||||
 | 
					                    Target.userRole==SecurityObjects::SUBSCRIBER ||
 | 
				
			||||||
 | 
					                    Target.userRole==SecurityObjects::CSR ||
 | 
				
			||||||
 | 
					                    Target.userRole==SecurityObjects::INSTALLER ||
 | 
				
			||||||
 | 
					                    Target.userRole==SecurityObjects::NOC ||
 | 
				
			||||||
 | 
					                    Target.userRole==SecurityObjects::ACCOUNTING))
 | 
				
			||||||
 | 
					                    return true;
 | 
				
			||||||
 | 
					                if(User.userRole==SecurityObjects::ADMIN &&
 | 
				
			||||||
 | 
					                    (Target.userRole==SecurityObjects::ADMIN ||
 | 
				
			||||||
 | 
					                    Target.userRole==SecurityObjects::SUBSCRIBER ||
 | 
				
			||||||
 | 
					                    Target.userRole==SecurityObjects::CSR ||
 | 
				
			||||||
 | 
					                    Target.userRole==SecurityObjects::INSTALLER ||
 | 
				
			||||||
 | 
					                    Target.userRole==SecurityObjects::NOC ||
 | 
				
			||||||
 | 
					                    Target.userRole==SecurityObjects::ACCOUNTING))
 | 
				
			||||||
 | 
					                    return true;
 | 
				
			||||||
 | 
					                if(User.userRole==SecurityObjects::ACCOUNTING &&
 | 
				
			||||||
 | 
					                    (Target.userRole==SecurityObjects::SUBSCRIBER ||
 | 
				
			||||||
 | 
					                    Target.userRole==SecurityObjects::INSTALLER ||
 | 
				
			||||||
 | 
					                    Target.userRole==SecurityObjects::CSR))
 | 
				
			||||||
 | 
					                    return true;
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    private:
 | 
					    private:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,47 +0,0 @@
 | 
				
			|||||||
//
 | 
					 | 
				
			||||||
// Created by stephane bourque on 2021-10-23.
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "framework/MicroService.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "RESTAPI/RESTAPI_oauth2Handler.h"
 | 
					 | 
				
			||||||
#include "RESTAPI/RESTAPI_user_handler.h"
 | 
					 | 
				
			||||||
#include "RESTAPI/RESTAPI_users_handler.h"
 | 
					 | 
				
			||||||
#include "RESTAPI/RESTAPI_action_links.h"
 | 
					 | 
				
			||||||
#include "RESTAPI/RESTAPI_systemEndpoints_handler.h"
 | 
					 | 
				
			||||||
#include "RESTAPI/RESTAPI_AssetServer.h"
 | 
					 | 
				
			||||||
#include "RESTAPI/RESTAPI_avatarHandler.h"
 | 
					 | 
				
			||||||
#include "RESTAPI/RESTAPI_email_handler.h"
 | 
					 | 
				
			||||||
#include "RESTAPI/RESTAPI_sms_handler.h"
 | 
					 | 
				
			||||||
#include "RESTAPI/RESTAPI_validateToken_handler.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace OpenWifi {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Poco::Net::HTTPRequestHandler * RESTAPI_external_server(const char *Path, RESTAPIHandler::BindingMap &Bindings,
 | 
					 | 
				
			||||||
                                                            Poco::Logger & L, RESTAPI_GenericServer & S) {
 | 
					 | 
				
			||||||
        return RESTAPI_Router<
 | 
					 | 
				
			||||||
            RESTAPI_oauth2Handler,
 | 
					 | 
				
			||||||
            RESTAPI_users_handler,
 | 
					 | 
				
			||||||
            RESTAPI_user_handler,
 | 
					 | 
				
			||||||
            RESTAPI_system_command,
 | 
					 | 
				
			||||||
            RESTAPI_AssetServer,
 | 
					 | 
				
			||||||
            RESTAPI_systemEndpoints_handler,
 | 
					 | 
				
			||||||
            RESTAPI_action_links,
 | 
					 | 
				
			||||||
            RESTAPI_avatarHandler,
 | 
					 | 
				
			||||||
            RESTAPI_email_handler,
 | 
					 | 
				
			||||||
            RESTAPI_sms_handler
 | 
					 | 
				
			||||||
        >(Path, Bindings, L, S);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Poco::Net::HTTPRequestHandler * RESTAPI_internal_server(const char *Path, RESTAPIHandler::BindingMap &Bindings,
 | 
					 | 
				
			||||||
                                                            Poco::Logger & L, RESTAPI_GenericServer & S) {
 | 
					 | 
				
			||||||
        return RESTAPI_Router_I<
 | 
					 | 
				
			||||||
            RESTAPI_users_handler,
 | 
					 | 
				
			||||||
            RESTAPI_user_handler,
 | 
					 | 
				
			||||||
            RESTAPI_system_command,
 | 
					 | 
				
			||||||
            RESTAPI_action_links,
 | 
					 | 
				
			||||||
            RESTAPI_validateToken_handler,
 | 
					 | 
				
			||||||
            RESTAPI_sms_handler
 | 
					 | 
				
			||||||
        >(Path, Bindings, L, S);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -32,7 +32,7 @@ namespace OpenWifi {
 | 
				
			|||||||
            std::vector<SecurityObjects::ActionLink>    Links;
 | 
					            std::vector<SecurityObjects::ActionLink>    Links;
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                std::lock_guard G(Mutex_);
 | 
					                std::lock_guard G(Mutex_);
 | 
				
			||||||
                StorageService()->GetActions(Links);
 | 
					                StorageService()->ActionLinksDB().GetActions(Links);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(Links.empty())
 | 
					            if(Links.empty())
 | 
				
			||||||
@@ -43,23 +43,52 @@ namespace OpenWifi {
 | 
				
			|||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                SecurityObjects::UserInfo UInfo;
 | 
					                SecurityObjects::UserInfo UInfo;
 | 
				
			||||||
                if(!StorageService()->GetUserById(i.userId,UInfo)) {
 | 
					                if((i.action==OpenWifi::SecurityObjects::LinkActions::FORGOT_PASSWORD ||
 | 
				
			||||||
                    StorageService()->CancelAction(i.id);
 | 
					                    i.action==OpenWifi::SecurityObjects::LinkActions::VERIFY_EMAIL) && !StorageService()->UserDB().GetUserById(i.userId,UInfo)) {
 | 
				
			||||||
 | 
					                    StorageService()->ActionLinksDB().CancelAction(i.id);
 | 
				
			||||||
 | 
					                    continue;
 | 
				
			||||||
 | 
					                } else if(( i.action==OpenWifi::SecurityObjects::LinkActions::SUB_FORGOT_PASSWORD ||
 | 
				
			||||||
 | 
					                            i.action==OpenWifi::SecurityObjects::LinkActions::SUB_VERIFY_EMAIL) && !StorageService()->SubDB().GetUserById(i.userId,UInfo)) {
 | 
				
			||||||
 | 
					                    StorageService()->ActionLinksDB().CancelAction(i.id);
 | 
				
			||||||
                    continue;
 | 
					                    continue;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if(i.action==OpenWifi::SecurityObjects::LinkActions::FORGOT_PASSWORD) {
 | 
					                switch(i.action) {
 | 
				
			||||||
 | 
					                    case OpenWifi::SecurityObjects::LinkActions::FORGOT_PASSWORD: {
 | 
				
			||||||
                            if(AuthService::SendEmailToUser(i.id, UInfo.email, AuthService::FORGOT_PASSWORD)) {
 | 
					                            if(AuthService::SendEmailToUser(i.id, UInfo.email, AuthService::FORGOT_PASSWORD)) {
 | 
				
			||||||
                        Logger_.information(Poco::format("Send password reset link to %s",UInfo.email));
 | 
					                                Logger().information(Poco::format("Send password reset link to %s",UInfo.email));
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                    StorageService()->SentAction(i.id);
 | 
					                            StorageService()->ActionLinksDB().SentAction(i.id);
 | 
				
			||||||
                } else if (i.action==OpenWifi::SecurityObjects::LinkActions::VERIFY_EMAIL) {
 | 
					                        }
 | 
				
			||||||
 | 
					                        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    case OpenWifi::SecurityObjects::LinkActions::VERIFY_EMAIL: {
 | 
				
			||||||
                            if(AuthService::SendEmailToUser(i.id, UInfo.email, AuthService::EMAIL_VERIFICATION)) {
 | 
					                            if(AuthService::SendEmailToUser(i.id, UInfo.email, AuthService::EMAIL_VERIFICATION)) {
 | 
				
			||||||
                        Logger_.information(Poco::format("Send email verification link to %s",UInfo.email));
 | 
					                                Logger().information(Poco::format("Send email verification link to %s",UInfo.email));
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                            StorageService()->ActionLinksDB().SentAction(i.id);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    case OpenWifi::SecurityObjects::LinkActions::SUB_FORGOT_PASSWORD: {
 | 
				
			||||||
 | 
					                            if(AuthService::SendEmailToSubUser(i.id, UInfo.email, AuthService::FORGOT_PASSWORD)) {
 | 
				
			||||||
 | 
					                                Logger().information(Poco::format("Send subscriber password reset link to %s",UInfo.email));
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                            StorageService()->ActionLinksDB().SentAction(i.id);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    case OpenWifi::SecurityObjects::LinkActions::SUB_VERIFY_EMAIL: {
 | 
				
			||||||
 | 
					                            if(AuthService::SendEmailToSubUser(i.id, UInfo.email, AuthService::EMAIL_VERIFICATION)) {
 | 
				
			||||||
 | 
					                                Logger().information(Poco::format("Send subscriber email verification link to %s",UInfo.email));
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                            StorageService()->ActionLinksDB().SentAction(i.id);
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    default: {
 | 
				
			||||||
 | 
					                        StorageService()->ActionLinksDB().SentAction(i.id);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    StorageService()->SentAction(i.id);
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    StorageService()->SentAction(i.id);
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,11 +12,13 @@ namespace OpenWifi {
 | 
				
			|||||||
    class ActionLinkManager : public SubSystemServer, Poco::Runnable {
 | 
					    class ActionLinkManager : public SubSystemServer, Poco::Runnable {
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        enum Actions {
 | 
					/*        enum Actions {
 | 
				
			||||||
            FORGOT_PASSWORD,
 | 
					            FORGOT_PASSWORD,
 | 
				
			||||||
            VERIFY_EMAIL
 | 
					            VERIFY_EMAIL,
 | 
				
			||||||
 | 
					            SUB_FORGOT_PASSWORD,
 | 
				
			||||||
 | 
					            SUB_VERIFY_EMAIL
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
        static ActionLinkManager * instance() {
 | 
					        static ActionLinkManager * instance() {
 | 
				
			||||||
            static auto * instance_ = new ActionLinkManager;
 | 
					            static auto * instance_ = new ActionLinkManager;
 | 
				
			||||||
            return instance_;
 | 
					            return instance_;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -45,15 +45,23 @@ namespace OpenWifi {
 | 
				
			|||||||
    int AuthService::Start() {
 | 
					    int AuthService::Start() {
 | 
				
			||||||
		Signer_.setRSAKey(MicroService::instance().Key());
 | 
							Signer_.setRSAKey(MicroService::instance().Key());
 | 
				
			||||||
		Signer_.addAllAlgorithms();
 | 
							Signer_.addAllAlgorithms();
 | 
				
			||||||
		Logger_.notice("Starting...");
 | 
							Logger().notice("Starting...");
 | 
				
			||||||
        PasswordValidation_ = PasswordValidationStr_ = MicroService::instance().ConfigGetString("authentication.validation.expression","^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$");
 | 
					 | 
				
			||||||
        TokenAging_ = (uint64_t) MicroService::instance().ConfigGetInt("authentication.token.ageing", 30 * 24 * 60 * 60);
 | 
					        TokenAging_ = (uint64_t) MicroService::instance().ConfigGetInt("authentication.token.ageing", 30 * 24 * 60 * 60);
 | 
				
			||||||
        HowManyOldPassword_ = MicroService::instance().ConfigGetInt("authentication.oldpasswords", 5);
 | 
					        HowManyOldPassword_ = MicroService::instance().ConfigGetInt("authentication.oldpasswords", 5);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        AccessPolicy_ = MicroService::instance().ConfigPath("openwifi.document.policy.access", "/wwwassets/access_policy.html");
 | 
				
			||||||
 | 
					        PasswordPolicy_ = MicroService::instance().ConfigPath("openwifi.document.policy.password", "/wwwassets/password_policy.html");
 | 
				
			||||||
 | 
					        PasswordValidation_ = PasswordValidationStr_ = MicroService::instance().ConfigGetString("authentication.validation.expression","^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        SubPasswordValidation_ = SubPasswordValidationStr_ = MicroService::instance().ConfigGetString("subscriber.validation.expression","^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$");
 | 
				
			||||||
 | 
					        SubAccessPolicy_ = MicroService::instance().ConfigPath("subscriber.policy.access", "/wwwassets/access_policy.html");
 | 
				
			||||||
 | 
					        SubPasswordPolicy_ = MicroService::instance().ConfigPath("subscriber.policy.password", "/wwwassets/password_policy.html");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void AuthService::Stop() {
 | 
					    void AuthService::Stop() {
 | 
				
			||||||
		Logger_.notice("Stopping...");
 | 
							Logger().notice("Stopping...");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool AuthService::IsAuthorized(Poco::Net::HTTPServerRequest & Request, std::string & SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired )
 | 
						bool AuthService::IsAuthorized(Poco::Net::HTTPServerRequest & Request, std::string & SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired )
 | 
				
			||||||
@@ -67,84 +75,132 @@ namespace OpenWifi {
 | 
				
			|||||||
		        CallToken = Auth.getBearerToken();
 | 
							        CallToken = Auth.getBearerToken();
 | 
				
			||||||
		    }
 | 
							    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		    if(!CallToken.empty()) {
 | 
					            if(CallToken.empty()) {
 | 
				
			||||||
		        auto Client = UserCache_.get(CallToken);
 | 
					                return false;
 | 
				
			||||||
		        if( Client.isNull() ) {
 | 
					            }
 | 
				
			||||||
		            SecurityObjects::UserInfoAndPolicy UInfo2;
 | 
					
 | 
				
			||||||
 | 
					            SecurityObjects::WebToken   WT;
 | 
				
			||||||
            uint64_t                    RevocationDate=0;
 | 
					            uint64_t                    RevocationDate=0;
 | 
				
			||||||
		            if(StorageService()->GetToken(CallToken,UInfo2,RevocationDate)) {
 | 
					            std::string                 UserId;
 | 
				
			||||||
 | 
					            if(StorageService()->UserTokenDB().GetToken(CallToken, WT, UserId, RevocationDate)) {
 | 
				
			||||||
                if(RevocationDate!=0)
 | 
					                if(RevocationDate!=0)
 | 
				
			||||||
                    return false;
 | 
					                    return false;
 | 
				
			||||||
		                Expired = (UInfo2.webtoken.created_ + UInfo2.webtoken.expires_in_) < time(nullptr);
 | 
					                Expired = (WT.created_ + WT.expires_in_) < time(nullptr);
 | 
				
			||||||
		                if(StorageService()->GetUserById(UInfo2.userinfo.Id,UInfo.userinfo)) {
 | 
					                if(StorageService()->UserDB().GetUserById(UserId,UInfo.userinfo)) {
 | 
				
			||||||
		                    UInfo.webtoken = UInfo2.webtoken;
 | 
					                    UInfo.webtoken = WT;
 | 
				
			||||||
		                    UserCache_.update(CallToken, UInfo);
 | 
					 | 
				
			||||||
                    SessionToken = CallToken;
 | 
					                    SessionToken = CallToken;
 | 
				
			||||||
                    return true;
 | 
					                    return true;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
		        }
 | 
					 | 
				
			||||||
		        if(!Expired) {
 | 
					 | 
				
			||||||
		            SessionToken = CallToken;
 | 
					 | 
				
			||||||
		            UInfo = *Client ;
 | 
					 | 
				
			||||||
		            return true;
 | 
					 | 
				
			||||||
		        }
 | 
					 | 
				
			||||||
                RevokeToken(CallToken);
 | 
					 | 
				
			||||||
		        return false;
 | 
					 | 
				
			||||||
		    }
 | 
					 | 
				
			||||||
		} catch(const Poco::Exception &E) {
 | 
							} catch(const Poco::Exception &E) {
 | 
				
			||||||
		    Logger_.log(E);
 | 
							    Logger().log(E);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool AuthService::IsSubAuthorized(Poco::Net::HTTPServerRequest & Request, std::string & SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::lock_guard	Guard(Mutex_);
 | 
				
			||||||
 | 
					        Expired = false;
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            std::string CallToken;
 | 
				
			||||||
 | 
					            Poco::Net::OAuth20Credentials Auth(Request);
 | 
				
			||||||
 | 
					            if (Auth.getScheme() == "Bearer") {
 | 
				
			||||||
 | 
					                CallToken = Auth.getBearerToken();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(CallToken.empty()) {
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            SecurityObjects::WebToken   WT;
 | 
				
			||||||
 | 
					            uint64_t                    RevocationDate=0;
 | 
				
			||||||
 | 
					            std::string                 UserId;
 | 
				
			||||||
 | 
					            if(StorageService()->SubTokenDB().GetToken(CallToken, WT, UserId, RevocationDate)) {
 | 
				
			||||||
 | 
					                if(RevocationDate!=0)
 | 
				
			||||||
 | 
					                    return false;
 | 
				
			||||||
 | 
					                Expired = (WT.created_ + WT.expires_in_) < time(nullptr);
 | 
				
			||||||
 | 
					                if(StorageService()->SubDB().GetUserById(UserId,UInfo.userinfo)) {
 | 
				
			||||||
 | 
					                    UInfo.webtoken = WT;
 | 
				
			||||||
 | 
					                    SessionToken = CallToken;
 | 
				
			||||||
 | 
					                    return true;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        } catch(const Poco::Exception &E) {
 | 
				
			||||||
 | 
					            Logger().log(E);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void AuthService::RevokeToken(std::string & Token) {
 | 
					    void AuthService::RevokeToken(std::string & Token) {
 | 
				
			||||||
        UserCache_.remove(Token);
 | 
					        StorageService()->UserTokenDB().RevokeToken(Token);
 | 
				
			||||||
        StorageService()->RevokeToken(Token);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool AuthService::DeleteUserFromCache(const std::string &UserName) {
 | 
					    void AuthService::RevokeSubToken(std::string & Token) {
 | 
				
			||||||
        std::lock_guard		Guard(Mutex_);
 | 
					        StorageService()->SubTokenDB().RevokeToken(Token);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        std::vector<std::string>    OldTokens;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        UserCache_.forEach([&OldTokens,UserName](const std::string &token, const SecurityObjects::UserInfoAndPolicy& O) -> void
 | 
					 | 
				
			||||||
        { if(O.userinfo.email==UserName)
 | 
					 | 
				
			||||||
            OldTokens.push_back(token);
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for(const auto &i:OldTokens) {
 | 
					 | 
				
			||||||
            Logout(i,false);
 | 
					 | 
				
			||||||
            UserCache_.remove(i);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
        return true;
 | 
					
 | 
				
			||||||
 | 
					    bool AuthService::DeleteUserFromCache(const std::string &Id) {
 | 
				
			||||||
 | 
					        return StorageService()->UserTokenDB().DeleteRecordsFromCache("userName",Id);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool AuthService::DeleteSubUserFromCache(const std::string &Id) {
 | 
				
			||||||
 | 
					        return StorageService()->SubTokenDB().DeleteRecordsFromCache("userName",Id);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool AuthService::RequiresMFA(const SecurityObjects::UserInfoAndPolicy &UInfo) {
 | 
					    bool AuthService::RequiresMFA(const SecurityObjects::UserInfoAndPolicy &UInfo) {
 | 
				
			||||||
        return (UInfo.userinfo.userTypeProprietaryInfo.mfa.enabled && MFAServer().MethodEnabled(UInfo.userinfo.userTypeProprietaryInfo.mfa.method));
 | 
					        return (UInfo.userinfo.userTypeProprietaryInfo.mfa.enabled && MFAServer::MethodEnabled(UInfo.userinfo.userTypeProprietaryInfo.mfa.method));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    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, bool EraseFromCache) {
 | 
					    bool AuthService::ValidateSubPassword(const std::string &Password) {
 | 
				
			||||||
		std::lock_guard		Guard(Mutex_);
 | 
					        return std::regex_match(Password, SubPasswordValidation_);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void AuthService::RemoveTokenSystemWide(const std::string &token) {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
 | 
					            if(KafkaManager()->Enabled()) {
 | 
				
			||||||
                Poco::JSON::Object Obj;
 | 
					                Poco::JSON::Object Obj;
 | 
				
			||||||
                Obj.set("event", "remove-token");
 | 
					                Obj.set("event", "remove-token");
 | 
				
			||||||
                Obj.set("id", MicroService::instance().ID());
 | 
					                Obj.set("id", MicroService::instance().ID());
 | 
				
			||||||
                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};
 | 
					                KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS, MicroService::instance().PrivateEndPoint(),
 | 
				
			||||||
            RevokeToken(Tmp);
 | 
					                                            ResultText.str(),
 | 
				
			||||||
            KafkaManager()->PostMessage(KafkaTopics::SERVICE_EVENTS, MicroService::instance().PrivateEndPoint(), ResultText.str(),
 | 
					 | 
				
			||||||
                                            false);
 | 
					                                            false);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        } catch (const Poco::Exception &E) {
 | 
					        } catch (const Poco::Exception &E) {
 | 
				
			||||||
            Logger_.log(E);
 | 
					            Logger().log(E);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void AuthService::Logout(const std::string &Token, bool EraseFromCache) {
 | 
				
			||||||
 | 
							std::lock_guard		Guard(Mutex_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            auto tToken{Token};
 | 
				
			||||||
 | 
					            StorageService()->UserTokenDB().DeleteRecord("token",tToken);
 | 
				
			||||||
 | 
					            StorageService()->LoginDB().AddLogout(Token);
 | 
				
			||||||
 | 
					        } catch (const Poco::Exception &E) {
 | 
				
			||||||
 | 
					            Logger().log(E);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void AuthService::SubLogout(const std::string &Token, bool EraseFromCache) {
 | 
				
			||||||
 | 
					        std::lock_guard		Guard(Mutex_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            auto tToken{Token};
 | 
				
			||||||
 | 
					            StorageService()->SubTokenDB().DeleteRecord("token",tToken);
 | 
				
			||||||
 | 
					            StorageService()->SubLoginDB().AddLogout(Token);
 | 
				
			||||||
 | 
					        } catch (const Poco::Exception &E) {
 | 
				
			||||||
 | 
					            Logger().log(E);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -184,18 +240,42 @@ namespace OpenWifi {
 | 
				
			|||||||
        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_ = GenerateTokenHMAC(UInfo.userinfo.Id,USERNAME);
 | 
					        UInfo.webtoken.access_token_ = GenerateTokenHMAC(UInfo.userinfo.id,USERNAME);
 | 
				
			||||||
        UInfo.webtoken.id_token_ = GenerateTokenHMAC(UInfo.userinfo.Id,USERNAME);
 | 
					        UInfo.webtoken.id_token_ = GenerateTokenHMAC(UInfo.userinfo.id,USERNAME);
 | 
				
			||||||
        UInfo.webtoken.refresh_token_ = GenerateTokenHMAC(UInfo.userinfo.Id,CUSTOM);
 | 
					        UInfo.webtoken.refresh_token_ = GenerateTokenHMAC(UInfo.userinfo.id,CUSTOM);
 | 
				
			||||||
        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_.update(UInfo.webtoken.access_token_,UInfo);
 | 
					        StorageService()->UserDB().SetLastLogin(UInfo.userinfo.id);
 | 
				
			||||||
        StorageService()->SetLastLogin(UInfo.userinfo.Id);
 | 
					        StorageService()->UserTokenDB().AddToken(UInfo.userinfo.id, UInfo.webtoken.access_token_,
 | 
				
			||||||
        StorageService()->AddToken(UInfo.userinfo.Id, UInfo.webtoken.access_token_,
 | 
					 | 
				
			||||||
                            UInfo.webtoken.refresh_token_, UInfo.webtoken.token_type_,
 | 
					                            UInfo.webtoken.refresh_token_, UInfo.webtoken.token_type_,
 | 
				
			||||||
                                UInfo.webtoken.expires_in_, UInfo.webtoken.idle_timeout_);
 | 
					                                UInfo.webtoken.expires_in_, UInfo.webtoken.idle_timeout_);
 | 
				
			||||||
 | 
					        StorageService()->LoginDB().AddLogin(UInfo.userinfo.id, UInfo.userinfo.email,UInfo.webtoken.access_token_ );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void AuthService::CreateSubToken(const std::string & UserName, SecurityObjects::UserInfoAndPolicy &UInfo)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::lock_guard		Guard(Mutex_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        SecurityObjects::AclTemplate	ACL;
 | 
				
			||||||
 | 
					        ACL.PortalLogin_ = ACL.Read_ = ACL.ReadWrite_ = ACL.ReadWriteCreate_ = ACL.Delete_ = true;
 | 
				
			||||||
 | 
					        UInfo.webtoken.acl_template_ = ACL;
 | 
				
			||||||
 | 
					        UInfo.webtoken.expires_in_ = TokenAging_ ;
 | 
				
			||||||
 | 
					        UInfo.webtoken.idle_timeout_ = 5 * 60;
 | 
				
			||||||
 | 
					        UInfo.webtoken.token_type_ = "Bearer";
 | 
				
			||||||
 | 
					        UInfo.webtoken.access_token_ = GenerateTokenHMAC(UInfo.userinfo.id,USERNAME);
 | 
				
			||||||
 | 
					        UInfo.webtoken.id_token_ = GenerateTokenHMAC(UInfo.userinfo.id,USERNAME);
 | 
				
			||||||
 | 
					        UInfo.webtoken.refresh_token_ = GenerateTokenHMAC(UInfo.userinfo.id,CUSTOM);
 | 
				
			||||||
 | 
					        UInfo.webtoken.created_ = time(nullptr);
 | 
				
			||||||
 | 
					        UInfo.webtoken.username_ = UserName;
 | 
				
			||||||
 | 
					        UInfo.webtoken.errorCode = 0;
 | 
				
			||||||
 | 
					        UInfo.webtoken.userMustChangePassword = false;
 | 
				
			||||||
 | 
					        StorageService()->SubDB().SetLastLogin(UInfo.userinfo.id);
 | 
				
			||||||
 | 
					        StorageService()->SubTokenDB().AddToken(UInfo.userinfo.id, UInfo.webtoken.access_token_,
 | 
				
			||||||
 | 
					                                   UInfo.webtoken.refresh_token_, UInfo.webtoken.token_type_,
 | 
				
			||||||
 | 
					                                   UInfo.webtoken.expires_in_, UInfo.webtoken.idle_timeout_);
 | 
				
			||||||
 | 
					        StorageService()->SubLoginDB().AddLogin(UInfo.userinfo.id, UInfo.userinfo.email,UInfo.webtoken.access_token_ );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool AuthService::SetPassword(const std::string &NewPassword, SecurityObjects::UserInfo & UInfo) {
 | 
					    bool AuthService::SetPassword(const std::string &NewPassword, SecurityObjects::UserInfo & UInfo) {
 | 
				
			||||||
@@ -232,6 +312,40 @@ namespace OpenWifi {
 | 
				
			|||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool AuthService::SetSubPassword(const std::string &NewPassword, SecurityObjects::UserInfo & UInfo) {
 | 
				
			||||||
 | 
					        std::lock_guard     G(Mutex_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Poco::toLowerInPlace(UInfo.email);
 | 
				
			||||||
 | 
					        for (const auto &i:UInfo.lastPasswords) {
 | 
				
			||||||
 | 
					            auto Tokens = Poco::StringTokenizer(i,"|");
 | 
				
			||||||
 | 
					            if(Tokens.count()==2) {
 | 
				
			||||||
 | 
					                const auto & Salt = Tokens[0];
 | 
				
			||||||
 | 
					                for(const auto &j:UInfo.lastPasswords) {
 | 
				
			||||||
 | 
					                    auto OldTokens = Poco::StringTokenizer(j,"|");
 | 
				
			||||||
 | 
					                    if(OldTokens.count()==2) {
 | 
				
			||||||
 | 
					                        SHA2_.update(Salt+NewPassword+UInfo.email);
 | 
				
			||||||
 | 
					                        if(OldTokens[1]==Utils::ToHex(SHA2_.digest()))
 | 
				
			||||||
 | 
					                            return false;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                SHA2_.update(NewPassword+UInfo.email);
 | 
				
			||||||
 | 
					                if(Tokens[0]==Utils::ToHex(SHA2_.digest()))
 | 
				
			||||||
 | 
					                    return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(UInfo.lastPasswords.size()==HowManyOldPassword_) {
 | 
				
			||||||
 | 
					            UInfo.lastPasswords.erase(UInfo.lastPasswords.begin());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        auto NewHash = ComputeNewPasswordHash(UInfo.email,NewPassword);
 | 
				
			||||||
 | 
					        UInfo.lastPasswords.push_back(NewHash);
 | 
				
			||||||
 | 
					        UInfo.currentPassword = NewHash;
 | 
				
			||||||
 | 
					        UInfo.changePassword = false;
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static std::string GetMeSomeSalt() {
 | 
					    static std::string GetMeSomeSalt() {
 | 
				
			||||||
        auto start = std::chrono::high_resolution_clock::now();
 | 
					        auto start = std::chrono::high_resolution_clock::now();
 | 
				
			||||||
        return std::to_string(start.time_since_epoch().count());
 | 
					        return std::to_string(start.time_since_epoch().count());
 | 
				
			||||||
@@ -261,13 +375,30 @@ namespace OpenWifi {
 | 
				
			|||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool AuthService::ValidateSubPasswordHash(const std::string & UserName, const std::string & Password, const std::string &StoredPassword) {
 | 
				
			||||||
 | 
					        std::lock_guard G(Mutex_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::string UName = Poco::trim(Poco::toLower(UserName));
 | 
				
			||||||
 | 
					        auto Tokens = Poco::StringTokenizer(StoredPassword,"|");
 | 
				
			||||||
 | 
					        if(Tokens.count()==1) {
 | 
				
			||||||
 | 
					            SHA2_.update(Password+UName);
 | 
				
			||||||
 | 
					            if(Tokens[0]==Utils::ToHex(SHA2_.digest()))
 | 
				
			||||||
 | 
					                return true;
 | 
				
			||||||
 | 
					        } else if (Tokens.count()==2) {
 | 
				
			||||||
 | 
					            SHA2_.update(Tokens[0]+Password+UName);
 | 
				
			||||||
 | 
					            if(Tokens[1]==Utils::ToHex(SHA2_.digest()))
 | 
				
			||||||
 | 
					                return true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    UNAUTHORIZED_REASON AuthService::Authorize( std::string & UserName, const std::string & Password, const std::string & NewPassword, SecurityObjects::UserInfoAndPolicy & UInfo , bool & Expired )
 | 
					    UNAUTHORIZED_REASON AuthService::Authorize( std::string & UserName, const std::string & Password, const std::string & NewPassword, SecurityObjects::UserInfoAndPolicy & UInfo , bool & Expired )
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        std::lock_guard		Guard(Mutex_);
 | 
					        std::lock_guard		Guard(Mutex_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Poco::toLowerInPlace(UserName);
 | 
					        Poco::toLowerInPlace(UserName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(StorageService()->GetUserByEmail(UserName,UInfo.userinfo)) {
 | 
					        if(StorageService()->UserDB().GetUserByEmail(UserName,UInfo.userinfo)) {
 | 
				
			||||||
            if(UInfo.userinfo.waitingForEmailCheck) {
 | 
					            if(UInfo.userinfo.waitingForEmailCheck) {
 | 
				
			||||||
                return USERNAME_PENDING_VERIFICATION;
 | 
					                return USERNAME_PENDING_VERIFICATION;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -292,12 +423,13 @@ namespace OpenWifi {
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
                UInfo.userinfo.lastPasswordChange = std::time(nullptr);
 | 
					                UInfo.userinfo.lastPasswordChange = std::time(nullptr);
 | 
				
			||||||
                UInfo.userinfo.changePassword = false;
 | 
					                UInfo.userinfo.changePassword = false;
 | 
				
			||||||
                StorageService()->UpdateUserInfo(AUTHENTICATION_SYSTEM, UInfo.userinfo.Id,UInfo.userinfo);
 | 
					                UInfo.userinfo.modified = std::time(nullptr);
 | 
				
			||||||
 | 
					                StorageService()->UserDB().UpdateUserInfo(AUTHENTICATION_SYSTEM, UInfo.userinfo.id,UInfo.userinfo);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            //  so we have a good password, password up date has taken place if need be, now generate the token.
 | 
					            //  so we have a good password, password up date has taken place if need be, now generate the token.
 | 
				
			||||||
            UInfo.userinfo.lastLogin=std::time(nullptr);
 | 
					            UInfo.userinfo.lastLogin=std::time(nullptr);
 | 
				
			||||||
            StorageService()->SetLastLogin(UInfo.userinfo.Id);
 | 
					            StorageService()->UserDB().SetLastLogin(UInfo.userinfo.id);
 | 
				
			||||||
            CreateToken(UserName, UInfo );
 | 
					            CreateToken(UserName, UInfo );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return SUCCESS;
 | 
					            return SUCCESS;
 | 
				
			||||||
@@ -306,10 +438,91 @@ namespace OpenWifi {
 | 
				
			|||||||
        return INVALID_CREDENTIALS;
 | 
					        return INVALID_CREDENTIALS;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    UNAUTHORIZED_REASON AuthService::AuthorizeSub( std::string & UserName, const std::string & Password, const std::string & NewPassword, SecurityObjects::UserInfoAndPolicy & UInfo , bool & Expired )
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        std::lock_guard		Guard(Mutex_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Poco::toLowerInPlace(UserName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(StorageService()->SubDB().GetUserByEmail(UserName,UInfo.userinfo)) {
 | 
				
			||||||
 | 
					            if(UInfo.userinfo.waitingForEmailCheck) {
 | 
				
			||||||
 | 
					                return USERNAME_PENDING_VERIFICATION;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(!ValidateSubPasswordHash(UserName,Password,UInfo.userinfo.currentPassword)) {
 | 
				
			||||||
 | 
					                return INVALID_CREDENTIALS;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(UInfo.userinfo.changePassword && NewPassword.empty()) {
 | 
				
			||||||
 | 
					                UInfo.webtoken.userMustChangePassword = true ;
 | 
				
			||||||
 | 
					                return PASSWORD_CHANGE_REQUIRED;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(!NewPassword.empty() && !ValidateSubPassword(NewPassword)) {
 | 
				
			||||||
 | 
					                return PASSWORD_INVALID;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(UInfo.userinfo.changePassword || !NewPassword.empty()) {
 | 
				
			||||||
 | 
					                if(!SetSubPassword(NewPassword,UInfo.userinfo)) {
 | 
				
			||||||
 | 
					                    UInfo.webtoken.errorCode = 1;
 | 
				
			||||||
 | 
					                    return PASSWORD_ALREADY_USED;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                UInfo.userinfo.lastPasswordChange = std::time(nullptr);
 | 
				
			||||||
 | 
					                UInfo.userinfo.changePassword = false;
 | 
				
			||||||
 | 
					                UInfo.userinfo.modified = std::time(nullptr);
 | 
				
			||||||
 | 
					                StorageService()->SubDB().UpdateUserInfo(AUTHENTICATION_SYSTEM, UInfo.userinfo.id,UInfo.userinfo);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            //  so we have a good password, password up date has taken place if need be, now generate the token.
 | 
				
			||||||
 | 
					            UInfo.userinfo.lastLogin=std::time(nullptr);
 | 
				
			||||||
 | 
					            StorageService()->SubDB().SetLastLogin(UInfo.userinfo.id);
 | 
				
			||||||
 | 
					            CreateSubToken(UserName, UInfo );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return SUCCESS;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return INVALID_CREDENTIALS;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool AuthService::SendEmailToUser(const std::string &LinkId, std::string &Email, EMAIL_REASON Reason) {
 | 
					    bool AuthService::SendEmailToUser(const std::string &LinkId, std::string &Email, EMAIL_REASON Reason) {
 | 
				
			||||||
        SecurityObjects::UserInfo   UInfo;
 | 
					        SecurityObjects::UserInfo   UInfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(StorageService()->GetUserByEmail(Email,UInfo)) {
 | 
					        if(StorageService()->UserDB().GetUserByEmail(Email,UInfo)) {
 | 
				
			||||||
 | 
					            switch (Reason) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                case FORGOT_PASSWORD: {
 | 
				
			||||||
 | 
					                        MessageAttributes Attrs;
 | 
				
			||||||
 | 
					                        Attrs[RECIPIENT_EMAIL] = UInfo.email;
 | 
				
			||||||
 | 
					                        Attrs[LOGO] = GetLogoAssetURI();
 | 
				
			||||||
 | 
					                        Attrs[SUBJECT] = "Password reset link";
 | 
				
			||||||
 | 
					                        Attrs[ACTION_LINK] = MicroService::instance().GetPublicAPIEndPoint() + "/actionLink?action=password_reset&id=" + LinkId ;
 | 
				
			||||||
 | 
					                        SMTPMailerService()->SendMessage(UInfo.email, "password_reset.txt", Attrs);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                case EMAIL_VERIFICATION: {
 | 
				
			||||||
 | 
					                        MessageAttributes Attrs;
 | 
				
			||||||
 | 
					                        Attrs[RECIPIENT_EMAIL] = UInfo.email;
 | 
				
			||||||
 | 
					                        Attrs[LOGO] = GetLogoAssetURI();
 | 
				
			||||||
 | 
					                        Attrs[SUBJECT] = "EMail Address Verification";
 | 
				
			||||||
 | 
					                        Attrs[ACTION_LINK] = MicroService::instance().GetPublicAPIEndPoint() + "/actionLink?action=email_verification&id=" + LinkId ;
 | 
				
			||||||
 | 
					                        SMTPMailerService()->SendMessage(UInfo.email, "email_verification.txt", Attrs);
 | 
				
			||||||
 | 
					                        UInfo.waitingForEmailCheck = true;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                default:
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool AuthService::SendEmailToSubUser(const std::string &LinkId, std::string &Email, EMAIL_REASON Reason) {
 | 
				
			||||||
 | 
					        SecurityObjects::UserInfo   UInfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(StorageService()->SubDB().GetUserByEmail(Email,UInfo)) {
 | 
				
			||||||
            switch (Reason) {
 | 
					            switch (Reason) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case FORGOT_PASSWORD: {
 | 
					                case FORGOT_PASSWORD: {
 | 
				
			||||||
@@ -349,44 +562,65 @@ namespace OpenWifi {
 | 
				
			|||||||
        A.id = MicroService::CreateUUID();
 | 
					        A.id = MicroService::CreateUUID();
 | 
				
			||||||
        A.created = std::time(nullptr);
 | 
					        A.created = std::time(nullptr);
 | 
				
			||||||
        A.expires = A.created + 24*60*60;
 | 
					        A.expires = A.created + 24*60*60;
 | 
				
			||||||
        StorageService()->CreateAction(A);
 | 
					        A.userAction = true;
 | 
				
			||||||
 | 
					        StorageService()->ActionLinksDB().CreateAction(A);
 | 
				
			||||||
 | 
					        UInfo.waitingForEmailCheck = true;
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool AuthService::VerifySubEmail(SecurityObjects::UserInfo &UInfo) {
 | 
				
			||||||
 | 
					        SecurityObjects::ActionLink A;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        A.action = OpenWifi::SecurityObjects::LinkActions::SUB_VERIFY_EMAIL;
 | 
				
			||||||
 | 
					        A.userId = UInfo.email;
 | 
				
			||||||
 | 
					        A.id = MicroService::CreateUUID();
 | 
				
			||||||
 | 
					        A.created = std::time(nullptr);
 | 
				
			||||||
 | 
					        A.expires = A.created + 24*60*60;
 | 
				
			||||||
 | 
					        A.userAction = false;
 | 
				
			||||||
 | 
					        StorageService()->ActionLinksDB().CreateAction(A);
 | 
				
			||||||
        UInfo.waitingForEmailCheck = true;
 | 
					        UInfo.waitingForEmailCheck = true;
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool AuthService::IsValidToken(const std::string &Token, SecurityObjects::WebToken &WebToken, SecurityObjects::UserInfo &UserInfo, bool & Expired) {
 | 
					    bool AuthService::IsValidToken(const std::string &Token, SecurityObjects::WebToken &WebToken, SecurityObjects::UserInfo &UserInfo, bool & Expired) {
 | 
				
			||||||
        std::lock_guard G(Mutex_);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::lock_guard G(Mutex_);
 | 
				
			||||||
        Expired = false;
 | 
					        Expired = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        auto Client = UserCache_.get(Token);
 | 
					        std::string TToken{Token}, UserId;
 | 
				
			||||||
        if(!Client.isNull()) {
 | 
					        SecurityObjects::WebToken   WT;
 | 
				
			||||||
            Expired = (Client->webtoken.created_ + Client->webtoken.expires_in_) < std::time(nullptr);
 | 
					 | 
				
			||||||
            WebToken = Client->webtoken;
 | 
					 | 
				
			||||||
            UserInfo = Client->userinfo;
 | 
					 | 
				
			||||||
            return true;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        std::string TToken{Token};
 | 
					 | 
				
			||||||
        if(StorageService()->IsTokenRevoked(TToken)) {
 | 
					 | 
				
			||||||
            return false;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        //  get the token from disk...
 | 
					 | 
				
			||||||
        SecurityObjects::UserInfoAndPolicy UInfo;
 | 
					 | 
				
			||||||
        uint64_t RevocationDate=0;
 | 
					        uint64_t RevocationDate=0;
 | 
				
			||||||
        if(StorageService()->GetToken(TToken, UInfo, RevocationDate)) {
 | 
					        if(StorageService()->UserTokenDB().GetToken(TToken, WT, UserId, RevocationDate)) {
 | 
				
			||||||
            if(RevocationDate!=0)
 | 
					            if(RevocationDate!=0)
 | 
				
			||||||
                return false;
 | 
					                return false;
 | 
				
			||||||
            Expired = (UInfo.webtoken.created_ + UInfo.webtoken.expires_in_) < std::time(nullptr);
 | 
					            Expired = (WT.created_ + WT.expires_in_) < std::time(nullptr);
 | 
				
			||||||
            if(StorageService()->GetUserById(UInfo.userinfo.Id,UInfo.userinfo)) {
 | 
					            if(StorageService()->UserDB().GetUserById(UserId,UserInfo)) {
 | 
				
			||||||
                WebToken = UInfo.webtoken;
 | 
					                WebToken = WT;
 | 
				
			||||||
                UserCache_.update(UInfo.webtoken.access_token_, UInfo);
 | 
					 | 
				
			||||||
                return true;
 | 
					                return true;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return IsValidSubToken(Token, WebToken, UserInfo, Expired);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool AuthService::IsValidSubToken(const std::string &Token, SecurityObjects::WebToken &WebToken, SecurityObjects::UserInfo &UserInfo, bool & Expired) {
 | 
				
			||||||
 | 
					        std::lock_guard G(Mutex_);
 | 
				
			||||||
 | 
					        Expired = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::string TToken{Token}, UserId;
 | 
				
			||||||
 | 
					        SecurityObjects::WebToken   WT;
 | 
				
			||||||
 | 
					        uint64_t RevocationDate=0;
 | 
				
			||||||
 | 
					        if(StorageService()->SubTokenDB().GetToken(TToken, WT, UserId, RevocationDate)) {
 | 
				
			||||||
 | 
					            if(RevocationDate!=0)
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            Expired = (WT.created_ + WT.expires_in_) < std::time(nullptr);
 | 
				
			||||||
 | 
					            if(StorageService()->SubDB().GetUserById(UserId,UserInfo)) {
 | 
				
			||||||
 | 
					                WebToken = WT;
 | 
				
			||||||
 | 
					                return true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
}  // end of namespace
 | 
					}  // end of namespace
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -44,8 +44,8 @@ namespace OpenWifi{
 | 
				
			|||||||
        static ACCESS_TYPE IntToAccessType(int C);
 | 
					        static ACCESS_TYPE IntToAccessType(int C);
 | 
				
			||||||
        static int AccessTypeToInt(ACCESS_TYPE T);
 | 
					        static int AccessTypeToInt(ACCESS_TYPE T);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        static AuthService *instance() {
 | 
					        static auto instance() {
 | 
				
			||||||
            static auto * instance_ = new AuthService;
 | 
					            static auto instance_ = new AuthService;
 | 
				
			||||||
            return instance_;
 | 
					            return instance_;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -59,23 +59,44 @@ namespace OpenWifi{
 | 
				
			|||||||
        [[nodiscard]] const std:: string & PasswordValidationExpression() const { return PasswordValidationStr_;};
 | 
					        [[nodiscard]] const std:: string & PasswordValidationExpression() const { return PasswordValidationStr_;};
 | 
				
			||||||
        void Logout(const std::string &token, bool EraseFromCache=true);
 | 
					        void Logout(const std::string &token, bool EraseFromCache=true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [[nodiscard]] bool IsSubAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired);
 | 
				
			||||||
 | 
					        [[nodiscard]] UNAUTHORIZED_REASON AuthorizeSub( std::string & UserName, const std::string & Password, const std::string & NewPassword, SecurityObjects::UserInfoAndPolicy & UInfo, bool & Expired );
 | 
				
			||||||
 | 
					        void CreateSubToken(const std::string & UserName, SecurityObjects::UserInfoAndPolicy &UInfo);
 | 
				
			||||||
 | 
					        [[nodiscard]] bool SetSubPassword(const std::string &Password, SecurityObjects::UserInfo & UInfo);
 | 
				
			||||||
 | 
					        [[nodiscard]] const std:: string & SubPasswordValidationExpression() const { return PasswordValidationStr_;};
 | 
				
			||||||
 | 
					        void SubLogout(const std::string &token, bool EraseFromCache=true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void RemoveTokenSystemWide(const std::string &token);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        bool ValidatePassword(const std::string &pwd);
 | 
					        bool ValidatePassword(const std::string &pwd);
 | 
				
			||||||
 | 
					        bool ValidateSubPassword(const std::string &pwd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        [[nodiscard]] bool IsValidToken(const std::string &Token, SecurityObjects::WebToken &WebToken, SecurityObjects::UserInfo &UserInfo, bool & Expired);
 | 
					        [[nodiscard]] bool IsValidToken(const std::string &Token, SecurityObjects::WebToken &WebToken, SecurityObjects::UserInfo &UserInfo, bool & Expired);
 | 
				
			||||||
 | 
					        [[nodiscard]] bool IsValidSubToken(const std::string &Token, SecurityObjects::WebToken &WebToken, SecurityObjects::UserInfo &UserInfo, bool & Expired);
 | 
				
			||||||
        [[nodiscard]] std::string GenerateTokenJWT(const std::string & UserName, ACCESS_TYPE Type);
 | 
					        [[nodiscard]] std::string GenerateTokenJWT(const std::string & UserName, ACCESS_TYPE Type);
 | 
				
			||||||
        [[nodiscard]] std::string GenerateTokenHMAC(const std::string & UserName, ACCESS_TYPE Type);
 | 
					        [[nodiscard]] std::string GenerateTokenHMAC(const std::string & UserName, ACCESS_TYPE Type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        [[nodiscard]] std::string ComputeNewPasswordHash(const std::string &UserName, const std::string &Password);
 | 
					        [[nodiscard]] std::string ComputeNewPasswordHash(const std::string &UserName, const std::string &Password);
 | 
				
			||||||
        [[nodiscard]] bool ValidatePasswordHash(const std::string & UserName, const std::string & Password, const std::string &StoredPassword);
 | 
					        [[nodiscard]] bool ValidatePasswordHash(const std::string & UserName, const std::string & Password, const std::string &StoredPassword);
 | 
				
			||||||
 | 
					        [[nodiscard]] bool ValidateSubPasswordHash(const std::string & UserName, const std::string & Password, const std::string &StoredPassword);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        [[nodiscard]] bool UpdatePassword(const std::string &Admin, const std::string &UserName, const std::string & OldPassword, const std::string &NewPassword);
 | 
					        [[nodiscard]] bool UpdatePassword(const std::string &Admin, const std::string &UserName, const std::string & OldPassword, const std::string &NewPassword);
 | 
				
			||||||
        [[nodiscard]] std::string ResetPassword(const std::string &Admin, const std::string &UserName);
 | 
					        [[nodiscard]] std::string ResetPassword(const std::string &Admin, const std::string &UserName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [[nodiscard]] bool UpdateSubPassword(const std::string &Admin, const std::string &UserName, const std::string & OldPassword, const std::string &NewPassword);
 | 
				
			||||||
 | 
					        [[nodiscard]] std::string ResetSubPassword(const std::string &Admin, const std::string &UserName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        [[nodiscard]] static bool VerifyEmail(SecurityObjects::UserInfo &UInfo);
 | 
					        [[nodiscard]] static bool VerifyEmail(SecurityObjects::UserInfo &UInfo);
 | 
				
			||||||
 | 
					        [[nodiscard]] static bool VerifySubEmail(SecurityObjects::UserInfo &UInfo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        [[nodiscard]] static bool SendEmailToUser(const std::string &LinkId, std::string &Email, EMAIL_REASON Reason);
 | 
					        [[nodiscard]] static bool SendEmailToUser(const std::string &LinkId, std::string &Email, EMAIL_REASON Reason);
 | 
				
			||||||
        [[nodiscard]] bool DeleteUserFromCache(const std::string &UserName);
 | 
					        [[nodiscard]] static bool SendEmailToSubUser(const std::string &LinkId, std::string &Email, EMAIL_REASON Reason);
 | 
				
			||||||
        [[nodiscard]] bool RequiresMFA(const SecurityObjects::UserInfoAndPolicy &UInfo);
 | 
					        [[nodiscard]] bool RequiresMFA(const SecurityObjects::UserInfoAndPolicy &UInfo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        bool DeleteUserFromCache(const std::string &UserName);
 | 
				
			||||||
 | 
					        bool DeleteSubUserFromCache(const std::string &UserName);
 | 
				
			||||||
        void RevokeToken(std::string & Token);
 | 
					        void RevokeToken(std::string & Token);
 | 
				
			||||||
 | 
					        void RevokeSubToken(std::string & Token);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        [[nodiscard]] static inline const std::string GetLogoAssetURI() {
 | 
					        [[nodiscard]] static inline const std::string GetLogoAssetURI() {
 | 
				
			||||||
            return MicroService::instance().PublicEndPoint() + "/wwwassets/the_logo.png";
 | 
					            return MicroService::instance().PublicEndPoint() + "/wwwassets/the_logo.png";
 | 
				
			||||||
@@ -85,13 +106,25 @@ namespace OpenWifi{
 | 
				
			|||||||
            return MicroService::instance().WWWAssetsDir() + "/the_logo.png";
 | 
					            return MicroService::instance().WWWAssetsDir() + "/the_logo.png";
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        inline const std::string & GetPasswordPolicy() const { return PasswordPolicy_; }
 | 
				
			||||||
 | 
					        inline const std::string & GetAccessPolicy() const { return AccessPolicy_; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        inline const std::string & GetSubPasswordPolicy() const { return SubPasswordPolicy_; }
 | 
				
			||||||
 | 
					        inline const std::string & GetSubAccessPolicy() const { return SubAccessPolicy_; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private:
 | 
					    private:
 | 
				
			||||||
		Poco::JWT::Signer	Signer_;
 | 
							Poco::JWT::Signer	Signer_;
 | 
				
			||||||
		Poco::SHA2Engine	SHA2_;
 | 
							Poco::SHA2Engine	SHA2_;
 | 
				
			||||||
		Poco::ExpireLRUCache<std::string,SecurityObjects::UserInfoAndPolicy>    UserCache_{2048,1200000};
 | 
					
 | 
				
			||||||
		// SecurityObjects::UserInfoCache UserCache_;
 | 
							std::string         AccessPolicy_;
 | 
				
			||||||
 | 
							std::string         PasswordPolicy_;
 | 
				
			||||||
 | 
							std::string         SubAccessPolicy_;
 | 
				
			||||||
 | 
							std::string         SubPasswordPolicy_;
 | 
				
			||||||
		std::string         PasswordValidationStr_;
 | 
							std::string         PasswordValidationStr_;
 | 
				
			||||||
 | 
					        std::string         SubPasswordValidationStr_;
 | 
				
			||||||
        std::regex          PasswordValidation_;
 | 
					        std::regex          PasswordValidation_;
 | 
				
			||||||
 | 
					        std::regex          SubPasswordValidation_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        uint64_t            TokenAging_ = 30 * 24 * 60 * 60;
 | 
					        uint64_t            TokenAging_ = 30 * 24 * 60 * 60;
 | 
				
			||||||
        uint64_t            HowManyOldPassword_=5;
 | 
					        uint64_t            HowManyOldPassword_=5;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -119,9 +152,12 @@ namespace OpenWifi{
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    inline AuthService * AuthService() { return AuthService::instance(); }
 | 
					    inline auto AuthService() { return AuthService::instance(); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    [[nodiscard]] inline bool AuthServiceIsAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo , bool & Expired) {
 | 
					    [[nodiscard]] inline bool AuthServiceIsAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo , bool & Expired, bool Sub ) {
 | 
				
			||||||
 | 
					        if(Sub)
 | 
				
			||||||
 | 
					            return AuthService()->IsSubAuthorized(Request, SessionToken, UInfo, Expired );
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
            return AuthService()->IsAuthorized(Request, SessionToken, UInfo, Expired );
 | 
					            return AuthService()->IsAuthorized(Request, SessionToken, UInfo, Expired );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,6 +31,7 @@
 | 
				
			|||||||
#include "AuthService.h"
 | 
					#include "AuthService.h"
 | 
				
			||||||
#include "SMSSender.h"
 | 
					#include "SMSSender.h"
 | 
				
			||||||
#include "ActionLinkManager.h"
 | 
					#include "ActionLinkManager.h"
 | 
				
			||||||
 | 
					#include "TotpCache.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
    class Daemon *Daemon::instance_ = nullptr;
 | 
					    class Daemon *Daemon::instance_ = nullptr;
 | 
				
			||||||
@@ -48,6 +49,7 @@ namespace OpenWifi {
 | 
				
			|||||||
                                           ActionLinkManager(),
 | 
					                                           ActionLinkManager(),
 | 
				
			||||||
                                           SMTPMailerService(),
 | 
					                                           SMTPMailerService(),
 | 
				
			||||||
                                           RESTAPI_RateLimiter(),
 | 
					                                           RESTAPI_RateLimiter(),
 | 
				
			||||||
 | 
					                                           TotpCache(),
 | 
				
			||||||
                                           AuthService()
 | 
					                                           AuthService()
 | 
				
			||||||
                                   });
 | 
					                                   });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -56,8 +58,6 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    void Daemon::initialize() {
 | 
					    void Daemon::initialize() {
 | 
				
			||||||
        AssetDir_ = MicroService::instance().ConfigPath("openwifi.restapi.wwwassets");
 | 
					        AssetDir_ = MicroService::instance().ConfigPath("openwifi.restapi.wwwassets");
 | 
				
			||||||
        AccessPolicy_ = MicroService::instance().ConfigPath("openwifi.document.policy.access", "/wwwassets/access_policy.html");
 | 
					 | 
				
			||||||
        PasswordPolicy_ = MicroService::instance().ConfigPath("openwifi.document.policy.password", "/wwwassets/password_policy.html");
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void MicroServicePostInitialization() {
 | 
					    void MicroServicePostInitialization() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,7 +20,6 @@
 | 
				
			|||||||
#include "Poco/Crypto/CipherFactory.h"
 | 
					#include "Poco/Crypto/CipherFactory.h"
 | 
				
			||||||
#include "Poco/Crypto/Cipher.h"
 | 
					#include "Poco/Crypto/Cipher.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "framework/OpenWifiTypes.h"
 | 
					 | 
				
			||||||
#include "framework/MicroService.h"
 | 
					#include "framework/MicroService.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
@@ -44,13 +43,9 @@ namespace OpenWifi {
 | 
				
			|||||||
        void initialize();
 | 
					        void initialize();
 | 
				
			||||||
        static Daemon *instance();
 | 
					        static Daemon *instance();
 | 
				
			||||||
        inline const std::string & AssetDir() { return AssetDir_; }
 | 
					        inline const std::string & AssetDir() { return AssetDir_; }
 | 
				
			||||||
        inline const std::string & GetPasswordPolicy() const { return PasswordPolicy_; }
 | 
					 | 
				
			||||||
        inline const std::string & GetAccessPolicy() const { return AccessPolicy_; }
 | 
					 | 
				
			||||||
    private:
 | 
					    private:
 | 
				
			||||||
        static Daemon 		*instance_;
 | 
					        static Daemon 		*instance_;
 | 
				
			||||||
        std::string         AssetDir_;
 | 
					        std::string         AssetDir_;
 | 
				
			||||||
        std::string         PasswordPolicy_;
 | 
					 | 
				
			||||||
        std::string         AccessPolicy_;
 | 
					 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    inline Daemon * Daemon() { return Daemon::instance(); }
 | 
					    inline Daemon * Daemon() { return Daemon::instance(); }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,6 +7,7 @@
 | 
				
			|||||||
#include "SMTPMailerService.h"
 | 
					#include "SMTPMailerService.h"
 | 
				
			||||||
#include "framework/MicroService.h"
 | 
					#include "framework/MicroService.h"
 | 
				
			||||||
#include "AuthService.h"
 | 
					#include "AuthService.h"
 | 
				
			||||||
 | 
					#include "TotpCache.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -31,6 +32,7 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        ChallengeStart.set("uuid",uuid);
 | 
					        ChallengeStart.set("uuid",uuid);
 | 
				
			||||||
        ChallengeStart.set("created", Created);
 | 
					        ChallengeStart.set("created", Created);
 | 
				
			||||||
 | 
					        ChallengeStart.set("question", "mfa challenge");
 | 
				
			||||||
        ChallengeStart.set("method", UInfo.userinfo.userTypeProprietaryInfo.mfa.method);
 | 
					        ChallengeStart.set("method", UInfo.userinfo.userTypeProprietaryInfo.mfa.method);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Cache_[uuid] = MFACacheEntry{ .UInfo = UInfo, .Answer=Challenge, .Created=Created, .Method=UInfo.userinfo.userTypeProprietaryInfo.mfa.method };
 | 
					        Cache_[uuid] = MFACacheEntry{ .UInfo = UInfo, .Answer=Challenge, .Created=Created, .Method=UInfo.userinfo.userTypeProprietaryInfo.mfa.method };
 | 
				
			||||||
@@ -38,18 +40,18 @@ namespace OpenWifi {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool MFAServer::SendChallenge(const SecurityObjects::UserInfoAndPolicy &UInfo, const std::string &Method, const std::string &Challenge) {
 | 
					    bool MFAServer::SendChallenge(const SecurityObjects::UserInfoAndPolicy &UInfo, const std::string &Method, const std::string &Challenge) {
 | 
				
			||||||
        if(Method=="sms" && SMSSender()->Enabled() && !UInfo.userinfo.userTypeProprietaryInfo.mobiles.empty()) {
 | 
					        if(Method==MFAMETHODS::SMS && SMSSender()->Enabled() && !UInfo.userinfo.userTypeProprietaryInfo.mobiles.empty()) {
 | 
				
			||||||
            std::string Message = "This is your login code: " + Challenge + " Please enter this in your login screen.";
 | 
					            std::string Message = "This is your login code: " + Challenge + " Please enter this in your login screen.";
 | 
				
			||||||
            return SMSSender()->Send(UInfo.userinfo.userTypeProprietaryInfo.mobiles[0].number, Message);
 | 
					            return SMSSender()->Send(UInfo.userinfo.userTypeProprietaryInfo.mobiles[0].number, Message);
 | 
				
			||||||
        }
 | 
					        } else if(Method==MFAMETHODS::EMAIL && SMTPMailerService()->Enabled() && !UInfo.userinfo.email.empty()) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
        if(Method=="email" && SMTPMailerService()->Enabled() && !UInfo.userinfo.email.empty()) {
 | 
					 | 
				
			||||||
            MessageAttributes Attrs;
 | 
					            MessageAttributes Attrs;
 | 
				
			||||||
            Attrs[RECIPIENT_EMAIL] = UInfo.userinfo.email;
 | 
					            Attrs[RECIPIENT_EMAIL] = UInfo.userinfo.email;
 | 
				
			||||||
            Attrs[LOGO] = AuthService::GetLogoAssetURI();
 | 
					            Attrs[LOGO] = AuthService::GetLogoAssetURI();
 | 
				
			||||||
            Attrs[SUBJECT] = "Login validation code";
 | 
					            Attrs[SUBJECT] = "Login validation code";
 | 
				
			||||||
            Attrs[CHALLENGE_CODE] = Challenge;
 | 
					            Attrs[CHALLENGE_CODE] = Challenge;
 | 
				
			||||||
            return SMTPMailerService()->SendMessage(UInfo.userinfo.email, "verification_code.txt", Attrs);
 | 
					            return SMTPMailerService()->SendMessage(UInfo.userinfo.email, "verification_code.txt", Attrs);
 | 
				
			||||||
 | 
					        } else if(Method==MFAMETHODS::AUTHENTICATOR && !UInfo.userinfo.userTypeProprietaryInfo.authenticatorSecret.empty()) {
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
@@ -76,7 +78,12 @@ namespace OpenWifi {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        auto answer = ChallengeResponse->get("answer").toString();
 | 
					        auto answer = ChallengeResponse->get("answer").toString();
 | 
				
			||||||
        if(Hint->second.Answer!=answer) {
 | 
					        std::string Expecting;
 | 
				
			||||||
 | 
					        if(Hint->second.Method==MFAMETHODS::AUTHENTICATOR) {
 | 
				
			||||||
 | 
					            if(!TotpCache()->ValidateCode(Hint->second.UInfo.userinfo.userTypeProprietaryInfo.authenticatorSecret,answer, Expecting)) {
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else if(Hint->second.Answer!=answer) {
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -86,12 +93,15 @@ namespace OpenWifi {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool MFAServer::MethodEnabled(const std::string &Method) {
 | 
					    bool MFAServer::MethodEnabled(const std::string &Method) {
 | 
				
			||||||
        if(Method=="sms")
 | 
					        if(Method==MFAMETHODS::SMS)
 | 
				
			||||||
            return SMSSender()->Enabled();
 | 
					            return SMSSender()->Enabled();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(Method=="email")
 | 
					        if(Method==MFAMETHODS::EMAIL)
 | 
				
			||||||
            return SMTPMailerService()->Enabled();
 | 
					            return SMTPMailerService()->Enabled();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(Method==MFAMETHODS::AUTHENTICATOR)
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,6 +10,17 @@
 | 
				
			|||||||
#include "RESTObjects/RESTAPI_SecurityObjects.h"
 | 
					#include "RESTObjects/RESTAPI_SecurityObjects.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    namespace MFAMETHODS {
 | 
				
			||||||
 | 
					        inline const static std::string SMS{"sms"};
 | 
				
			||||||
 | 
					        inline const static std::string EMAIL{"email"};
 | 
				
			||||||
 | 
					        inline const static std::string AUTHENTICATOR{"authenticator"};
 | 
				
			||||||
 | 
					        inline const static std::vector<std::string> Methods{ SMS, EMAIL, AUTHENTICATOR };
 | 
				
			||||||
 | 
					        inline bool Validate(const std::string &M) {
 | 
				
			||||||
 | 
					            return std::find(cbegin(Methods), cend(Methods),M)!=Methods.end();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    struct MFACacheEntry {
 | 
					    struct MFACacheEntry {
 | 
				
			||||||
        SecurityObjects::UserInfoAndPolicy  UInfo;
 | 
					        SecurityObjects::UserInfoAndPolicy  UInfo;
 | 
				
			||||||
        std::string                         Answer;
 | 
					        std::string                         Answer;
 | 
				
			||||||
@@ -17,14 +28,15 @@ namespace OpenWifi {
 | 
				
			|||||||
        std::string                         Method;
 | 
					        std::string                         Method;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    typedef std::map<std::string,MFACacheEntry>     MFAChallengeCache;
 | 
					    typedef std::map<std::string,MFACacheEntry>     MFAChallengeCache;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class MFAServer : public SubSystemServer{
 | 
					    class MFAServer : public SubSystemServer{
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        int Start() override;
 | 
					        int Start() override;
 | 
				
			||||||
        void Stop() override;
 | 
					        void Stop() override;
 | 
				
			||||||
        static MFAServer *instance() {
 | 
					        static auto instance() {
 | 
				
			||||||
            static auto * instance_ = new MFAServer;
 | 
					            static auto instance_ = new MFAServer;
 | 
				
			||||||
            return instance_;
 | 
					            return instance_;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -35,7 +47,9 @@ namespace OpenWifi {
 | 
				
			|||||||
        static bool SendChallenge(const SecurityObjects::UserInfoAndPolicy &UInfo, const std::string &Method, const std::string &Challenge);
 | 
					        static bool SendChallenge(const SecurityObjects::UserInfoAndPolicy &UInfo, const std::string &Method, const std::string &Challenge);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        static inline std::string MakeChallenge() {
 | 
					        static inline std::string MakeChallenge() {
 | 
				
			||||||
            return std::to_string(MicroService::instance().Random(1,999999));
 | 
					            char buf[16];
 | 
				
			||||||
 | 
					            std::sprintf(buf,"%06llu",MicroService::instance().Random(1,999999));
 | 
				
			||||||
 | 
					            return buf;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private:
 | 
					    private:
 | 
				
			||||||
@@ -48,7 +62,7 @@ namespace OpenWifi {
 | 
				
			|||||||
        void CleanCache();
 | 
					        void CleanCache();
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    inline MFAServer & MFAServer() { return *MFAServer::instance(); }
 | 
					    inline auto MFAServer() { return MFAServer::instance(); }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif //OWSEC_MFASERVER_H
 | 
					#endif //OWSEC_MFASERVER_H
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,7 +18,7 @@ namespace OpenWifi {
 | 
				
			|||||||
        auto Id = GetParameter("id","");
 | 
					        auto Id = GetParameter("id","");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        SecurityObjects::ActionLink Link;
 | 
					        SecurityObjects::ActionLink Link;
 | 
				
			||||||
        if(!StorageService()->GetActionLink(Id,Link))
 | 
					        if(!StorageService()->ActionLinksDB().GetActionLink(Id,Link))
 | 
				
			||||||
            return DoReturnA404();
 | 
					            return DoReturnA404();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(Action=="password_reset")
 | 
					        if(Action=="password_reset")
 | 
				
			||||||
@@ -58,11 +58,11 @@ namespace OpenWifi {
 | 
				
			|||||||
            auto Now = std::time(nullptr);
 | 
					            auto Now = std::time(nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            SecurityObjects::ActionLink Link;
 | 
					            SecurityObjects::ActionLink Link;
 | 
				
			||||||
            if(!StorageService()->GetActionLink(Id,Link))
 | 
					            if(!StorageService()->ActionLinksDB().GetActionLink(Id,Link))
 | 
				
			||||||
                return DoReturnA404();
 | 
					                return DoReturnA404();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(Now > Link.expires) {
 | 
					            if(Now > Link.expires) {
 | 
				
			||||||
                StorageService()->CancelAction(Id);
 | 
					                StorageService()->ActionLinksDB().CancelAction(Id);
 | 
				
			||||||
                return DoReturnA404();
 | 
					                return DoReturnA404();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -77,7 +77,9 @@ namespace OpenWifi {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            SecurityObjects::UserInfo   UInfo;
 | 
					            SecurityObjects::UserInfo   UInfo;
 | 
				
			||||||
            if(!StorageService()->GetUserById(Link.userId,UInfo)) {
 | 
					
 | 
				
			||||||
 | 
					            bool Found = Link.userAction ? StorageService()->UserDB().GetUserById(Link.userId,UInfo) : StorageService()->SubDB().GetUserById(Link.userId,UInfo);
 | 
				
			||||||
 | 
					            if(!Found) {
 | 
				
			||||||
                Poco::File  FormFile{ Daemon()->AssetDir() + "/password_reset_error.html"};
 | 
					                Poco::File  FormFile{ Daemon()->AssetDir() + "/password_reset_error.html"};
 | 
				
			||||||
                Types::StringPairVec    FormVars{ {"UUID", Id},
 | 
					                Types::StringPairVec    FormVars{ {"UUID", Id},
 | 
				
			||||||
                                                  {"ERROR_TEXT", "This request does not contain a valid user ID. Please contact your system administrator."}};
 | 
					                                                  {"ERROR_TEXT", "This request does not contain a valid user ID. Please contact your system administrator."}};
 | 
				
			||||||
@@ -91,18 +93,25 @@ namespace OpenWifi {
 | 
				
			|||||||
                return SendHTMLFileBack(FormFile,FormVars);
 | 
					                return SendHTMLFileBack(FormFile,FormVars);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(!AuthService()->SetPassword(Password1,UInfo)) {
 | 
					            bool GoodPassword = Link.userAction ? AuthService()->SetPassword(Password1,UInfo) : AuthService()->SetSubPassword(Password1,UInfo);
 | 
				
			||||||
 | 
					            if(!GoodPassword) {
 | 
				
			||||||
                Poco::File  FormFile{ Daemon()->AssetDir() + "/password_reset_error.html"};
 | 
					                Poco::File  FormFile{ Daemon()->AssetDir() + "/password_reset_error.html"};
 | 
				
			||||||
                Types::StringPairVec    FormVars{ {"UUID", Id},
 | 
					                Types::StringPairVec    FormVars{ {"UUID", Id},
 | 
				
			||||||
                                                  {"ERROR_TEXT", "You cannot reuse one of your recent passwords."}};
 | 
					                                                  {"ERROR_TEXT", "You cannot reuse one of your recent passwords."}};
 | 
				
			||||||
                return SendHTMLFileBack(FormFile,FormVars);
 | 
					                return SendHTMLFileBack(FormFile,FormVars);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            StorageService()->UpdateUserInfo(UInfo.email,Link.userId,UInfo);
 | 
					
 | 
				
			||||||
 | 
					            UInfo.modified = std::time(nullptr);
 | 
				
			||||||
 | 
					            if(Link.userAction)
 | 
				
			||||||
 | 
					                StorageService()->UserDB().UpdateUserInfo(UInfo.email,Link.userId,UInfo);
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					                StorageService()->SubDB().UpdateUserInfo(UInfo.email,Link.userId,UInfo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Poco::File  FormFile{ Daemon()->AssetDir() + "/password_reset_success.html"};
 | 
					            Poco::File  FormFile{ Daemon()->AssetDir() + "/password_reset_success.html"};
 | 
				
			||||||
            Types::StringPairVec    FormVars{ {"UUID", Id},
 | 
					            Types::StringPairVec    FormVars{ {"UUID", Id},
 | 
				
			||||||
                                              {"USERNAME", UInfo.email},
 | 
					                                              {"USERNAME", UInfo.email},
 | 
				
			||||||
                                              {"ACTION_LINK",MicroService::instance().GetUIURI()}};
 | 
					                                              {"ACTION_LINK",MicroService::instance().GetUIURI()}};
 | 
				
			||||||
            StorageService()->CompleteAction(Id);
 | 
					            StorageService()->ActionLinksDB().CompleteAction(Id);
 | 
				
			||||||
            SendHTMLFileBack(FormFile,FormVars);
 | 
					            SendHTMLFileBack(FormFile,FormVars);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            DoReturnA404();
 | 
					            DoReturnA404();
 | 
				
			||||||
@@ -113,12 +122,13 @@ namespace OpenWifi {
 | 
				
			|||||||
        auto Now = std::time(nullptr);
 | 
					        auto Now = std::time(nullptr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(Now > Link.expires) {
 | 
					        if(Now > Link.expires) {
 | 
				
			||||||
            StorageService()->CancelAction(Link.id);
 | 
					            StorageService()->ActionLinksDB().CancelAction(Link.id);
 | 
				
			||||||
            return DoReturnA404();
 | 
					            return DoReturnA404();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        SecurityObjects::UserInfo UInfo;
 | 
					        SecurityObjects::UserInfo UInfo;
 | 
				
			||||||
        if (!StorageService()->GetUserById(Link.userId, UInfo)) {
 | 
					        bool Found = Link.userAction ? StorageService()->UserDB().GetUserById(Link.userId,UInfo) : StorageService()->SubDB().GetUserById(Link.userId,UInfo);
 | 
				
			||||||
 | 
					        if (!Found) {
 | 
				
			||||||
            Types::StringPairVec FormVars{{"UUID",       Link.id},
 | 
					            Types::StringPairVec FormVars{{"UUID",       Link.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{Daemon()->AssetDir() + "/email_verification_error.html"};
 | 
					            Poco::File FormFile{Daemon()->AssetDir() + "/email_verification_error.html"};
 | 
				
			||||||
@@ -130,12 +140,16 @@ namespace OpenWifi {
 | 
				
			|||||||
        UInfo.validated = true;
 | 
					        UInfo.validated = true;
 | 
				
			||||||
        UInfo.lastEmailCheck = std::time(nullptr);
 | 
					        UInfo.lastEmailCheck = std::time(nullptr);
 | 
				
			||||||
        UInfo.validationDate = std::time(nullptr);
 | 
					        UInfo.validationDate = std::time(nullptr);
 | 
				
			||||||
        StorageService()->UpdateUserInfo(UInfo.email, Link.userId, UInfo);
 | 
					        UInfo.modified  = std::time(nullptr);
 | 
				
			||||||
 | 
					        if(Link.userAction)
 | 
				
			||||||
 | 
					            StorageService()->UserDB().UpdateUserInfo(UInfo.email, Link.userId, UInfo);
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            StorageService()->SubDB().UpdateUserInfo(UInfo.email, Link.userId, UInfo);
 | 
				
			||||||
        Types::StringPairVec FormVars{{"UUID",     Link.id},
 | 
					        Types::StringPairVec FormVars{{"UUID",     Link.id},
 | 
				
			||||||
                                      {"USERNAME", UInfo.email},
 | 
					                                      {"USERNAME", UInfo.email},
 | 
				
			||||||
                                      {"ACTION_LINK",MicroService::instance().GetUIURI()}};
 | 
					                                      {"ACTION_LINK",MicroService::instance().GetUIURI()}};
 | 
				
			||||||
        Poco::File FormFile{Daemon()->AssetDir() + "/email_verification_success.html"};
 | 
					        Poco::File FormFile{Daemon()->AssetDir() + "/email_verification_success.html"};
 | 
				
			||||||
        StorageService()->CompleteAction(Link.id);
 | 
					        StorageService()->ActionLinksDB().CompleteAction(Link.id);
 | 
				
			||||||
        SendHTMLFileBack(FormFile, FormVars);
 | 
					        SendHTMLFileBack(FormFile, FormVars);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,22 +2,21 @@
 | 
				
			|||||||
// Created by stephane bourque on 2021-06-22.
 | 
					// Created by stephane bourque on 2021-06-22.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef UCENTRALSEC_RESTAPI_ACTION_LINKS_H
 | 
					#pragma once
 | 
				
			||||||
#define UCENTRALSEC_RESTAPI_ACTION_LINKS_H
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "framework/MicroService.h"
 | 
					#include "framework/MicroService.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
    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, RESTAPI_GenericServer &Server, uint64_t TransactionId, bool Internal)
 | 
				
			||||||
                : RESTAPIHandler(bindings, L,
 | 
					                : RESTAPIHandler(bindings, L,
 | 
				
			||||||
             std::vector<std::string>{
 | 
					             std::vector<std::string>{
 | 
				
			||||||
                                        Poco::Net::HTTPRequest::HTTP_GET,
 | 
					                                        Poco::Net::HTTPRequest::HTTP_GET,
 | 
				
			||||||
                                        Poco::Net::HTTPRequest::HTTP_POST,
 | 
					                                        Poco::Net::HTTPRequest::HTTP_POST,
 | 
				
			||||||
                                        Poco::Net::HTTPRequest::HTTP_OPTIONS},
 | 
					                                        Poco::Net::HTTPRequest::HTTP_OPTIONS},
 | 
				
			||||||
                                        Server,
 | 
					                                        Server,
 | 
				
			||||||
 | 
					                                        TransactionId,
 | 
				
			||||||
                                        Internal,
 | 
					                                        Internal,
 | 
				
			||||||
                                        false,
 | 
					                                        false,
 | 
				
			||||||
                                        true, RateLimit{.Interval=1000,.MaxCalls=10}) {}
 | 
					                                        true, RateLimit{.Interval=1000,.MaxCalls=10}) {}
 | 
				
			||||||
@@ -33,5 +32,3 @@ namespace OpenWifi {
 | 
				
			|||||||
        void DoPut() final {};
 | 
					        void DoPut() final {};
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif //UCENTRALSEC_RESTAPI_ACTION_LINKS_H
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,13 +2,13 @@
 | 
				
			|||||||
// Created by stephane bourque on 2021-07-10.
 | 
					// Created by stephane bourque on 2021-07-10.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "RESTAPI_AssetServer.h"
 | 
					#include "RESTAPI_asset_server.h"
 | 
				
			||||||
#include "Poco/File.h"
 | 
					#include "Poco/File.h"
 | 
				
			||||||
#include "framework/RESTAPI_protocol.h"
 | 
					#include "framework/RESTAPI_protocol.h"
 | 
				
			||||||
#include "Daemon.h"
 | 
					#include "Daemon.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
    void RESTAPI_AssetServer::DoGet() {
 | 
					    void RESTAPI_asset_server::DoGet() {
 | 
				
			||||||
        Poco::File  AssetFile;
 | 
					        Poco::File  AssetFile;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(Request->getURI().find("/favicon.ico") != std::string::npos) {
 | 
					        if(Request->getURI().find("/favicon.ico") != std::string::npos) {
 | 
				
			||||||
@@ -2,15 +2,14 @@
 | 
				
			|||||||
// Created by stephane bourque on 2021-07-10.
 | 
					// Created by stephane bourque on 2021-07-10.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef UCENTRALSEC_RESTAPI_ASSETSERVER_H
 | 
					#pragma once
 | 
				
			||||||
#define UCENTRALSEC_RESTAPI_ASSETSERVER_H
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "../framework/MicroService.h"
 | 
					#include "../framework/MicroService.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
    class RESTAPI_AssetServer : public RESTAPIHandler {
 | 
					    class RESTAPI_asset_server : public RESTAPIHandler {
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        RESTAPI_AssetServer(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, bool Internal)
 | 
					        RESTAPI_asset_server(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, uint64_t TransactionId, bool Internal)
 | 
				
			||||||
                : RESTAPIHandler(bindings, L,
 | 
					                : RESTAPIHandler(bindings, L,
 | 
				
			||||||
                                 std::vector<std::string>
 | 
					                                 std::vector<std::string>
 | 
				
			||||||
                                         {Poco::Net::HTTPRequest::HTTP_POST,
 | 
					                                         {Poco::Net::HTTPRequest::HTTP_POST,
 | 
				
			||||||
@@ -19,6 +18,7 @@ namespace OpenWifi {
 | 
				
			|||||||
                                          Poco::Net::HTTPRequest::HTTP_DELETE,
 | 
					                                          Poco::Net::HTTPRequest::HTTP_DELETE,
 | 
				
			||||||
                                          Poco::Net::HTTPRequest::HTTP_OPTIONS},
 | 
					                                          Poco::Net::HTTPRequest::HTTP_OPTIONS},
 | 
				
			||||||
                                          Server,
 | 
					                                          Server,
 | 
				
			||||||
 | 
					                                          TransactionId,
 | 
				
			||||||
                                          Internal, false) {}
 | 
					                                          Internal, false) {}
 | 
				
			||||||
        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"}; };
 | 
				
			||||||
@@ -32,5 +32,3 @@ namespace OpenWifi {
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif //UCENTRALSEC_RESTAPI_ASSETSERVER_H
 | 
					 | 
				
			||||||
@@ -5,7 +5,7 @@
 | 
				
			|||||||
#include <fstream>
 | 
					#include <fstream>
 | 
				
			||||||
#include <iostream>
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "RESTAPI_avatarHandler.h"
 | 
					#include "RESTAPI_avatar_handler.h"
 | 
				
			||||||
#include "StorageService.h"
 | 
					#include "StorageService.h"
 | 
				
			||||||
#include "Poco/Net/HTMLForm.h"
 | 
					#include "Poco/Net/HTMLForm.h"
 | 
				
			||||||
#include "framework/RESTAPI_protocol.h"
 | 
					#include "framework/RESTAPI_protocol.h"
 | 
				
			||||||
@@ -22,33 +22,26 @@ namespace OpenWifi {
 | 
				
			|||||||
            Name_ = Parameters.get(RESTAPI::Protocol::NAME, RESTAPI::Protocol::UNNAMED);
 | 
					            Name_ = Parameters.get(RESTAPI::Protocol::NAME, RESTAPI::Protocol::UNNAMED);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        Poco::CountingInputStream InputStream(Stream);
 | 
					        Poco::CountingInputStream InputStream(Stream);
 | 
				
			||||||
        std::ofstream OutputStream(TempFile_.path(), std::ofstream::out);
 | 
					        Poco::StreamCopier::copyStream(InputStream, OutputStream_);
 | 
				
			||||||
        Poco::StreamCopier::copyStream(InputStream, OutputStream);
 | 
					        Length_ = OutputStream_.str().size();
 | 
				
			||||||
        Length_ = InputStream.chars();
 | 
					 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void RESTAPI_avatarHandler::DoPost() {
 | 
					    void RESTAPI_avatar_handler::DoPost() {
 | 
				
			||||||
        std::string Id = GetBinding(RESTAPI::Protocol::ID, "");
 | 
					        std::string Id = UserInfo_.userinfo.id;
 | 
				
			||||||
        SecurityObjects::UserInfo UInfo;
 | 
					        SecurityObjects::UserInfo UInfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (Id.empty() || !StorageService()->GetUserById(Id, UInfo)) {
 | 
					        std::stringstream SS;
 | 
				
			||||||
            return NotFound();
 | 
					        AvatarPartHandler partHandler(Id, Logger_, SS);
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        //  if there is an avatar, just remove it...
 | 
					 | 
				
			||||||
        StorageService()->DeleteAvatar(UserInfo_.userinfo.email,Id);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Poco::TemporaryFile TmpFile;
 | 
					 | 
				
			||||||
        AvatarPartHandler partHandler(Id, Logger_, TmpFile);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Poco::Net::HTMLForm form(*Request, Request->stream(), partHandler);
 | 
					        Poco::Net::HTMLForm form(*Request, Request->stream(), partHandler);
 | 
				
			||||||
        Poco::JSON::Object Answer;
 | 
					        Poco::JSON::Object Answer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!partHandler.Name().empty() && partHandler.Length()< MicroService::instance().ConfigGetInt("openwifi.avatar.maxsize",2000000)) {
 | 
					        if (!partHandler.Name().empty() && partHandler.Length()< MicroService::instance().ConfigGetInt("openwifi.avatar.maxsize",2000000)) {
 | 
				
			||||||
            Answer.set(RESTAPI::Protocol::AVATARID, Id);
 | 
					            Answer.set(RESTAPI::Protocol::AVATARID, Id);
 | 
				
			||||||
            Answer.set(RESTAPI::Protocol::ERRORCODE, 0);
 | 
					            Answer.set(RESTAPI::Protocol::ERRORCODE, 0);
 | 
				
			||||||
            Logger_.information(Poco::format("Uploaded avatar: %s Type: %s", partHandler.Name(), partHandler.ContentType()));
 | 
					            Logger_.information(Poco::format("Uploaded avatar: %s Type: %s", partHandler.Name(), partHandler.ContentType()));
 | 
				
			||||||
            StorageService()->SetAvatar(UserInfo_.userinfo.email,
 | 
					            StorageService()->AvatarDB().SetAvatar(UserInfo_.userinfo.email,
 | 
				
			||||||
                                 Id, TmpFile, partHandler.ContentType(), partHandler.Name());
 | 
					                                 Id, SS.str(), partHandler.ContentType(), partHandler.Name());
 | 
				
			||||||
 | 
					            StorageService()->UserDB().SetAvatar(Id,"1");
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            Answer.set(RESTAPI::Protocol::AVATARID, Id);
 | 
					            Answer.set(RESTAPI::Protocol::AVATARID, Id);
 | 
				
			||||||
            Answer.set(RESTAPI::Protocol::ERRORCODE, 13);
 | 
					            Answer.set(RESTAPI::Protocol::ERRORCODE, 13);
 | 
				
			||||||
@@ -57,27 +50,31 @@ namespace OpenWifi {
 | 
				
			|||||||
        ReturnObject(Answer);
 | 
					        ReturnObject(Answer);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void RESTAPI_avatarHandler::DoGet() {
 | 
					    void RESTAPI_avatar_handler::DoGet() {
 | 
				
			||||||
        std::string Id = GetBinding(RESTAPI::Protocol::ID, "");
 | 
					        std::string Id = GetBinding(RESTAPI::Protocol::ID, "");
 | 
				
			||||||
        if (Id.empty()) {
 | 
					        if (Id.empty()) {
 | 
				
			||||||
            return NotFound();
 | 
					            return NotFound();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        Poco::TemporaryFile TempAvatar;
 | 
					 | 
				
			||||||
        std::string Type, Name;
 | 
					 | 
				
			||||||
        if (!StorageService()->GetAvatar(UserInfo_.userinfo.email, Id, TempAvatar, Type, Name)) {
 | 
					 | 
				
			||||||
            return NotFound();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        SendFile(TempAvatar, Type, Name);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void RESTAPI_avatarHandler::DoDelete() {
 | 
					        std::string Type, Name, AvatarContent;
 | 
				
			||||||
 | 
					        if (!StorageService()->AvatarDB().GetAvatar(UserInfo_.userinfo.email, Id, AvatarContent, Type, Name)) {
 | 
				
			||||||
 | 
					            return NotFound();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return SendFileContent(AvatarContent, Type, Name);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void RESTAPI_avatar_handler::DoDelete() {
 | 
				
			||||||
        std::string Id = GetBinding(RESTAPI::Protocol::ID, "");
 | 
					        std::string Id = GetBinding(RESTAPI::Protocol::ID, "");
 | 
				
			||||||
        if (Id.empty()) {
 | 
					
 | 
				
			||||||
            return NotFound();
 | 
					        if(UserInfo_.userinfo.userRole!=SecurityObjects::ROOT && Id!=UserInfo_.userinfo.id) {
 | 
				
			||||||
        }
 | 
					            return UnAuthorized(RESTAPI::Errors::InsufficientAccessRights, ACCESS_DENIED);
 | 
				
			||||||
        if (!StorageService()->DeleteAvatar(UserInfo_.userinfo.email, Id)) {
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!StorageService()->AvatarDB().DeleteAvatar(UserInfo_.userinfo.email, Id)) {
 | 
				
			||||||
            return NotFound();
 | 
					            return NotFound();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        StorageService()->UserDB().SetAvatar(Id,"");
 | 
				
			||||||
        OK();
 | 
					        OK();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -1,10 +1,7 @@
 | 
				
			|||||||
//
 | 
					//
 | 
				
			||||||
// Created by stephane bourque on 2021-07-15.
 | 
					// Created by stephane bourque on 2021-07-15.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
#ifndef UCENTRALSEC_RESTAPI_AVATARHANDLER_H
 | 
					 | 
				
			||||||
#define UCENTRALSEC_RESTAPI_AVATARHANDLER_H
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "framework/MicroService.h"
 | 
					#include "framework/MicroService.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -12,28 +9,28 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    class AvatarPartHandler : public Poco::Net::PartHandler {
 | 
					    class AvatarPartHandler : public Poco::Net::PartHandler {
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        AvatarPartHandler(std::string Id, Poco::Logger &Logger, Poco::TemporaryFile &TmpFile) :
 | 
					        AvatarPartHandler(std::string Id, Poco::Logger &Logger, std::stringstream & ofs) :
 | 
				
			||||||
                Id_(std::move(Id)),
 | 
					                Id_(std::move(Id)),
 | 
				
			||||||
                Logger_(Logger),
 | 
					                Logger_(Logger),
 | 
				
			||||||
                TempFile_(TmpFile){
 | 
					                OutputStream_(ofs){
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        void handlePart(const Poco::Net::MessageHeader &Header, std::istream &Stream);
 | 
					        void handlePart(const Poco::Net::MessageHeader &Header, std::istream &Stream);
 | 
				
			||||||
        [[nodiscard]] uint64_t Length() const { return Length_; }
 | 
					        [[nodiscard]] uint64_t Length() const { return Length_; }
 | 
				
			||||||
        [[nodiscard]] std::string &Name() { return Name_; }
 | 
					        [[nodiscard]] std::string &Name() { return Name_; }
 | 
				
			||||||
        [[nodiscard]] std::string &ContentType() { return FileType_; }
 | 
					        [[nodiscard]] std::string &ContentType() { return FileType_; }
 | 
				
			||||||
        [[nodiscard]] std::string FileName() const { return TempFile_.path(); }
 | 
					
 | 
				
			||||||
    private:
 | 
					    private:
 | 
				
			||||||
        uint64_t        Length_ = 0;
 | 
					        uint64_t        Length_ = 0;
 | 
				
			||||||
        std::string     FileType_;
 | 
					        std::string     FileType_;
 | 
				
			||||||
        std::string     Name_;
 | 
					        std::string     Name_;
 | 
				
			||||||
        std::string     Id_;
 | 
					        std::string     Id_;
 | 
				
			||||||
        Poco::Logger    &Logger_;
 | 
					        Poco::Logger    &Logger_;
 | 
				
			||||||
        Poco::TemporaryFile &TempFile_;
 | 
					        std::stringstream &OutputStream_;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class RESTAPI_avatarHandler : public RESTAPIHandler {
 | 
					    class RESTAPI_avatar_handler : public RESTAPIHandler {
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        RESTAPI_avatarHandler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, bool Internal)
 | 
					        RESTAPI_avatar_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, uint64_t TransactionId, bool Internal)
 | 
				
			||||||
                : RESTAPIHandler(bindings, L,
 | 
					                : RESTAPIHandler(bindings, L,
 | 
				
			||||||
                                 std::vector<std::string>{
 | 
					                                 std::vector<std::string>{
 | 
				
			||||||
                                         Poco::Net::HTTPRequest::HTTP_GET,
 | 
					                                         Poco::Net::HTTPRequest::HTTP_GET,
 | 
				
			||||||
@@ -41,6 +38,7 @@ namespace OpenWifi {
 | 
				
			|||||||
                                         Poco::Net::HTTPRequest::HTTP_DELETE,
 | 
					                                         Poco::Net::HTTPRequest::HTTP_DELETE,
 | 
				
			||||||
                                         Poco::Net::HTTPRequest::HTTP_OPTIONS},
 | 
					                                         Poco::Net::HTTPRequest::HTTP_OPTIONS},
 | 
				
			||||||
                                         Server,
 | 
					                                         Server,
 | 
				
			||||||
 | 
					                                         TransactionId,
 | 
				
			||||||
                                         Internal) {}
 | 
					                                         Internal) {}
 | 
				
			||||||
        static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/avatar/{id}"}; };
 | 
					        static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/avatar/{id}"}; };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -51,4 +49,3 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif //UCENTRALSEC_RESTAPI_AVATARHANDLER_H
 | 
					 | 
				
			||||||
							
								
								
									
										17
									
								
								src/RESTAPI/RESTAPI_db_helpers.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/RESTAPI/RESTAPI_db_helpers.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Created by stephane bourque on 2022-01-01.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "framework/orm.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline void Sanitize(const SecurityObjects::UserInfoAndPolicy &User, SecurityObjects::UserInfo & U) {
 | 
				
			||||||
 | 
					        U.currentPassword.clear();
 | 
				
			||||||
 | 
					        U.lastPasswords.clear();
 | 
				
			||||||
 | 
					        U.oauthType.clear();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -2,20 +2,19 @@
 | 
				
			|||||||
// Created by stephane bourque on 2021-09-02.
 | 
					// Created by stephane bourque on 2021-09-02.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef OWSEC_RESTAPI_EMAIL_HANDLER_H
 | 
					#pragma once
 | 
				
			||||||
#define OWSEC_RESTAPI_EMAIL_HANDLER_H
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "framework/MicroService.h"
 | 
					#include "framework/MicroService.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
    class RESTAPI_email_handler : public RESTAPIHandler {
 | 
					    class RESTAPI_email_handler : public RESTAPIHandler {
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        RESTAPI_email_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, bool Internal)
 | 
					        RESTAPI_email_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, uint64_t TransactionId, bool Internal)
 | 
				
			||||||
        : RESTAPIHandler(bindings, L,
 | 
					        : RESTAPIHandler(bindings, L,
 | 
				
			||||||
                         std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_POST,
 | 
					                         std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_POST,
 | 
				
			||||||
                                                  Poco::Net::HTTPRequest::HTTP_OPTIONS},
 | 
					                                                  Poco::Net::HTTPRequest::HTTP_OPTIONS},
 | 
				
			||||||
                                                  Server,
 | 
					                                                  Server,
 | 
				
			||||||
 | 
					                                                  TransactionId,
 | 
				
			||||||
                                                  Internal) {}
 | 
					                                                  Internal) {}
 | 
				
			||||||
        static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/email"};}
 | 
					        static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/email"};}
 | 
				
			||||||
        void DoGet() final {};
 | 
					        void DoGet() final {};
 | 
				
			||||||
@@ -24,5 +23,3 @@ namespace OpenWifi {
 | 
				
			|||||||
        void DoPut() final {};
 | 
					        void DoPut() final {};
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif //OWSEC_RESTAPI_EMAIL_HANDLER_H
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,47 +8,41 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "Poco/JSON/Parser.h"
 | 
					#include "Poco/JSON/Parser.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "Daemon.h"
 | 
					 | 
				
			||||||
#include "AuthService.h"
 | 
					#include "AuthService.h"
 | 
				
			||||||
#include "RESTAPI_oauth2Handler.h"
 | 
					#include "RESTAPI_oauth2_handler.h"
 | 
				
			||||||
#include "MFAServer.h"
 | 
					#include "MFAServer.h"
 | 
				
			||||||
#include "framework/RESTAPI_protocol.h"
 | 
					#include "framework/RESTAPI_protocol.h"
 | 
				
			||||||
#include "framework/MicroService.h"
 | 
					#include "framework/MicroService.h"
 | 
				
			||||||
#include "StorageService.h"
 | 
					#include "StorageService.h"
 | 
				
			||||||
 | 
					#include "RESTAPI_db_helpers.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static void FilterCredentials(SecurityObjects::UserInfo & U) {
 | 
						void RESTAPI_oauth2_handler::DoGet() {
 | 
				
			||||||
        U.currentPassword.clear();
 | 
						    bool Expired = false, Contacted = false;
 | 
				
			||||||
        U.lastPasswords.clear();
 | 
					        if (!IsAuthorized(Expired, Contacted)) {
 | 
				
			||||||
        U.oauthType.clear();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	void RESTAPI_oauth2Handler::DoGet() {
 | 
					 | 
				
			||||||
	    bool Expired = false;
 | 
					 | 
				
			||||||
        if (!IsAuthorized(Expired)) {
 | 
					 | 
				
			||||||
            if(Expired)
 | 
					            if(Expired)
 | 
				
			||||||
                return UnAuthorized(RESTAPI::Errors::ExpiredToken,EXPIRED_TOKEN);
 | 
					                return UnAuthorized(RESTAPI::Errors::ExpiredToken,EXPIRED_TOKEN);
 | 
				
			||||||
            return UnAuthorized(RESTAPI::Errors::MissingAuthenticationInformation);
 | 
					            return UnAuthorized(RESTAPI::Errors::MissingAuthenticationInformation, INVALID_TOKEN);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        bool GetMe = GetBoolParameter(RESTAPI::Protocol::ME, false);
 | 
					        bool GetMe = GetBoolParameter(RESTAPI::Protocol::ME, false);
 | 
				
			||||||
        if(GetMe) {
 | 
					        if(GetMe) {
 | 
				
			||||||
            Logger_.information(Poco::format("REQUEST-ME(%s): Request for %s", Request->clientAddress().toString(), UserInfo_.userinfo.email));
 | 
					            Logger_.information(Poco::format("REQUEST-ME(%s): Request for %s", Request->clientAddress().toString(), UserInfo_.userinfo.email));
 | 
				
			||||||
            Poco::JSON::Object Me;
 | 
					            Poco::JSON::Object Me;
 | 
				
			||||||
            SecurityObjects::UserInfo   ReturnedUser = UserInfo_.userinfo;
 | 
					            SecurityObjects::UserInfo   ReturnedUser = UserInfo_.userinfo;
 | 
				
			||||||
            FilterCredentials(ReturnedUser);
 | 
					            Sanitize(UserInfo_, ReturnedUser);
 | 
				
			||||||
            ReturnedUser.to_json(Me);
 | 
					            ReturnedUser.to_json(Me);
 | 
				
			||||||
            return ReturnObject(Me);
 | 
					            return ReturnObject(Me);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        BadRequest(RESTAPI::Errors::UnrecognizedRequest);
 | 
					        BadRequest(RESTAPI::Errors::UnrecognizedRequest);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void RESTAPI_oauth2Handler::DoDelete() {
 | 
					    void RESTAPI_oauth2_handler::DoDelete() {
 | 
				
			||||||
	    bool Expired = false;
 | 
						    bool Expired = false, Contacted=false;
 | 
				
			||||||
	    if (!IsAuthorized(Expired)) {
 | 
						    if (!IsAuthorized(Expired, Contacted)) {
 | 
				
			||||||
	        if(Expired)
 | 
						        if(Expired)
 | 
				
			||||||
	            return UnAuthorized(RESTAPI::Errors::ExpiredToken,EXPIRED_TOKEN);
 | 
						            return UnAuthorized(RESTAPI::Errors::ExpiredToken,EXPIRED_TOKEN);
 | 
				
			||||||
	        return UnAuthorized(RESTAPI::Errors::MissingAuthenticationInformation);
 | 
						        return UnAuthorized(RESTAPI::Errors::MissingAuthenticationInformation, INVALID_TOKEN);
 | 
				
			||||||
	    }
 | 
						    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        auto Token = GetBinding(RESTAPI::Protocol::TOKEN, "...");
 | 
					        auto Token = GetBinding(RESTAPI::Protocol::TOKEN, "...");
 | 
				
			||||||
@@ -61,7 +55,7 @@ namespace OpenWifi {
 | 
				
			|||||||
        NotFound();
 | 
					        NotFound();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void RESTAPI_oauth2Handler::DoPost() {
 | 
						void RESTAPI_oauth2_handler::DoPost() {
 | 
				
			||||||
        auto Obj = ParseStream();
 | 
					        auto Obj = ParseStream();
 | 
				
			||||||
        auto userId = GetS(RESTAPI::Protocol::USERID, Obj);
 | 
					        auto userId = GetS(RESTAPI::Protocol::USERID, Obj);
 | 
				
			||||||
        auto password = GetS(RESTAPI::Protocol::PASSWORD, Obj);
 | 
					        auto password = GetS(RESTAPI::Protocol::PASSWORD, Obj);
 | 
				
			||||||
@@ -73,24 +67,25 @@ namespace OpenWifi {
 | 
				
			|||||||
            Logger_.information(Poco::format("POLICY-REQUEST(%s): Request.", Request->clientAddress().toString()));
 | 
					            Logger_.information(Poco::format("POLICY-REQUEST(%s): Request.", Request->clientAddress().toString()));
 | 
				
			||||||
            Poco::JSON::Object  Answer;
 | 
					            Poco::JSON::Object  Answer;
 | 
				
			||||||
            Answer.set(RESTAPI::Protocol::PASSWORDPATTERN, AuthService()->PasswordValidationExpression());
 | 
					            Answer.set(RESTAPI::Protocol::PASSWORDPATTERN, AuthService()->PasswordValidationExpression());
 | 
				
			||||||
            Answer.set(RESTAPI::Protocol::ACCESSPOLICY, Daemon()->GetAccessPolicy());
 | 
					            Answer.set(RESTAPI::Protocol::ACCESSPOLICY, AuthService()->GetAccessPolicy());
 | 
				
			||||||
            Answer.set(RESTAPI::Protocol::PASSWORDPOLICY, Daemon()->GetPasswordPolicy());
 | 
					            Answer.set(RESTAPI::Protocol::PASSWORDPOLICY, AuthService()->GetPasswordPolicy());
 | 
				
			||||||
            return ReturnObject(Answer);
 | 
					            return ReturnObject(Answer);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(GetBoolParameter(RESTAPI::Protocol::FORGOTPASSWORD,false)) {
 | 
					        if(GetBoolParameter(RESTAPI::Protocol::FORGOTPASSWORD,false)) {
 | 
				
			||||||
            SecurityObjects::UserInfo UInfo1;
 | 
					            SecurityObjects::UserInfo UInfo1;
 | 
				
			||||||
            auto UserExists = StorageService()->GetUserByEmail(userId,UInfo1);
 | 
					            auto UserExists = StorageService()->UserDB().GetUserByEmail(userId,UInfo1);
 | 
				
			||||||
            if(UserExists) {
 | 
					            if(UserExists) {
 | 
				
			||||||
                Logger_.information(Poco::format("FORGOTTEN-PASSWORD(%s): Request for %s", Request->clientAddress().toString(), userId));
 | 
					                Logger_.information(Poco::format("FORGOTTEN-PASSWORD(%s): Request for %s", Request->clientAddress().toString(), userId));
 | 
				
			||||||
                SecurityObjects::ActionLink NewLink;
 | 
					                SecurityObjects::ActionLink NewLink;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                NewLink.action = OpenWifi::SecurityObjects::LinkActions::FORGOT_PASSWORD;
 | 
					                NewLink.action = OpenWifi::SecurityObjects::LinkActions::FORGOT_PASSWORD;
 | 
				
			||||||
                NewLink.id = MicroService::CreateUUID();
 | 
					                NewLink.id = MicroService::CreateUUID();
 | 
				
			||||||
                NewLink.userId = UInfo1.Id;
 | 
					                NewLink.userId = UInfo1.id;
 | 
				
			||||||
                NewLink.created = std::time(nullptr);
 | 
					                NewLink.created = std::time(nullptr);
 | 
				
			||||||
                NewLink.expires = NewLink.created + (24*60*60);
 | 
					                NewLink.expires = NewLink.created + (24*60*60);
 | 
				
			||||||
                StorageService()->CreateAction(NewLink);
 | 
					                NewLink.userAction = true;
 | 
				
			||||||
 | 
					                StorageService()->ActionLinksDB().CreateAction(NewLink);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                Poco::JSON::Object ReturnObj;
 | 
					                Poco::JSON::Object ReturnObj;
 | 
				
			||||||
                SecurityObjects::UserInfoAndPolicy UInfo;
 | 
					                SecurityObjects::UserInfoAndPolicy UInfo;
 | 
				
			||||||
@@ -110,23 +105,23 @@ namespace OpenWifi {
 | 
				
			|||||||
            Logger_.information(Poco::format("RESEND-MFA-CODE(%s): Request for %s", Request->clientAddress().toString(), userId));
 | 
					            Logger_.information(Poco::format("RESEND-MFA-CODE(%s): Request for %s", Request->clientAddress().toString(), userId));
 | 
				
			||||||
            if(Obj->has("uuid")) {
 | 
					            if(Obj->has("uuid")) {
 | 
				
			||||||
                auto uuid = Obj->get("uuid").toString();
 | 
					                auto uuid = Obj->get("uuid").toString();
 | 
				
			||||||
                if(MFAServer().ResendCode(uuid))
 | 
					                if(MFAServer()->ResendCode(uuid))
 | 
				
			||||||
                    return OK();
 | 
					                    return OK();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            return UnAuthorized(RESTAPI::Errors::InvalidCredentials);
 | 
					            return UnAuthorized(RESTAPI::Errors::InvalidCredentials, BAD_MFA_TRANSACTION);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(GetBoolParameter(RESTAPI::Protocol::COMPLETEMFACHALLENGE,false)) {
 | 
					        if(GetBoolParameter(RESTAPI::Protocol::COMPLETEMFACHALLENGE,false)) {
 | 
				
			||||||
            Logger_.information(Poco::format("COMPLETE-MFA-CHALLENGE(%s): Request for %s", Request->clientAddress().toString(), userId));
 | 
					            Logger_.information(Poco::format("COMPLETE-MFA-CHALLENGE(%s): Request for %s", Request->clientAddress().toString(), userId));
 | 
				
			||||||
            if(Obj->has("uuid")) {
 | 
					            if(Obj->has("uuid")) {
 | 
				
			||||||
                SecurityObjects::UserInfoAndPolicy UInfo;
 | 
					                SecurityObjects::UserInfoAndPolicy UInfo;
 | 
				
			||||||
                if(MFAServer().CompleteMFAChallenge(Obj,UInfo)) {
 | 
					                if(MFAServer()->CompleteMFAChallenge(Obj,UInfo)) {
 | 
				
			||||||
                    Poco::JSON::Object ReturnObj;
 | 
					                    Poco::JSON::Object ReturnObj;
 | 
				
			||||||
                    UInfo.webtoken.to_json(ReturnObj);
 | 
					                    UInfo.webtoken.to_json(ReturnObj);
 | 
				
			||||||
                    return ReturnObject(ReturnObj);
 | 
					                    return ReturnObject(ReturnObj);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            return UnAuthorized(RESTAPI::Errors::InvalidCredentials);
 | 
					            return UnAuthorized(RESTAPI::Errors::InvalidCredentials, MFA_FAILURE);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        SecurityObjects::UserInfoAndPolicy UInfo;
 | 
					        SecurityObjects::UserInfoAndPolicy UInfo;
 | 
				
			||||||
@@ -135,7 +130,7 @@ namespace OpenWifi {
 | 
				
			|||||||
        if (Code==SUCCESS) {
 | 
					        if (Code==SUCCESS) {
 | 
				
			||||||
            Poco::JSON::Object ReturnObj;
 | 
					            Poco::JSON::Object ReturnObj;
 | 
				
			||||||
            if(AuthService()->RequiresMFA(UInfo)) {
 | 
					            if(AuthService()->RequiresMFA(UInfo)) {
 | 
				
			||||||
                if(MFAServer().StartMFAChallenge(UInfo, ReturnObj)) {
 | 
					                if(MFAServer()->StartMFAChallenge(UInfo, ReturnObj)) {
 | 
				
			||||||
                    return ReturnObject(ReturnObj);
 | 
					                    return ReturnObject(ReturnObj);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                Logger_.warning("MFA Seems to be broken. Please fix. Disabling MFA checking for now.");
 | 
					                Logger_.warning("MFA Seems to be broken. Please fix. Disabling MFA checking for now.");
 | 
				
			||||||
@@ -6,21 +6,20 @@
 | 
				
			|||||||
//	Arilia Wireless Inc.
 | 
					//	Arilia Wireless Inc.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef UCENTRAL_RESTAPI_OAUTH2HANDLER_H
 | 
					#pragma once
 | 
				
			||||||
#define UCENTRAL_RESTAPI_OAUTH2HANDLER_H
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "framework/MicroService.h"
 | 
					#include "framework/MicroService.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
	class RESTAPI_oauth2Handler : public RESTAPIHandler {
 | 
						class RESTAPI_oauth2_handler : public RESTAPIHandler {
 | 
				
			||||||
	  public:
 | 
						  public:
 | 
				
			||||||
	    RESTAPI_oauth2Handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, bool Internal)
 | 
						    RESTAPI_oauth2_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, uint64_t TransactionId, bool Internal)
 | 
				
			||||||
			: RESTAPIHandler(bindings, L,
 | 
								: RESTAPIHandler(bindings, L,
 | 
				
			||||||
							 std::vector<std::string>{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,
 | 
																		  Server,
 | 
				
			||||||
 | 
					                                                      TransactionId,
 | 
				
			||||||
													  Internal, false, true , RateLimit{.Interval=1000,.MaxCalls=10}) {}
 | 
																		  Internal, false, true , RateLimit{.Interval=1000,.MaxCalls=10}) {}
 | 
				
			||||||
		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 DoGet() final;
 | 
				
			||||||
@@ -29,4 +28,5 @@ namespace OpenWifi {
 | 
				
			|||||||
		void DoPut() final {};
 | 
							void DoPut() final {};
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif //UCENTRAL_RESTAPI_OAUTH2HANDLER_H
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										36
									
								
								src/RESTAPI/RESTAPI_preferences.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/RESTAPI/RESTAPI_preferences.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Created by stephane bourque on 2021-11-16.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "RESTAPI_preferences.h"
 | 
				
			||||||
 | 
					#include "StorageService.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void RESTAPI_preferences::DoGet() {
 | 
				
			||||||
 | 
					        SecurityObjects::Preferences    P;
 | 
				
			||||||
 | 
					        Poco::JSON::Object  Answer;
 | 
				
			||||||
 | 
					        StorageService()->PreferencesDB().GetPreferences(UserInfo_.userinfo.id, P);
 | 
				
			||||||
 | 
					        P.to_json(Answer);
 | 
				
			||||||
 | 
					        ReturnObject(Answer);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void RESTAPI_preferences::DoPut() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        SecurityObjects::Preferences    P;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        auto RawObject = ParseStream();
 | 
				
			||||||
 | 
					        if(!P.from_json(RawObject)) {
 | 
				
			||||||
 | 
					            return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        P.id = UserInfo_.userinfo.id;
 | 
				
			||||||
 | 
					        P.modified = std::time(nullptr);
 | 
				
			||||||
 | 
					        StorageService()->PreferencesDB().SetPreferences(P);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Poco::JSON::Object  Answer;
 | 
				
			||||||
 | 
					        P.to_json(Answer);
 | 
				
			||||||
 | 
					        ReturnObject(Answer);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										27
									
								
								src/RESTAPI/RESTAPI_preferences.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/RESTAPI/RESTAPI_preferences.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Created by stephane bourque on 2021-11-16.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "framework/MicroService.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					    class RESTAPI_preferences : public RESTAPIHandler {
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        RESTAPI_preferences(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, uint64_t TransactionId, bool Internal)
 | 
				
			||||||
 | 
					        : RESTAPIHandler(bindings, L,
 | 
				
			||||||
 | 
					                         std::vector<std::string>{
 | 
				
			||||||
 | 
					            Poco::Net::HTTPRequest::HTTP_GET,
 | 
				
			||||||
 | 
					            Poco::Net::HTTPRequest::HTTP_PUT,
 | 
				
			||||||
 | 
					            Poco::Net::HTTPRequest::HTTP_OPTIONS},
 | 
				
			||||||
 | 
					            Server,
 | 
				
			||||||
 | 
					            TransactionId,
 | 
				
			||||||
 | 
					            Internal) {}
 | 
				
			||||||
 | 
					            static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/preferences"}; };
 | 
				
			||||||
 | 
					        void DoGet() final;
 | 
				
			||||||
 | 
					        void DoPut() final;
 | 
				
			||||||
 | 
					        void DoPost() final {};
 | 
				
			||||||
 | 
					        void DoDelete() final {};
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										73
									
								
								src/RESTAPI/RESTAPI_routers.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								src/RESTAPI/RESTAPI_routers.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,73 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Created by stephane bourque on 2021-10-23.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "framework/MicroService.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "RESTAPI/RESTAPI_oauth2_handler.h"
 | 
				
			||||||
 | 
					#include "RESTAPI/RESTAPI_user_handler.h"
 | 
				
			||||||
 | 
					#include "RESTAPI/RESTAPI_users_handler.h"
 | 
				
			||||||
 | 
					#include "RESTAPI/RESTAPI_action_links.h"
 | 
				
			||||||
 | 
					#include "RESTAPI/RESTAPI_system_endpoints_handler.h"
 | 
				
			||||||
 | 
					#include "RESTAPI/RESTAPI_asset_server.h"
 | 
				
			||||||
 | 
					#include "RESTAPI/RESTAPI_avatar_handler.h"
 | 
				
			||||||
 | 
					#include "RESTAPI/RESTAPI_subavatar_handler.h"
 | 
				
			||||||
 | 
					#include "RESTAPI/RESTAPI_email_handler.h"
 | 
				
			||||||
 | 
					#include "RESTAPI/RESTAPI_sms_handler.h"
 | 
				
			||||||
 | 
					#include "RESTAPI/RESTAPI_validate_token_handler.h"
 | 
				
			||||||
 | 
					#include "RESTAPI/RESTAPI_preferences.h"
 | 
				
			||||||
 | 
					#include "RESTAPI/RESTAPI_subpreferences.h"
 | 
				
			||||||
 | 
					#include "RESTAPI/RESTAPI_suboauth2_handler.h"
 | 
				
			||||||
 | 
					#include "RESTAPI/RESTAPI_subuser_handler.h"
 | 
				
			||||||
 | 
					#include "RESTAPI/RESTAPI_subusers_handler.h"
 | 
				
			||||||
 | 
					#include "RESTAPI/RESTAPI_validate_sub_token_handler.h"
 | 
				
			||||||
 | 
					#include "RESTAPI/RESTAPI_submfa_handler.h"
 | 
				
			||||||
 | 
					#include "RESTAPI/RESTAPI_totp_handler.h"
 | 
				
			||||||
 | 
					#include "RESTAPI/RESTAPI_subtotp_handler.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Poco::Net::HTTPRequestHandler * RESTAPI_ExtRouter(const char *Path, RESTAPIHandler::BindingMap &Bindings,
 | 
				
			||||||
 | 
					                                                            Poco::Logger & L, RESTAPI_GenericServer & S, uint64_t TransactionId) {
 | 
				
			||||||
 | 
					        return RESTAPI_Router<
 | 
				
			||||||
 | 
					            RESTAPI_oauth2_handler,
 | 
				
			||||||
 | 
					            RESTAPI_users_handler,
 | 
				
			||||||
 | 
					            RESTAPI_user_handler,
 | 
				
			||||||
 | 
					            RESTAPI_system_command,
 | 
				
			||||||
 | 
					            RESTAPI_asset_server,
 | 
				
			||||||
 | 
					            RESTAPI_system_endpoints_handler,
 | 
				
			||||||
 | 
					            RESTAPI_action_links,
 | 
				
			||||||
 | 
					            RESTAPI_avatar_handler,
 | 
				
			||||||
 | 
					            RESTAPI_subavatar_handler,
 | 
				
			||||||
 | 
					            RESTAPI_email_handler,
 | 
				
			||||||
 | 
					            RESTAPI_sms_handler,
 | 
				
			||||||
 | 
					            RESTAPI_preferences,
 | 
				
			||||||
 | 
					            RESTAPI_subpreferences,
 | 
				
			||||||
 | 
					            RESTAPI_suboauth2_handler,
 | 
				
			||||||
 | 
					            RESTAPI_subuser_handler,
 | 
				
			||||||
 | 
					            RESTAPI_subusers_handler,
 | 
				
			||||||
 | 
					            RESTAPI_submfa_handler,
 | 
				
			||||||
 | 
					            RESTAPI_totp_handler,
 | 
				
			||||||
 | 
					            RESTAPI_subtotp_handler
 | 
				
			||||||
 | 
					        >(Path, Bindings, L, S,TransactionId);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Poco::Net::HTTPRequestHandler * RESTAPI_IntRouter(const char *Path, RESTAPIHandler::BindingMap &Bindings,
 | 
				
			||||||
 | 
					                                                            Poco::Logger & L, RESTAPI_GenericServer & S, uint64_t TransactionId) {
 | 
				
			||||||
 | 
					        return RESTAPI_Router_I<
 | 
				
			||||||
 | 
					            RESTAPI_users_handler,
 | 
				
			||||||
 | 
					            RESTAPI_user_handler,
 | 
				
			||||||
 | 
					            RESTAPI_subuser_handler,
 | 
				
			||||||
 | 
					            RESTAPI_subusers_handler,
 | 
				
			||||||
 | 
					            RESTAPI_system_command,
 | 
				
			||||||
 | 
					            RESTAPI_action_links,
 | 
				
			||||||
 | 
					            RESTAPI_validate_token_handler,
 | 
				
			||||||
 | 
					            RESTAPI_validate_sub_token_handler,
 | 
				
			||||||
 | 
					            RESTAPI_sms_handler,
 | 
				
			||||||
 | 
					            RESTAPI_preferences,
 | 
				
			||||||
 | 
					            RESTAPI_subpreferences,
 | 
				
			||||||
 | 
					            RESTAPI_suboauth2_handler,
 | 
				
			||||||
 | 
					            RESTAPI_submfa_handler
 | 
				
			||||||
 | 
					        >(Path, Bindings, L, S, TransactionId);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -18,7 +18,7 @@ namespace OpenWifi {
 | 
				
			|||||||
            if(SMSSender()->StartValidation(Number, UserInfo_.userinfo.email)) {
 | 
					            if(SMSSender()->StartValidation(Number, UserInfo_.userinfo.email)) {
 | 
				
			||||||
                return OK();
 | 
					                return OK();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            return BadRequest("SMS could not be sent to validate device, try later or change the phone number.");
 | 
					            return BadRequest(RESTAPI::Errors::SMSCouldNotBeSentRetry);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        std::string Code;
 | 
					        std::string Code;
 | 
				
			||||||
@@ -30,7 +30,13 @@ namespace OpenWifi {
 | 
				
			|||||||
            if(SMSSender()->CompleteValidation(Number, Code, UserInfo_.userinfo.email)) {
 | 
					            if(SMSSender()->CompleteValidation(Number, Code, UserInfo_.userinfo.email)) {
 | 
				
			||||||
                return OK();
 | 
					                return OK();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            return BadRequest("Code and number could not be validated");
 | 
					            return BadRequest(RESTAPI::Errors::SMSCouldNotValidate);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if( UserInfo_.userinfo.userRole!=SecurityObjects::ROOT &&
 | 
				
			||||||
 | 
					            UserInfo_.userinfo.userRole!=SecurityObjects::PARTNER &&
 | 
				
			||||||
 | 
					            UserInfo_.userinfo.userRole!=SecurityObjects::ADMIN) {
 | 
				
			||||||
 | 
					            return UnAuthorized(RESTAPI::Errors::InsufficientAccessRights,ACCESS_DENIED);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (Obj->has("to") &&
 | 
					        if (Obj->has("to") &&
 | 
				
			||||||
@@ -41,7 +47,7 @@ namespace OpenWifi {
 | 
				
			|||||||
            if(SMSSender()->Send(PhoneNumber, Text))
 | 
					            if(SMSSender()->Send(PhoneNumber, Text))
 | 
				
			||||||
                return OK();
 | 
					                return OK();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return InternalError("SMS Message could not be sent.");
 | 
					            return InternalError(RESTAPI::Errors::SMSCouldNotBeSentRetry);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
 | 
					        BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,20 +2,19 @@
 | 
				
			|||||||
// Created by stephane bourque on 2021-10-09.
 | 
					// Created by stephane bourque on 2021-10-09.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef OWSEC_RESTAPI_SMS_HANDLER_H
 | 
					#pragma once
 | 
				
			||||||
#define OWSEC_RESTAPI_SMS_HANDLER_H
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "framework/MicroService.h"
 | 
					#include "framework/MicroService.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
    class RESTAPI_sms_handler : public RESTAPIHandler {
 | 
					    class RESTAPI_sms_handler : public RESTAPIHandler {
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        RESTAPI_sms_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, bool Internal)
 | 
					        RESTAPI_sms_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, uint64_t TransactionId, bool Internal)
 | 
				
			||||||
        : RESTAPIHandler(bindings, L,
 | 
					        : RESTAPIHandler(bindings, L,
 | 
				
			||||||
                         std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_POST,
 | 
					                         std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_POST,
 | 
				
			||||||
                                                  Poco::Net::HTTPRequest::HTTP_OPTIONS},
 | 
					                                                  Poco::Net::HTTPRequest::HTTP_OPTIONS},
 | 
				
			||||||
                                                  Server,
 | 
					                                                  Server,
 | 
				
			||||||
 | 
					                                                  TransactionId,
 | 
				
			||||||
                                                  Internal) {}
 | 
					                                                  Internal) {}
 | 
				
			||||||
                                                  static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/sms"};}
 | 
					                                                  static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/sms"};}
 | 
				
			||||||
        void DoGet() final {};
 | 
					        void DoGet() final {};
 | 
				
			||||||
@@ -24,5 +23,3 @@ namespace OpenWifi {
 | 
				
			|||||||
        void DoPut() final {};
 | 
					        void DoPut() final {};
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif //OWSEC_RESTAPI_SMS_HANDLER_H
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										79
									
								
								src/RESTAPI/RESTAPI_subavatar_handler.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								src/RESTAPI/RESTAPI_subavatar_handler.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,79 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Created by stephane bourque on 2021-07-15.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <fstream>
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "RESTAPI_subavatar_handler.h"
 | 
				
			||||||
 | 
					#include "StorageService.h"
 | 
				
			||||||
 | 
					#include "Poco/Net/HTMLForm.h"
 | 
				
			||||||
 | 
					#include "framework/RESTAPI_protocol.h"
 | 
				
			||||||
 | 
					#include "framework/MicroService.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void SubAvatarPartHandler::handlePart(const Poco::Net::MessageHeader &Header, std::istream &Stream) {
 | 
				
			||||||
 | 
					        FileType_ = Header.get(RESTAPI::Protocol::CONTENTTYPE, RESTAPI::Protocol::UNSPECIFIED);
 | 
				
			||||||
 | 
					        if (Header.has(RESTAPI::Protocol::CONTENTDISPOSITION)) {
 | 
				
			||||||
 | 
					            std::string Disposition;
 | 
				
			||||||
 | 
					            Poco::Net::NameValueCollection Parameters;
 | 
				
			||||||
 | 
					            Poco::Net::MessageHeader::splitParameters(Header[RESTAPI::Protocol::CONTENTDISPOSITION], Disposition, Parameters);
 | 
				
			||||||
 | 
					            Name_ = Parameters.get(RESTAPI::Protocol::NAME, RESTAPI::Protocol::UNNAMED);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Poco::CountingInputStream InputStream(Stream);
 | 
				
			||||||
 | 
					        Poco::StreamCopier::copyStream(InputStream, OutputStream_);
 | 
				
			||||||
 | 
					        Length_ = OutputStream_.str().size();
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void RESTAPI_subavatar_handler::DoPost() {
 | 
				
			||||||
 | 
					        std::string Id = UserInfo_.userinfo.id;
 | 
				
			||||||
 | 
					        SecurityObjects::UserInfo UInfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::stringstream SS;
 | 
				
			||||||
 | 
					        SubAvatarPartHandler partHandler(Id, Logger_, SS);
 | 
				
			||||||
 | 
					        Poco::Net::HTMLForm form(*Request, Request->stream(), partHandler);
 | 
				
			||||||
 | 
					        Poco::JSON::Object Answer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!partHandler.Name().empty() && partHandler.Length()< MicroService::instance().ConfigGetInt("openwifi.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()));
 | 
				
			||||||
 | 
					            StorageService()->SubAvatarDB().SetAvatar(UserInfo_.userinfo.email,
 | 
				
			||||||
 | 
					                                 Id, SS.str(), partHandler.ContentType(), partHandler.Name());
 | 
				
			||||||
 | 
					            StorageService()->SubDB().SetAvatar(Id,"1");
 | 
				
			||||||
 | 
					        } 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_subavatar_handler::DoGet() {
 | 
				
			||||||
 | 
					        std::string Id = GetBinding(RESTAPI::Protocol::ID, "");
 | 
				
			||||||
 | 
					        if (Id.empty()) {
 | 
				
			||||||
 | 
					            return NotFound();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::string Type, Name, AvatarContent;
 | 
				
			||||||
 | 
					        if (!StorageService()->SubAvatarDB().GetAvatar(UserInfo_.userinfo.email, Id, AvatarContent, Type, Name)) {
 | 
				
			||||||
 | 
					            return NotFound();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return SendFileContent(AvatarContent, Type, Name);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void RESTAPI_subavatar_handler::DoDelete() {
 | 
				
			||||||
 | 
					        std::string Id = GetBinding(RESTAPI::Protocol::ID, "");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(UserInfo_.userinfo.userRole!=SecurityObjects::ROOT && Id!=UserInfo_.userinfo.id) {
 | 
				
			||||||
 | 
					            return UnAuthorized(RESTAPI::Errors::InsufficientAccessRights, ACCESS_DENIED);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!StorageService()->SubAvatarDB().DeleteAvatar(UserInfo_.userinfo.email, Id)) {
 | 
				
			||||||
 | 
					            return NotFound();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        StorageService()->SubDB().SetAvatar(Id,"");
 | 
				
			||||||
 | 
					        OK();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										51
									
								
								src/RESTAPI/RESTAPI_subavatar_handler.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/RESTAPI/RESTAPI_subavatar_handler.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Created by stephane bourque on 2021-07-15.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "framework/MicroService.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class SubAvatarPartHandler : public Poco::Net::PartHandler {
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        SubAvatarPartHandler(std::string Id, Poco::Logger &Logger, std::stringstream & ofs) :
 | 
				
			||||||
 | 
					                Id_(std::move(Id)),
 | 
				
			||||||
 | 
					                Logger_(Logger),
 | 
				
			||||||
 | 
					                OutputStream_(ofs){
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        void handlePart(const Poco::Net::MessageHeader &Header, std::istream &Stream);
 | 
				
			||||||
 | 
					        [[nodiscard]] uint64_t Length() const { return Length_; }
 | 
				
			||||||
 | 
					        [[nodiscard]] std::string &Name() { return Name_; }
 | 
				
			||||||
 | 
					        [[nodiscard]] std::string &ContentType() { return FileType_; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private:
 | 
				
			||||||
 | 
					        uint64_t        Length_ = 0;
 | 
				
			||||||
 | 
					        std::string     FileType_;
 | 
				
			||||||
 | 
					        std::string     Name_;
 | 
				
			||||||
 | 
					        std::string     Id_;
 | 
				
			||||||
 | 
					        Poco::Logger    &Logger_;
 | 
				
			||||||
 | 
					        std::stringstream &OutputStream_;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class RESTAPI_subavatar_handler : public RESTAPIHandler {
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        RESTAPI_subavatar_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, uint64_t TransactionId, bool Internal)
 | 
				
			||||||
 | 
					                : RESTAPIHandler(bindings, L,
 | 
				
			||||||
 | 
					                                 std::vector<std::string>{
 | 
				
			||||||
 | 
					                                         Poco::Net::HTTPRequest::HTTP_GET,
 | 
				
			||||||
 | 
					                                         Poco::Net::HTTPRequest::HTTP_POST,
 | 
				
			||||||
 | 
					                                         Poco::Net::HTTPRequest::HTTP_DELETE,
 | 
				
			||||||
 | 
					                                         Poco::Net::HTTPRequest::HTTP_OPTIONS},
 | 
				
			||||||
 | 
					                                         Server,
 | 
				
			||||||
 | 
					                                         TransactionId,
 | 
				
			||||||
 | 
					                                         Internal) {}
 | 
				
			||||||
 | 
					        static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/subavatar/{id}"}; };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void DoGet() final;
 | 
				
			||||||
 | 
					        void DoPost() final;
 | 
				
			||||||
 | 
					        void DoDelete() final;
 | 
				
			||||||
 | 
					        void DoPut() final {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										129
									
								
								src/RESTAPI/RESTAPI_submfa_handler.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								src/RESTAPI/RESTAPI_submfa_handler.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,129 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Created by stephane bourque on 2021-12-01.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "RESTAPI_submfa_handler.h"
 | 
				
			||||||
 | 
					#include "StorageService.h"
 | 
				
			||||||
 | 
					#include "SMSSender.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void RESTAPI_submfa_handler::DoGet() {
 | 
				
			||||||
 | 
					        SecurityObjects::UserInfo   User;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // std::cout << "submfa get " << UserInfo_.userinfo.Id << "   user:" << UserInfo_.userinfo.email << std::endl;
 | 
				
			||||||
 | 
					        if (StorageService()->SubDB().GetUserById(UserInfo_.userinfo.id,User)) {
 | 
				
			||||||
 | 
					            Poco::JSON::Object              Answer;
 | 
				
			||||||
 | 
					            SecurityObjects::SubMfaConfig   MFC;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            MFC.id = User.id;
 | 
				
			||||||
 | 
					            if(User.userTypeProprietaryInfo.mfa.enabled) {
 | 
				
			||||||
 | 
					                if(User.userTypeProprietaryInfo.mfa.method == "sms") {
 | 
				
			||||||
 | 
					                    MFC.sms = User.userTypeProprietaryInfo.mobiles[0].number;
 | 
				
			||||||
 | 
					                    MFC.type = "sms";
 | 
				
			||||||
 | 
					                } else if(User.userTypeProprietaryInfo.mfa.method == "email") {
 | 
				
			||||||
 | 
					                    MFC.email = User.email;
 | 
				
			||||||
 | 
					                    MFC.type = "email";
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                MFC.type = "disabled";
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            MFC.to_json(Answer);
 | 
				
			||||||
 | 
					            return ReturnObject(Answer);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        NotFound();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void RESTAPI_submfa_handler::DoPut() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            auto Body = ParseStream();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            SecurityObjects::SubMfaConfig MFC;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!MFC.from_json(Body)) {
 | 
				
			||||||
 | 
					                return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (MFC.type == "disabled") {
 | 
				
			||||||
 | 
					                SecurityObjects::UserInfo User;
 | 
				
			||||||
 | 
					                StorageService()->SubDB().GetUserById(UserInfo_.userinfo.id, User);
 | 
				
			||||||
 | 
					                User.userTypeProprietaryInfo.mfa.enabled = false;
 | 
				
			||||||
 | 
					                StorageService()->SubDB().UpdateUserInfo(UserInfo_.userinfo.email, UserInfo_.userinfo.id, User);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                Poco::JSON::Object Answer;
 | 
				
			||||||
 | 
					                MFC.to_json(Answer);
 | 
				
			||||||
 | 
					                return ReturnObject(Answer);
 | 
				
			||||||
 | 
					            } else if (MFC.type == "email") {
 | 
				
			||||||
 | 
					                SecurityObjects::UserInfo User;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                StorageService()->SubDB().GetUserById(UserInfo_.userinfo.id, User);
 | 
				
			||||||
 | 
					                User.userTypeProprietaryInfo.mfa.enabled = true;
 | 
				
			||||||
 | 
					                User.userTypeProprietaryInfo.mfa.method = "email";
 | 
				
			||||||
 | 
					                StorageService()->SubDB().UpdateUserInfo(UserInfo_.userinfo.email, UserInfo_.userinfo.id, User);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                MFC.sms = MFC.sms;
 | 
				
			||||||
 | 
					                MFC.type = "email";
 | 
				
			||||||
 | 
					                MFC.email = UserInfo_.userinfo.email;
 | 
				
			||||||
 | 
					                MFC.id = MicroService::instance().CreateUUID();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                Poco::JSON::Object Answer;
 | 
				
			||||||
 | 
					                MFC.to_json(Answer);
 | 
				
			||||||
 | 
					                return ReturnObject(Answer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            } else if (MFC.type == "sms") {
 | 
				
			||||||
 | 
					                if (GetBoolParameter("startValidation", false)) {
 | 
				
			||||||
 | 
					                    if (MFC.sms.empty()) {
 | 
				
			||||||
 | 
					                        return BadRequest("Missing phone number");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if (SMSSender()->StartValidation(MFC.sms, UserInfo_.userinfo.email)) {
 | 
				
			||||||
 | 
					                        return OK();
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        return InternalError("SMS could not be sent. Verify the number or try again later.");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                } else if (GetBoolParameter("completeValidation", false)) {
 | 
				
			||||||
 | 
					                    auto ChallengeCode = GetParameter("challengeCode", "");
 | 
				
			||||||
 | 
					                    if (ChallengeCode.empty()) {
 | 
				
			||||||
 | 
					                        return BadRequest("Missing 'challengeCode'");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    if (MFC.sms.empty()) {
 | 
				
			||||||
 | 
					                        return BadRequest("Missing phone number");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    if (SMSSender()->CompleteValidation(MFC.sms, ChallengeCode, UserInfo_.userinfo.email)) {
 | 
				
			||||||
 | 
					                        SecurityObjects::UserInfo User;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        StorageService()->SubDB().GetUserById(UserInfo_.userinfo.id, User);
 | 
				
			||||||
 | 
					                        User.userTypeProprietaryInfo.mfa.enabled = true;
 | 
				
			||||||
 | 
					                        User.userTypeProprietaryInfo.mfa.method = "sms";
 | 
				
			||||||
 | 
					                        SecurityObjects::MobilePhoneNumber PhoneNumber;
 | 
				
			||||||
 | 
					                        PhoneNumber.number = MFC.sms;
 | 
				
			||||||
 | 
					                        PhoneNumber.primary = true;
 | 
				
			||||||
 | 
					                        PhoneNumber.verified = true;
 | 
				
			||||||
 | 
					                        User.userTypeProprietaryInfo.mobiles.clear();
 | 
				
			||||||
 | 
					                        User.userTypeProprietaryInfo.mobiles.push_back(PhoneNumber);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        StorageService()->SubDB().UpdateUserInfo(UserInfo_.userinfo.email, UserInfo_.userinfo.id, User);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        MFC.sms = MFC.sms;
 | 
				
			||||||
 | 
					                        MFC.type = "sms";
 | 
				
			||||||
 | 
					                        MFC.email = UserInfo_.userinfo.email;
 | 
				
			||||||
 | 
					                        MFC.id = MicroService::instance().CreateUUID();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        Poco::JSON::Object Answer;
 | 
				
			||||||
 | 
					                        MFC.to_json(Answer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        return ReturnObject(Answer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        return InternalError("SMS could not be sent. Verify the number or try again later.");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } catch (const Poco::Exception &E) {
 | 
				
			||||||
 | 
					            Logger_.log(E);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										27
									
								
								src/RESTAPI/RESTAPI_submfa_handler.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/RESTAPI/RESTAPI_submfa_handler.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Created by stephane bourque on 2021-12-01.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "framework/MicroService.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					    class RESTAPI_submfa_handler : public RESTAPIHandler {
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        RESTAPI_submfa_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, uint64_t TransactionId, bool Internal)
 | 
				
			||||||
 | 
					        : RESTAPIHandler(bindings, L,
 | 
				
			||||||
 | 
					                         std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_PUT,
 | 
				
			||||||
 | 
					                                                  Poco::Net::HTTPRequest::HTTP_GET,
 | 
				
			||||||
 | 
					                                                  Poco::Net::HTTPRequest::HTTP_OPTIONS},
 | 
				
			||||||
 | 
					                                                  Server,
 | 
				
			||||||
 | 
					                                                  TransactionId,
 | 
				
			||||||
 | 
					                                                  Internal, true, false , RateLimit{.Interval=1000,.MaxCalls=10},
 | 
				
			||||||
 | 
					                                                  true) {}
 | 
				
			||||||
 | 
					                                                  static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/submfa"}; };
 | 
				
			||||||
 | 
					        void DoGet() final;
 | 
				
			||||||
 | 
					        void DoPost() final {};
 | 
				
			||||||
 | 
					        void DoDelete() final {};
 | 
				
			||||||
 | 
					        void DoPut() final ;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										153
									
								
								src/RESTAPI/RESTAPI_suboauth2_handler.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								src/RESTAPI/RESTAPI_suboauth2_handler.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,153 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Created by stephane bourque on 2021-11-30.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "RESTAPI_suboauth2_handler.h"
 | 
				
			||||||
 | 
					#include "AuthService.h"
 | 
				
			||||||
 | 
					#include "MFAServer.h"
 | 
				
			||||||
 | 
					#include "framework/RESTAPI_protocol.h"
 | 
				
			||||||
 | 
					#include "framework/MicroService.h"
 | 
				
			||||||
 | 
					#include "StorageService.h"
 | 
				
			||||||
 | 
					#include "RESTAPI/RESTAPI_db_helpers.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void RESTAPI_suboauth2_handler::DoGet() {
 | 
				
			||||||
 | 
					        bool Expired = false, Contacted = false;
 | 
				
			||||||
 | 
					        if (!IsAuthorized(Expired, Contacted, true)) {
 | 
				
			||||||
 | 
					            if(Expired)
 | 
				
			||||||
 | 
					                return UnAuthorized(RESTAPI::Errors::ExpiredToken,EXPIRED_TOKEN);
 | 
				
			||||||
 | 
					            return UnAuthorized(RESTAPI::Errors::MissingAuthenticationInformation, INVALID_TOKEN);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        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;
 | 
				
			||||||
 | 
					            SecurityObjects::UserInfo   ReturnedUser = UserInfo_.userinfo;
 | 
				
			||||||
 | 
					            Sanitize(UserInfo_, ReturnedUser);
 | 
				
			||||||
 | 
					            ReturnedUser.to_json(Me);
 | 
				
			||||||
 | 
					            return ReturnObject(Me);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        BadRequest(RESTAPI::Errors::UnrecognizedRequest);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void RESTAPI_suboauth2_handler::DoDelete() {
 | 
				
			||||||
 | 
					        bool Expired = false, Contacted = false;
 | 
				
			||||||
 | 
					        if (!IsAuthorized(Expired, Contacted, true)) {
 | 
				
			||||||
 | 
					            if(Expired)
 | 
				
			||||||
 | 
					                return UnAuthorized(RESTAPI::Errors::ExpiredToken,EXPIRED_TOKEN);
 | 
				
			||||||
 | 
					            return UnAuthorized(RESTAPI::Errors::MissingAuthenticationInformation, INVALID_TOKEN);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        auto Token = GetBinding(RESTAPI::Protocol::TOKEN, "...");
 | 
				
			||||||
 | 
					        if (Token == SessionToken_) {
 | 
				
			||||||
 | 
					            AuthService()->SubLogout(Token);
 | 
				
			||||||
 | 
					            return ReturnStatus(Poco::Net::HTTPResponse::HTTP_NO_CONTENT, true);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Logger_.information(Poco::format("BAD-LOGOUT(%s): Request for %s", Request->clientAddress().toString(), UserInfo_.userinfo.email));
 | 
				
			||||||
 | 
					        NotFound();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void RESTAPI_suboauth2_handler::DoPost() {
 | 
				
			||||||
 | 
					        auto Obj = ParseStream();
 | 
				
			||||||
 | 
					        auto userId = GetS(RESTAPI::Protocol::USERID, Obj);
 | 
				
			||||||
 | 
					        auto password = GetS(RESTAPI::Protocol::PASSWORD, Obj);
 | 
				
			||||||
 | 
					        auto newPassword = GetS(RESTAPI::Protocol::NEWPASSWORD, Obj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Poco::toLowerInPlace(userId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(GetBoolParameter(RESTAPI::Protocol::REQUIREMENTS, false)) {
 | 
				
			||||||
 | 
					            Logger_.information(Poco::format("POLICY-REQUEST(%s): Request.", Request->clientAddress().toString()));
 | 
				
			||||||
 | 
					            Poco::JSON::Object  Answer;
 | 
				
			||||||
 | 
					            Answer.set(RESTAPI::Protocol::PASSWORDPATTERN, AuthService()->SubPasswordValidationExpression());
 | 
				
			||||||
 | 
					            Answer.set(RESTAPI::Protocol::ACCESSPOLICY, AuthService()->GetSubAccessPolicy());
 | 
				
			||||||
 | 
					            Answer.set(RESTAPI::Protocol::PASSWORDPOLICY, AuthService()->GetSubPasswordPolicy());
 | 
				
			||||||
 | 
					            return ReturnObject(Answer);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(GetBoolParameter(RESTAPI::Protocol::FORGOTPASSWORD,false)) {
 | 
				
			||||||
 | 
					            SecurityObjects::UserInfo UInfo1;
 | 
				
			||||||
 | 
					            auto UserExists = StorageService()->SubDB().GetUserByEmail(userId,UInfo1);
 | 
				
			||||||
 | 
					            if(UserExists) {
 | 
				
			||||||
 | 
					                Logger_.information(Poco::format("FORGOTTEN-PASSWORD(%s): Request for %s", Request->clientAddress().toString(), userId));
 | 
				
			||||||
 | 
					                SecurityObjects::ActionLink NewLink;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                NewLink.action = OpenWifi::SecurityObjects::LinkActions::SUB_FORGOT_PASSWORD;
 | 
				
			||||||
 | 
					                NewLink.id = MicroService::CreateUUID();
 | 
				
			||||||
 | 
					                NewLink.userId = UInfo1.id;
 | 
				
			||||||
 | 
					                NewLink.created = std::time(nullptr);
 | 
				
			||||||
 | 
					                NewLink.expires = NewLink.created + (24*60*60);
 | 
				
			||||||
 | 
					                NewLink.userAction = false;
 | 
				
			||||||
 | 
					                StorageService()->ActionLinksDB().CreateAction(NewLink);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                Poco::JSON::Object ReturnObj;
 | 
				
			||||||
 | 
					                SecurityObjects::UserInfoAndPolicy UInfo;
 | 
				
			||||||
 | 
					                UInfo.webtoken.userMustChangePassword = true;
 | 
				
			||||||
 | 
					                UInfo.webtoken.to_json(ReturnObj);
 | 
				
			||||||
 | 
					                return ReturnObject(ReturnObj);
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                Poco::JSON::Object ReturnObj;
 | 
				
			||||||
 | 
					                SecurityObjects::UserInfoAndPolicy UInfo;
 | 
				
			||||||
 | 
					                UInfo.webtoken.userMustChangePassword = true;
 | 
				
			||||||
 | 
					                UInfo.webtoken.to_json(ReturnObj);
 | 
				
			||||||
 | 
					                return ReturnObject(ReturnObj);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(GetBoolParameter(RESTAPI::Protocol::RESENDMFACODE,false)) {
 | 
				
			||||||
 | 
					            Logger_.information(Poco::format("RESEND-MFA-CODE(%s): Request for %s", Request->clientAddress().toString(), userId));
 | 
				
			||||||
 | 
					            if(Obj->has("uuid")) {
 | 
				
			||||||
 | 
					                auto uuid = Obj->get("uuid").toString();
 | 
				
			||||||
 | 
					                if(MFAServer()->ResendCode(uuid))
 | 
				
			||||||
 | 
					                    return OK();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return UnAuthorized(RESTAPI::Errors::InvalidCredentials, BAD_MFA_TRANSACTION);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(GetBoolParameter(RESTAPI::Protocol::COMPLETEMFACHALLENGE,false)) {
 | 
				
			||||||
 | 
					            Logger_.information(Poco::format("COMPLETE-MFA-CHALLENGE(%s): Request for %s", Request->clientAddress().toString(), userId));
 | 
				
			||||||
 | 
					            if(Obj->has("uuid") && Obj->has("answer")) {
 | 
				
			||||||
 | 
					                SecurityObjects::UserInfoAndPolicy UInfo;
 | 
				
			||||||
 | 
					                if(MFAServer()->CompleteMFAChallenge(Obj,UInfo)) {
 | 
				
			||||||
 | 
					                    Poco::JSON::Object ReturnObj;
 | 
				
			||||||
 | 
					                    UInfo.webtoken.to_json(ReturnObj);
 | 
				
			||||||
 | 
					                    return ReturnObject(ReturnObj);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return UnAuthorized(RESTAPI::Errors::InvalidCredentials, MFA_FAILURE);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        SecurityObjects::UserInfoAndPolicy UInfo;
 | 
				
			||||||
 | 
					        bool Expired=false;
 | 
				
			||||||
 | 
					        auto Code=AuthService()->AuthorizeSub(userId, password, newPassword, UInfo, Expired);
 | 
				
			||||||
 | 
					        if (Code==SUCCESS) {
 | 
				
			||||||
 | 
					            Poco::JSON::Object ReturnObj;
 | 
				
			||||||
 | 
					            if(AuthService()->RequiresMFA(UInfo)) {
 | 
				
			||||||
 | 
					                if(MFAServer()->StartMFAChallenge(UInfo, ReturnObj)) {
 | 
				
			||||||
 | 
					                    return ReturnObject(ReturnObj);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                Logger_.warning("MFA Seems to be broken. Please fix. Disabling MFA checking for now.");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            UInfo.webtoken.to_json(ReturnObj);
 | 
				
			||||||
 | 
					            return ReturnObject(ReturnObj);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            switch(Code) {
 | 
				
			||||||
 | 
					                case INVALID_CREDENTIALS:
 | 
				
			||||||
 | 
					                    return UnAuthorized(RESTAPI::Errors::InvalidCredentials, Code);
 | 
				
			||||||
 | 
					                case PASSWORD_INVALID:
 | 
				
			||||||
 | 
					                    return UnAuthorized(RESTAPI::Errors::InvalidPassword, Code);
 | 
				
			||||||
 | 
					                case PASSWORD_ALREADY_USED:
 | 
				
			||||||
 | 
					                    return UnAuthorized(RESTAPI::Errors::PasswordRejected, Code);
 | 
				
			||||||
 | 
					                case USERNAME_PENDING_VERIFICATION:
 | 
				
			||||||
 | 
					                    return UnAuthorized(RESTAPI::Errors::UserPendingVerification, Code);
 | 
				
			||||||
 | 
					                case PASSWORD_CHANGE_REQUIRED:
 | 
				
			||||||
 | 
					                    return UnAuthorized(RESTAPI::Errors::PasswordMustBeChanged, Code);
 | 
				
			||||||
 | 
					                default:
 | 
				
			||||||
 | 
					                    return UnAuthorized(RESTAPI::Errors::InvalidCredentials); break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										27
									
								
								src/RESTAPI/RESTAPI_suboauth2_handler.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/RESTAPI/RESTAPI_suboauth2_handler.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Created by stephane bourque on 2021-11-30.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include "framework/MicroService.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					    class RESTAPI_suboauth2_handler : public RESTAPIHandler {
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        RESTAPI_suboauth2_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, uint64_t TransactionId, bool Internal)
 | 
				
			||||||
 | 
					        : RESTAPIHandler(bindings, L,
 | 
				
			||||||
 | 
					                         std::vector<std::string>{Poco::Net::HTTPRequest::HTTP_POST,
 | 
				
			||||||
 | 
					                                                  Poco::Net::HTTPRequest::HTTP_DELETE,
 | 
				
			||||||
 | 
					                                                  Poco::Net::HTTPRequest::HTTP_GET,
 | 
				
			||||||
 | 
					                                                  Poco::Net::HTTPRequest::HTTP_OPTIONS},
 | 
				
			||||||
 | 
					                                                  Server,
 | 
				
			||||||
 | 
					                                                  TransactionId,
 | 
				
			||||||
 | 
					                                                  Internal, false, false , RateLimit{.Interval=1000,.MaxCalls=10},
 | 
				
			||||||
 | 
					                                                  false) {}
 | 
				
			||||||
 | 
					                                                  static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/suboauth2/{token}","/api/v1/suboauth2"}; };
 | 
				
			||||||
 | 
					        void DoGet() final;
 | 
				
			||||||
 | 
					        void DoPost() final;
 | 
				
			||||||
 | 
					        void DoDelete() final;
 | 
				
			||||||
 | 
					        void DoPut() final {};
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										36
									
								
								src/RESTAPI/RESTAPI_subpreferences.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/RESTAPI/RESTAPI_subpreferences.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Created by stephane bourque on 2021-11-16.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "RESTAPI_subpreferences.h"
 | 
				
			||||||
 | 
					#include "StorageService.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void RESTAPI_subpreferences::DoGet() {
 | 
				
			||||||
 | 
					        SecurityObjects::Preferences    P;
 | 
				
			||||||
 | 
					        Poco::JSON::Object  Answer;
 | 
				
			||||||
 | 
					        StorageService()->SubPreferencesDB().GetPreferences(UserInfo_.userinfo.id, P);
 | 
				
			||||||
 | 
					        P.to_json(Answer);
 | 
				
			||||||
 | 
					        ReturnObject(Answer);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void RESTAPI_subpreferences::DoPut() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        SecurityObjects::Preferences    P;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        auto RawObject = ParseStream();
 | 
				
			||||||
 | 
					        if(!P.from_json(RawObject)) {
 | 
				
			||||||
 | 
					            return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        P.id = UserInfo_.userinfo.id;
 | 
				
			||||||
 | 
					        P.modified = std::time(nullptr);
 | 
				
			||||||
 | 
					        StorageService()->SubPreferencesDB().SetPreferences(P);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Poco::JSON::Object  Answer;
 | 
				
			||||||
 | 
					        P.to_json(Answer);
 | 
				
			||||||
 | 
					        ReturnObject(Answer);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										27
									
								
								src/RESTAPI/RESTAPI_subpreferences.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/RESTAPI/RESTAPI_subpreferences.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Created by stephane bourque on 2021-11-16.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "framework/MicroService.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					    class RESTAPI_subpreferences : public RESTAPIHandler {
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        RESTAPI_subpreferences(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, uint64_t TransactionId, bool Internal)
 | 
				
			||||||
 | 
					        : RESTAPIHandler(bindings, L,
 | 
				
			||||||
 | 
					                         std::vector<std::string>{
 | 
				
			||||||
 | 
					            Poco::Net::HTTPRequest::HTTP_GET,
 | 
				
			||||||
 | 
					            Poco::Net::HTTPRequest::HTTP_PUT,
 | 
				
			||||||
 | 
					            Poco::Net::HTTPRequest::HTTP_OPTIONS},
 | 
				
			||||||
 | 
					            Server,
 | 
				
			||||||
 | 
					            TransactionId,
 | 
				
			||||||
 | 
					            Internal) {}
 | 
				
			||||||
 | 
					            static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/subpreferences"}; };
 | 
				
			||||||
 | 
					        void DoGet() final;
 | 
				
			||||||
 | 
					        void DoPut() final;
 | 
				
			||||||
 | 
					        void DoPost() final {};
 | 
				
			||||||
 | 
					        void DoDelete() final {};
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										38
									
								
								src/RESTAPI/RESTAPI_subtotp_handler.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/RESTAPI/RESTAPI_subtotp_handler.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Created by stephane bourque on 2022-01-31.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "RESTAPI_subtotp_handler.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "TotpCache.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void RESTAPI_subtotp_handler::DoGet() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        auto Reset = GetBoolParameter("reset",false);
 | 
				
			||||||
 | 
					        std::string QRCode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(TotpCache()->StartValidation(UserInfo_.userinfo,true,QRCode,Reset)) {
 | 
				
			||||||
 | 
					            return SendFileContent(QRCode, "image/svg+xml","qrcode.svg");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return BadRequest(RESTAPI::Errors::InvalidCommand);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void RESTAPI_subtotp_handler::DoPut() {
 | 
				
			||||||
 | 
					        auto Value = GetParameter("value","");
 | 
				
			||||||
 | 
					        auto nextIndex = GetParameter("index",0);
 | 
				
			||||||
 | 
					        bool moreCodes=false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        uint64_t ErrorCode = 0;
 | 
				
			||||||
 | 
					        std::string ErrorText;
 | 
				
			||||||
 | 
					        if(TotpCache()->ContinueValidation(UserInfo_.userinfo,true,Value,nextIndex,moreCodes, ErrorCode, ErrorText )) {
 | 
				
			||||||
 | 
					            Poco::JSON::Object Answer;
 | 
				
			||||||
 | 
					            Answer.set("nextIndex", nextIndex);
 | 
				
			||||||
 | 
					            Answer.set("moreCodes", moreCodes);
 | 
				
			||||||
 | 
					            return ReturnObject(Answer);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return BadRequest(ErrorCode, ErrorText);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										29
									
								
								src/RESTAPI/RESTAPI_subtotp_handler.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/RESTAPI/RESTAPI_subtotp_handler.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Created by stephane bourque on 2022-01-31.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "framework/MicroService.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					    class RESTAPI_subtotp_handler : public RESTAPIHandler {
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        RESTAPI_subtotp_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, uint64_t TransactionId, bool Internal)
 | 
				
			||||||
 | 
					                : RESTAPIHandler(bindings, L,
 | 
				
			||||||
 | 
					                                 std::vector<std::string>
 | 
				
			||||||
 | 
					                                         {
 | 
				
			||||||
 | 
					                                                 Poco::Net::HTTPRequest::HTTP_GET,
 | 
				
			||||||
 | 
					                                                 Poco::Net::HTTPRequest::HTTP_PUT,
 | 
				
			||||||
 | 
					                                                 Poco::Net::HTTPRequest::HTTP_OPTIONS
 | 
				
			||||||
 | 
					                                         },
 | 
				
			||||||
 | 
					                                 Server,
 | 
				
			||||||
 | 
					                                 TransactionId,
 | 
				
			||||||
 | 
					                                 Internal) {}
 | 
				
			||||||
 | 
					        static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/subtotp"}; };
 | 
				
			||||||
 | 
					        void DoGet() final;
 | 
				
			||||||
 | 
					        void DoPost() final {};
 | 
				
			||||||
 | 
					        void DoDelete() final {};
 | 
				
			||||||
 | 
					        void DoPut() final;
 | 
				
			||||||
 | 
					    private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										259
									
								
								src/RESTAPI/RESTAPI_subuser_handler.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										259
									
								
								src/RESTAPI/RESTAPI_subuser_handler.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,259 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Created by stephane bourque on 2021-11-30.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "RESTAPI_subuser_handler.h"
 | 
				
			||||||
 | 
					#include "StorageService.h"
 | 
				
			||||||
 | 
					#include "framework/RESTAPI_errors.h"
 | 
				
			||||||
 | 
					#include "SMSSender.h"
 | 
				
			||||||
 | 
					#include "ACLProcessor.h"
 | 
				
			||||||
 | 
					#include "AuthService.h"
 | 
				
			||||||
 | 
					#include "RESTAPI/RESTAPI_db_helpers.h"
 | 
				
			||||||
 | 
					#include "MFAServer.h"
 | 
				
			||||||
 | 
					#include "TotpCache.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void RESTAPI_subuser_handler::DoGet() {
 | 
				
			||||||
 | 
					        std::string Id = GetBinding("id", "");
 | 
				
			||||||
 | 
					        if(Id.empty()) {
 | 
				
			||||||
 | 
					            return BadRequest(RESTAPI::Errors::MissingUserID);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Poco::toLowerInPlace(Id);
 | 
				
			||||||
 | 
					        std::string Arg;
 | 
				
			||||||
 | 
					        SecurityObjects::UserInfo   UInfo;
 | 
				
			||||||
 | 
					        if(HasParameter("byEmail",Arg) && Arg=="true") {
 | 
				
			||||||
 | 
					            if(!StorageService()->SubDB().GetUserByEmail(Id,UInfo)) {
 | 
				
			||||||
 | 
					                return NotFound();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else if(!StorageService()->SubDB().GetUserById(Id,UInfo)) {
 | 
				
			||||||
 | 
					            return NotFound();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Poco::JSON::Object  UserInfoObject;
 | 
				
			||||||
 | 
					        Sanitize(UserInfo_, UInfo);
 | 
				
			||||||
 | 
					        UInfo.to_json(UserInfoObject);
 | 
				
			||||||
 | 
					        ReturnObject(UserInfoObject);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void RESTAPI_subuser_handler::DoDelete() {
 | 
				
			||||||
 | 
					        std::string Id = GetBinding("id", "");
 | 
				
			||||||
 | 
					        if(Id.empty()) {
 | 
				
			||||||
 | 
					            return BadRequest(RESTAPI::Errors::MissingUserID);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        SecurityObjects::UserInfo TargetUser;
 | 
				
			||||||
 | 
					        if(!StorageService()->SubDB().GetUserById(Id,TargetUser)) {
 | 
				
			||||||
 | 
					            return NotFound();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(TargetUser.userRole != SecurityObjects::SUBSCRIBER) {
 | 
				
			||||||
 | 
					            return BadRequest(RESTAPI::Errors::InvalidUserRole);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(!ACLProcessor::Can(UserInfo_.userinfo, TargetUser,ACLProcessor::DELETE)) {
 | 
				
			||||||
 | 
					            return UnAuthorized(RESTAPI::Errors::InsufficientAccessRights, ACCESS_DENIED);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(!StorageService()->SubDB().DeleteUser(UserInfo_.userinfo.email,Id)) {
 | 
				
			||||||
 | 
					            return NotFound();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        AuthService()->DeleteSubUserFromCache(Id);
 | 
				
			||||||
 | 
					        StorageService()->SubTokenDB().RevokeAllTokens(TargetUser.email);
 | 
				
			||||||
 | 
					        StorageService()->SubPreferencesDB().DeleteRecord("id", Id);
 | 
				
			||||||
 | 
					        StorageService()->SubAvatarDB().DeleteRecord("id", Id);
 | 
				
			||||||
 | 
					        Logger_.information(Poco::format("User '%s' deleted by '%s'.",Id,UserInfo_.userinfo.email));
 | 
				
			||||||
 | 
					        OK();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void RESTAPI_subuser_handler::DoPost() {
 | 
				
			||||||
 | 
					        std::string Id = GetBinding("id", "");
 | 
				
			||||||
 | 
					        if(Id!="0") {
 | 
				
			||||||
 | 
					            return BadRequest(RESTAPI::Errors::IdMustBe0);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        SecurityObjects::UserInfo   NewUser;
 | 
				
			||||||
 | 
					        RESTAPI_utils::from_request(NewUser,*Request);
 | 
				
			||||||
 | 
					        if(NewUser.userRole == SecurityObjects::UNKNOWN || NewUser.userRole != SecurityObjects::SUBSCRIBER) {
 | 
				
			||||||
 | 
					            return BadRequest(RESTAPI::Errors::EntityMustExist);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(!ACLProcessor::Can(UserInfo_.userinfo,NewUser,ACLProcessor::CREATE)) {
 | 
				
			||||||
 | 
					            return UnAuthorized(RESTAPI::Errors::InsufficientAccessRights, ACCESS_DENIED);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Poco::toLowerInPlace(NewUser.email);
 | 
				
			||||||
 | 
					        if(!Utils::ValidEMailAddress(NewUser.email)) {
 | 
				
			||||||
 | 
					            return BadRequest(RESTAPI::Errors::InvalidEmailAddress);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(!NewUser.currentPassword.empty()) {
 | 
				
			||||||
 | 
					            if(!AuthService()->ValidateSubPassword(NewUser.currentPassword)) {
 | 
				
			||||||
 | 
					                return BadRequest(RESTAPI::Errors::InvalidPassword);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(NewUser.name.empty())
 | 
				
			||||||
 | 
					            NewUser.name = NewUser.email;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        //  You cannot enable MFA during user creation
 | 
				
			||||||
 | 
					        NewUser.userTypeProprietaryInfo.mfa.enabled = false;
 | 
				
			||||||
 | 
					        NewUser.userTypeProprietaryInfo.mfa.method = "";
 | 
				
			||||||
 | 
					        NewUser.userTypeProprietaryInfo.mobiles.clear();
 | 
				
			||||||
 | 
					        NewUser.userTypeProprietaryInfo.authenticatorSecret.clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(!StorageService()->SubDB().CreateUser(NewUser.email, NewUser)) {
 | 
				
			||||||
 | 
					            Logger_.information(Poco::format("Could not add user '%s'.",NewUser.email));
 | 
				
			||||||
 | 
					            return BadRequest(RESTAPI::Errors::RecordNotCreated);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(GetParameter("email_verification","false")=="true") {
 | 
				
			||||||
 | 
					            if(AuthService::VerifySubEmail(NewUser))
 | 
				
			||||||
 | 
					                Logger_.information(Poco::format("Verification e-mail requested for %s",NewUser.email));
 | 
				
			||||||
 | 
					            StorageService()->SubDB().UpdateUserInfo(UserInfo_.userinfo.email,NewUser.id,NewUser);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(!StorageService()->SubDB().GetUserByEmail(NewUser.email, NewUser)) {
 | 
				
			||||||
 | 
					            Logger_.information(Poco::format("User '%s' but not retrieved.",NewUser.email));
 | 
				
			||||||
 | 
					            return NotFound();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Poco::JSON::Object  UserInfoObject;
 | 
				
			||||||
 | 
					        Sanitize(UserInfo_, NewUser);
 | 
				
			||||||
 | 
					        NewUser.to_json(UserInfoObject);
 | 
				
			||||||
 | 
					        ReturnObject(UserInfoObject);
 | 
				
			||||||
 | 
					        Logger_.information(Poco::format("User '%s' has been added by '%s')",NewUser.email, UserInfo_.userinfo.email));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void RESTAPI_subuser_handler::DoPut() {
 | 
				
			||||||
 | 
					        std::string Id = GetBinding("id", "");
 | 
				
			||||||
 | 
					        if(Id.empty()) {
 | 
				
			||||||
 | 
					            return BadRequest(RESTAPI::Errors::MissingUserID);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        SecurityObjects::UserInfo   Existing;
 | 
				
			||||||
 | 
					        if(!StorageService()->SubDB().GetUserById(Id,Existing)) {
 | 
				
			||||||
 | 
					            return NotFound();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(!ACLProcessor::Can(UserInfo_.userinfo,Existing,ACLProcessor::MODIFY)) {
 | 
				
			||||||
 | 
					            return UnAuthorized("Insufficient access rights.", ACCESS_DENIED);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        SecurityObjects::UserInfo   NewUser;
 | 
				
			||||||
 | 
					        auto RawObject = ParseStream();
 | 
				
			||||||
 | 
					        if(!NewUser.from_json(RawObject)) {
 | 
				
			||||||
 | 
					            return BadRequest(RESTAPI::Errors::InvalidJSONDocument);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // some basic validations
 | 
				
			||||||
 | 
					        if(RawObject->has("userRole") &&
 | 
				
			||||||
 | 
					            (SecurityObjects::UserTypeFromString(RawObject->get("userRole").toString())==SecurityObjects::UNKNOWN ||
 | 
				
			||||||
 | 
					            SecurityObjects::UserTypeFromString(RawObject->get("userRole").toString())==SecurityObjects::SUBSCRIBER)) {
 | 
				
			||||||
 | 
					            return BadRequest(RESTAPI::Errors::InvalidUserRole);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // The only valid things to change are: changePassword, name,
 | 
				
			||||||
 | 
					        AssignIfPresent(RawObject,"name", Existing.name);
 | 
				
			||||||
 | 
					        AssignIfPresent(RawObject,"description", Existing.description);
 | 
				
			||||||
 | 
					        AssignIfPresent(RawObject,"owner", Existing.owner);
 | 
				
			||||||
 | 
					        AssignIfPresent(RawObject,"location", Existing.location);
 | 
				
			||||||
 | 
					        AssignIfPresent(RawObject,"locale", Existing.locale);
 | 
				
			||||||
 | 
					        AssignIfPresent(RawObject,"changePassword", Existing.changePassword);
 | 
				
			||||||
 | 
					        AssignIfPresent(RawObject,"suspended", Existing.suspended);
 | 
				
			||||||
 | 
					        AssignIfPresent(RawObject,"blackListed", Existing.blackListed);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(RawObject->has("userRole")) {
 | 
				
			||||||
 | 
					            auto NewRole = SecurityObjects::UserTypeFromString(RawObject->get("userRole").toString());
 | 
				
			||||||
 | 
					            if(NewRole!=Existing.userRole) {
 | 
				
			||||||
 | 
					                if(UserInfo_.userinfo.userRole!=SecurityObjects::ROOT && NewRole==SecurityObjects::ROOT) {
 | 
				
			||||||
 | 
					                    return UnAuthorized(RESTAPI::Errors::InsufficientAccessRights, ACCESS_DENIED);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                if(Id==UserInfo_.userinfo.id) {
 | 
				
			||||||
 | 
					                    return UnAuthorized(RESTAPI::Errors::InsufficientAccessRights, ACCESS_DENIED);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                Existing.userRole = NewRole;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        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};
 | 
				
			||||||
 | 
					                Existing.notes.push_back(ii);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if(RawObject->has("currentPassword")) {
 | 
				
			||||||
 | 
					            if(!AuthService()->ValidateSubPassword(RawObject->get("currentPassword").toString())) {
 | 
				
			||||||
 | 
					                return BadRequest(RESTAPI::Errors::InvalidPassword);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if(!AuthService()->SetPassword(RawObject->get("currentPassword").toString(),Existing)) {
 | 
				
			||||||
 | 
					                return BadRequest(RESTAPI::Errors::PasswordRejected);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(GetParameter("email_verification","false")=="true") {
 | 
				
			||||||
 | 
					            if(AuthService::VerifySubEmail(Existing))
 | 
				
			||||||
 | 
					                Logger_.information(Poco::format("Verification e-mail requested for %s",Existing.email));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(RawObject->has("userTypeProprietaryInfo")) {
 | 
				
			||||||
 | 
					            if(NewUser.userTypeProprietaryInfo.mfa.enabled) {
 | 
				
			||||||
 | 
					                if (!MFAMETHODS::Validate(NewUser.userTypeProprietaryInfo.mfa.method)) {
 | 
				
			||||||
 | 
					                    return BadRequest(RESTAPI::Errors::BadMFAMethod);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                bool ChangingMFA =
 | 
				
			||||||
 | 
					                        NewUser.userTypeProprietaryInfo.mfa.enabled && !Existing.userTypeProprietaryInfo.mfa.enabled;
 | 
				
			||||||
 | 
					                Existing.userTypeProprietaryInfo.mfa.enabled = NewUser.userTypeProprietaryInfo.mfa.enabled;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                auto PropInfo = RawObject->get("userTypeProprietaryInfo");
 | 
				
			||||||
 | 
					                if (ChangingMFA && NewUser.userTypeProprietaryInfo.mfa.method == MFAMETHODS::SMS) {
 | 
				
			||||||
 | 
					                    auto PInfo = PropInfo.extract<Poco::JSON::Object::Ptr>();
 | 
				
			||||||
 | 
					                    if (PInfo->isArray("mobiles")) {
 | 
				
			||||||
 | 
					                        Existing.userTypeProprietaryInfo.mobiles = NewUser.userTypeProprietaryInfo.mobiles;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    if (NewUser.userTypeProprietaryInfo.mobiles.empty() ||
 | 
				
			||||||
 | 
					                        !SMSSender()->IsNumberValid(NewUser.userTypeProprietaryInfo.mobiles[0].number,
 | 
				
			||||||
 | 
					                                                    UserInfo_.userinfo.email)) {
 | 
				
			||||||
 | 
					                        return BadRequest(RESTAPI::Errors::NeedMobileNumber);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    Existing.userTypeProprietaryInfo.authenticatorSecret.clear();
 | 
				
			||||||
 | 
					                } else if (ChangingMFA && NewUser.userTypeProprietaryInfo.mfa.method == MFAMETHODS::AUTHENTICATOR) {
 | 
				
			||||||
 | 
					                    std::string Secret;
 | 
				
			||||||
 | 
					                    Existing.userTypeProprietaryInfo.mobiles.clear();
 | 
				
			||||||
 | 
					                    if(Existing.userTypeProprietaryInfo.authenticatorSecret.empty() && TotpCache()->CompleteValidation(UserInfo_.userinfo,false,Secret)) {
 | 
				
			||||||
 | 
					                        Existing.userTypeProprietaryInfo.authenticatorSecret = Secret;
 | 
				
			||||||
 | 
					                    } else if (!Existing.userTypeProprietaryInfo.authenticatorSecret.empty()) {
 | 
				
			||||||
 | 
					                        // we allow someone to use their old secret
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        return BadRequest(RESTAPI::Errors::AuthenticatorVerificationIncomplete);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                } else if (ChangingMFA && NewUser.userTypeProprietaryInfo.mfa.method == MFAMETHODS::EMAIL) {
 | 
				
			||||||
 | 
					                    // nothing to do for email.
 | 
				
			||||||
 | 
					                    Existing.userTypeProprietaryInfo.mobiles.clear();
 | 
				
			||||||
 | 
					                    Existing.userTypeProprietaryInfo.authenticatorSecret.clear();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                Existing.userTypeProprietaryInfo.mfa.method = NewUser.userTypeProprietaryInfo.mfa.method;
 | 
				
			||||||
 | 
					                Existing.userTypeProprietaryInfo.mfa.enabled = true;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                Existing.userTypeProprietaryInfo.authenticatorSecret.clear();
 | 
				
			||||||
 | 
					                Existing.userTypeProprietaryInfo.mobiles.clear();
 | 
				
			||||||
 | 
					                Existing.userTypeProprietaryInfo.mfa.enabled = false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(StorageService()->SubDB().UpdateUserInfo(UserInfo_.userinfo.email,Id,Existing)) {
 | 
				
			||||||
 | 
					            SecurityObjects::UserInfo   NewUserInfo;
 | 
				
			||||||
 | 
					            StorageService()->SubDB().GetUserById(Id,NewUserInfo);
 | 
				
			||||||
 | 
					            Poco::JSON::Object  ModifiedObject;
 | 
				
			||||||
 | 
					            Sanitize(UserInfo_, NewUserInfo);
 | 
				
			||||||
 | 
					            NewUserInfo.to_json(ModifiedObject);
 | 
				
			||||||
 | 
					            return ReturnObject(ModifiedObject);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        BadRequest(RESTAPI::Errors::RecordNotUpdated);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										31
									
								
								src/RESTAPI/RESTAPI_subuser_handler.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/RESTAPI/RESTAPI_subuser_handler.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Created by stephane bourque on 2021-11-30.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "framework/MicroService.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					    class RESTAPI_subuser_handler : public RESTAPIHandler {
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        RESTAPI_subuser_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, uint64_t TransactionId, bool Internal)
 | 
				
			||||||
 | 
					        : RESTAPIHandler(bindings, L,
 | 
				
			||||||
 | 
					                         std::vector<std::string>
 | 
				
			||||||
 | 
					                         {Poco::Net::HTTPRequest::HTTP_POST,
 | 
				
			||||||
 | 
					                          Poco::Net::HTTPRequest::HTTP_GET,
 | 
				
			||||||
 | 
					                          Poco::Net::HTTPRequest::HTTP_PUT,
 | 
				
			||||||
 | 
					                          Poco::Net::HTTPRequest::HTTP_DELETE,
 | 
				
			||||||
 | 
					                          Poco::Net::HTTPRequest::HTTP_OPTIONS},
 | 
				
			||||||
 | 
					                          Server,
 | 
				
			||||||
 | 
					                          TransactionId,
 | 
				
			||||||
 | 
					                          Internal) {}
 | 
				
			||||||
 | 
					                          static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/subuser/{id}"}; };
 | 
				
			||||||
 | 
					        void DoGet() final;
 | 
				
			||||||
 | 
					        void DoPost() final;
 | 
				
			||||||
 | 
					        void DoDelete() final;
 | 
				
			||||||
 | 
					        void DoPut() final;
 | 
				
			||||||
 | 
					    private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										55
									
								
								src/RESTAPI/RESTAPI_subusers_handler.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								src/RESTAPI/RESTAPI_subusers_handler.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,55 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Created by stephane bourque on 2021-11-30.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "RESTAPI_subusers_handler.h"
 | 
				
			||||||
 | 
					#include "StorageService.h"
 | 
				
			||||||
 | 
					#include "framework/RESTAPI_protocol.h"
 | 
				
			||||||
 | 
					#include "framework/MicroService.h"
 | 
				
			||||||
 | 
					#include "RESTAPI/RESTAPI_db_helpers.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void RESTAPI_subusers_handler::DoGet() {
 | 
				
			||||||
 | 
					        std::vector<SecurityObjects::UserInfo> Users;
 | 
				
			||||||
 | 
					        bool IdOnly = (GetParameter("idOnly","false")=="true");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(QB_.Select.empty()) {
 | 
				
			||||||
 | 
					            Poco::JSON::Array ArrayObj;
 | 
				
			||||||
 | 
					            Poco::JSON::Object Answer;
 | 
				
			||||||
 | 
					            if (StorageService()->SubDB().GetUsers(QB_.Offset, QB_.Limit, Users)) {
 | 
				
			||||||
 | 
					                for (auto &i : Users) {
 | 
				
			||||||
 | 
					                    Poco::JSON::Object Obj;
 | 
				
			||||||
 | 
					                    if (IdOnly) {
 | 
				
			||||||
 | 
					                        ArrayObj.add(i.id);
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        Sanitize(UserInfo_, i);
 | 
				
			||||||
 | 
					                        i.to_json(Obj);
 | 
				
			||||||
 | 
					                        ArrayObj.add(Obj);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                Answer.set(RESTAPI::Protocol::USERS, ArrayObj);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return ReturnObject(Answer);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            Poco::JSON::Array ArrayObj;
 | 
				
			||||||
 | 
					            for(auto &i:SelectedRecords()) {
 | 
				
			||||||
 | 
					                SecurityObjects::UserInfo   UInfo;
 | 
				
			||||||
 | 
					                auto tI{i};
 | 
				
			||||||
 | 
					                if(StorageService()->SubDB().GetUserById(tI,UInfo)) {
 | 
				
			||||||
 | 
					                    Poco::JSON::Object Obj;
 | 
				
			||||||
 | 
					                    if (IdOnly) {
 | 
				
			||||||
 | 
					                        ArrayObj.add(UInfo.id);
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        Sanitize(UserInfo_, UInfo);
 | 
				
			||||||
 | 
					                        UInfo.to_json(Obj);
 | 
				
			||||||
 | 
					                        ArrayObj.add(Obj);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            Poco::JSON::Object RetObj;
 | 
				
			||||||
 | 
					            RetObj.set(RESTAPI::Protocol::USERS, ArrayObj);
 | 
				
			||||||
 | 
					            return ReturnObject(RetObj);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										26
									
								
								src/RESTAPI/RESTAPI_subusers_handler.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/RESTAPI/RESTAPI_subusers_handler.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Created by stephane bourque on 2021-11-30.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "framework/MicroService.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					    class RESTAPI_subusers_handler : public RESTAPIHandler {
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        RESTAPI_subusers_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, uint64_t TransactionId, bool Internal)
 | 
				
			||||||
 | 
					        : RESTAPIHandler(bindings, L,
 | 
				
			||||||
 | 
					                         std::vector<std::string>
 | 
				
			||||||
 | 
					                         {Poco::Net::HTTPRequest::HTTP_GET,
 | 
				
			||||||
 | 
					                          Poco::Net::HTTPRequest::HTTP_OPTIONS},
 | 
				
			||||||
 | 
					                          Server,
 | 
				
			||||||
 | 
					                          TransactionId,
 | 
				
			||||||
 | 
					                          Internal) {}
 | 
				
			||||||
 | 
					        static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/subusers"}; };
 | 
				
			||||||
 | 
					        void DoGet() final;
 | 
				
			||||||
 | 
					        void DoPost() final {};
 | 
				
			||||||
 | 
					        void DoDelete() final {};
 | 
				
			||||||
 | 
					        void DoPut() final {};
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@@ -2,12 +2,12 @@
 | 
				
			|||||||
// Created by stephane bourque on 2021-07-01.
 | 
					// Created by stephane bourque on 2021-07-01.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "RESTAPI_systemEndpoints_handler.h"
 | 
					#include "RESTAPI_system_endpoints_handler.h"
 | 
				
			||||||
#include "RESTObjects/RESTAPI_SecurityObjects.h"
 | 
					#include "RESTObjects/RESTAPI_SecurityObjects.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void RESTAPI_systemEndpoints_handler::DoGet() {
 | 
					    void RESTAPI_system_endpoints_handler::DoGet() {
 | 
				
			||||||
        auto Services = MicroService::instance().GetServices();
 | 
					        auto Services = MicroService::instance().GetServices();
 | 
				
			||||||
        SecurityObjects::SystemEndpointList L;
 | 
					        SecurityObjects::SystemEndpointList L;
 | 
				
			||||||
        for(const auto &i:Services) {
 | 
					        for(const auto &i:Services) {
 | 
				
			||||||
@@ -2,19 +2,19 @@
 | 
				
			|||||||
// Created by stephane bourque on 2021-07-01.
 | 
					// Created by stephane bourque on 2021-07-01.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef UCENTRALSEC_RESTAPI_SYSTEMENDPOINTS_HANDLER_H
 | 
					#pragma once
 | 
				
			||||||
#define UCENTRALSEC_RESTAPI_SYSTEMENDPOINTS_HANDLER_H
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "../framework/MicroService.h"
 | 
					#include "../framework/MicroService.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
    class RESTAPI_systemEndpoints_handler : public RESTAPIHandler {
 | 
					    class RESTAPI_system_endpoints_handler : public RESTAPIHandler {
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        RESTAPI_systemEndpoints_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, bool Internal)
 | 
					        RESTAPI_system_endpoints_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, uint64_t TransactionId, bool Internal)
 | 
				
			||||||
                : RESTAPIHandler(bindings, L,
 | 
					                : RESTAPIHandler(bindings, L,
 | 
				
			||||||
                                 std::vector<std::string>{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,
 | 
					                                                          Server,
 | 
				
			||||||
 | 
					                                                          TransactionId,
 | 
				
			||||||
                                                          Internal) {}
 | 
					                                                          Internal) {}
 | 
				
			||||||
        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 DoGet() final;
 | 
				
			||||||
@@ -23,5 +23,3 @@ namespace OpenWifi {
 | 
				
			|||||||
        void DoPut() final {};
 | 
					        void DoPut() final {};
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif //UCENTRALSEC_RESTAPI_SYSTEMENDPOINTS_HANDLER_H
 | 
					 | 
				
			||||||
							
								
								
									
										37
									
								
								src/RESTAPI/RESTAPI_totp_handler.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								src/RESTAPI/RESTAPI_totp_handler.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Created by stephane bourque on 2022-01-31.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "RESTAPI_totp_handler.h"
 | 
				
			||||||
 | 
					#include "TotpCache.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void RESTAPI_totp_handler::DoGet() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        auto Reset = GetBoolParameter("reset",false);
 | 
				
			||||||
 | 
					        std::string QRCode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(TotpCache()->StartValidation(UserInfo_.userinfo,false,QRCode,Reset)) {
 | 
				
			||||||
 | 
					            return SendFileContent(QRCode, "image/svg+xml","qrcode.svg");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return BadRequest(RESTAPI::Errors::InvalidCommand);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void RESTAPI_totp_handler::DoPut() {
 | 
				
			||||||
 | 
					        auto Value = GetParameter("value","");
 | 
				
			||||||
 | 
					        auto nextIndex = GetParameter("index",0);
 | 
				
			||||||
 | 
					        bool moreCodes=false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        uint64_t ErrorCode = 0;
 | 
				
			||||||
 | 
					        std::string ErrorText;
 | 
				
			||||||
 | 
					        if(TotpCache()->ContinueValidation(UserInfo_.userinfo,false,Value,nextIndex,moreCodes, ErrorCode, ErrorText )) {
 | 
				
			||||||
 | 
					            Poco::JSON::Object Answer;
 | 
				
			||||||
 | 
					            Answer.set("nextIndex", nextIndex);
 | 
				
			||||||
 | 
					            Answer.set("moreCodes", moreCodes);
 | 
				
			||||||
 | 
					            return ReturnObject(Answer);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return BadRequest(ErrorCode, ErrorText);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										31
									
								
								src/RESTAPI/RESTAPI_totp_handler.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/RESTAPI/RESTAPI_totp_handler.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Created by stephane bourque on 2022-01-31.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "framework/MicroService.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					    class RESTAPI_totp_handler : public RESTAPIHandler {
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        RESTAPI_totp_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, uint64_t TransactionId, bool Internal)
 | 
				
			||||||
 | 
					                : RESTAPIHandler(bindings, L,
 | 
				
			||||||
 | 
					                                 std::vector<std::string>
 | 
				
			||||||
 | 
					                                         {
 | 
				
			||||||
 | 
					                                              Poco::Net::HTTPRequest::HTTP_GET,
 | 
				
			||||||
 | 
					                                              Poco::Net::HTTPRequest::HTTP_PUT,
 | 
				
			||||||
 | 
					                                              Poco::Net::HTTPRequest::HTTP_OPTIONS
 | 
				
			||||||
 | 
					                                          },
 | 
				
			||||||
 | 
					                                 Server,
 | 
				
			||||||
 | 
					                                 TransactionId,
 | 
				
			||||||
 | 
					                                 Internal) {}
 | 
				
			||||||
 | 
					        static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/totp"}; };
 | 
				
			||||||
 | 
					        void DoGet() final;
 | 
				
			||||||
 | 
					        void DoPost() final {};
 | 
				
			||||||
 | 
					        void DoDelete() final {};
 | 
				
			||||||
 | 
					        void DoPut() final;
 | 
				
			||||||
 | 
					    private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -4,19 +4,16 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "RESTAPI_user_handler.h"
 | 
					#include "RESTAPI_user_handler.h"
 | 
				
			||||||
#include "StorageService.h"
 | 
					#include "StorageService.h"
 | 
				
			||||||
#include "Poco/JSON/Parser.h"
 | 
					 | 
				
			||||||
#include "framework/RESTAPI_errors.h"
 | 
					#include "framework/RESTAPI_errors.h"
 | 
				
			||||||
#include "SMSSender.h"
 | 
					#include "SMSSender.h"
 | 
				
			||||||
#include "ACLProcessor.h"
 | 
					#include "ACLProcessor.h"
 | 
				
			||||||
 | 
					#include "AuthService.h"
 | 
				
			||||||
 | 
					#include "RESTAPI/RESTAPI_db_helpers.h"
 | 
				
			||||||
 | 
					#include "MFAServer.h"
 | 
				
			||||||
 | 
					#include "TotpCache.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static void FilterCredentials(SecurityObjects::UserInfo & U) {
 | 
					 | 
				
			||||||
        U.currentPassword.clear();
 | 
					 | 
				
			||||||
        U.lastPasswords.clear();
 | 
					 | 
				
			||||||
        U.oauthType.clear();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void RESTAPI_user_handler::DoGet() {
 | 
					    void RESTAPI_user_handler::DoGet() {
 | 
				
			||||||
        std::string Id = GetBinding("id", "");
 | 
					        std::string Id = GetBinding("id", "");
 | 
				
			||||||
        if(Id.empty()) {
 | 
					        if(Id.empty()) {
 | 
				
			||||||
@@ -27,15 +24,19 @@ namespace OpenWifi {
 | 
				
			|||||||
        std::string Arg;
 | 
					        std::string Arg;
 | 
				
			||||||
        SecurityObjects::UserInfo   UInfo;
 | 
					        SecurityObjects::UserInfo   UInfo;
 | 
				
			||||||
        if(HasParameter("byEmail",Arg) && Arg=="true") {
 | 
					        if(HasParameter("byEmail",Arg) && Arg=="true") {
 | 
				
			||||||
            if(!StorageService()->GetUserByEmail(Id,UInfo)) {
 | 
					            if(!StorageService()->UserDB().GetUserByEmail(Id,UInfo)) {
 | 
				
			||||||
                return NotFound();
 | 
					                return NotFound();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } else if(!StorageService()->GetUserById(Id,UInfo)) {
 | 
					        } else if(!StorageService()->UserDB().GetUserById(Id,UInfo)) {
 | 
				
			||||||
            return NotFound();
 | 
					            return NotFound();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(!ACLProcessor::Can(UserInfo_.userinfo, UInfo,ACLProcessor::READ)) {
 | 
				
			||||||
 | 
					            return UnAuthorized(RESTAPI::Errors::InsufficientAccessRights, ACCESS_DENIED);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Poco::JSON::Object  UserInfoObject;
 | 
					        Poco::JSON::Object  UserInfoObject;
 | 
				
			||||||
        FilterCredentials(UInfo);
 | 
					        Sanitize(UserInfo_, UInfo);
 | 
				
			||||||
        UInfo.to_json(UserInfoObject);
 | 
					        UInfo.to_json(UserInfoObject);
 | 
				
			||||||
        ReturnObject(UserInfoObject);
 | 
					        ReturnObject(UserInfoObject);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -47,7 +48,7 @@ namespace OpenWifi {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        SecurityObjects::UserInfo UInfo;
 | 
					        SecurityObjects::UserInfo UInfo;
 | 
				
			||||||
        if(!StorageService()->GetUserById(Id,UInfo)) {
 | 
					        if(!StorageService()->UserDB().GetUserById(Id,UInfo)) {
 | 
				
			||||||
            return NotFound();
 | 
					            return NotFound();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -55,18 +56,14 @@ namespace OpenWifi {
 | 
				
			|||||||
            return UnAuthorized(RESTAPI::Errors::InsufficientAccessRights, ACCESS_DENIED);
 | 
					            return UnAuthorized(RESTAPI::Errors::InsufficientAccessRights, ACCESS_DENIED);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(!StorageService()->DeleteUser(UserInfo_.userinfo.email,Id)) {
 | 
					        if(!StorageService()->UserDB().DeleteUser(UserInfo_.userinfo.email,Id)) {
 | 
				
			||||||
            return NotFound();
 | 
					            return NotFound();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(AuthService()->DeleteUserFromCache(UInfo.email)) {
 | 
					        AuthService()->DeleteUserFromCache(Id);
 | 
				
			||||||
            // nothing to do
 | 
					        StorageService()->AvatarDB().DeleteAvatar(UserInfo_.userinfo.email,Id);
 | 
				
			||||||
        }
 | 
					        StorageService()->PreferencesDB().DeletePreferences(UserInfo_.userinfo.email,Id);
 | 
				
			||||||
 | 
					        StorageService()->UserTokenDB().RevokeAllTokens(Id);
 | 
				
			||||||
        StorageService()->DeleteAvatar(UserInfo_.userinfo.email,Id);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        Logger_.information(Poco::format("Remove all tokens for '%s'", UserInfo_.userinfo.email));
 | 
					 | 
				
			||||||
        StorageService()->RevokeAllTokens(UInfo.email);
 | 
					 | 
				
			||||||
        Logger_.information(Poco::format("User '%s' deleted by '%s'.",Id,UserInfo_.userinfo.email));
 | 
					        Logger_.information(Poco::format("User '%s' deleted by '%s'.",Id,UserInfo_.userinfo.email));
 | 
				
			||||||
        OK();
 | 
					        OK();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -79,13 +76,18 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        SecurityObjects::UserInfo   NewUser;
 | 
					        SecurityObjects::UserInfo   NewUser;
 | 
				
			||||||
        RESTAPI_utils::from_request(NewUser,*Request);
 | 
					        RESTAPI_utils::from_request(NewUser,*Request);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        if(NewUser.userRole == SecurityObjects::UNKNOWN) {
 | 
					        if(NewUser.userRole == SecurityObjects::UNKNOWN) {
 | 
				
			||||||
            return BadRequest(RESTAPI::Errors::InvalidUserRole);
 | 
					            return BadRequest(RESTAPI::Errors::InvalidUserRole);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(UserInfo_.userinfo.userRole==SecurityObjects::ROOT) {
 | 
				
			||||||
 | 
					            NewUser.owner = GetParameter("entity","");
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            NewUser.owner = UserInfo_.userinfo.owner;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(!ACLProcessor::Can(UserInfo_.userinfo,NewUser,ACLProcessor::CREATE)) {
 | 
					        if(!ACLProcessor::Can(UserInfo_.userinfo,NewUser,ACLProcessor::CREATE)) {
 | 
				
			||||||
            return UnAuthorized("Insufficient access rights.", ACCESS_DENIED);
 | 
					            return UnAuthorized(RESTAPI::Errors::InsufficientAccessRights, ACCESS_DENIED);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Poco::toLowerInPlace(NewUser.email);
 | 
					        Poco::toLowerInPlace(NewUser.email);
 | 
				
			||||||
@@ -102,7 +104,13 @@ namespace OpenWifi {
 | 
				
			|||||||
        if(NewUser.name.empty())
 | 
					        if(NewUser.name.empty())
 | 
				
			||||||
            NewUser.name = NewUser.email;
 | 
					            NewUser.name = NewUser.email;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(!StorageService()->CreateUser(NewUser.email,NewUser)) {
 | 
					        //  You cannot enable MFA during user creation
 | 
				
			||||||
 | 
					        NewUser.userTypeProprietaryInfo.mfa.enabled = false;
 | 
				
			||||||
 | 
					        NewUser.userTypeProprietaryInfo.mfa.method = "";
 | 
				
			||||||
 | 
					        NewUser.userTypeProprietaryInfo.mobiles.clear();
 | 
				
			||||||
 | 
					        NewUser.userTypeProprietaryInfo.authenticatorSecret.clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(!StorageService()->UserDB().CreateUser(NewUser.email,NewUser)) {
 | 
				
			||||||
            Logger_.information(Poco::format("Could not add user '%s'.",NewUser.email));
 | 
					            Logger_.information(Poco::format("Could not add user '%s'.",NewUser.email));
 | 
				
			||||||
            return BadRequest(RESTAPI::Errors::RecordNotCreated);
 | 
					            return BadRequest(RESTAPI::Errors::RecordNotCreated);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -110,16 +118,16 @@ namespace OpenWifi {
 | 
				
			|||||||
        if(GetParameter("email_verification","false")=="true") {
 | 
					        if(GetParameter("email_verification","false")=="true") {
 | 
				
			||||||
            if(AuthService::VerifyEmail(NewUser))
 | 
					            if(AuthService::VerifyEmail(NewUser))
 | 
				
			||||||
                Logger_.information(Poco::format("Verification e-mail requested for %s",NewUser.email));
 | 
					                Logger_.information(Poco::format("Verification e-mail requested for %s",NewUser.email));
 | 
				
			||||||
            StorageService()->UpdateUserInfo(UserInfo_.userinfo.email,NewUser.Id,NewUser);
 | 
					            StorageService()->UserDB().UpdateUserInfo(UserInfo_.userinfo.email,NewUser.id,NewUser);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(!StorageService()->GetUserByEmail(NewUser.email, NewUser)) {
 | 
					        if(!StorageService()->UserDB().GetUserByEmail(NewUser.email, NewUser)) {
 | 
				
			||||||
            Logger_.information(Poco::format("User '%s' but not retrieved.",NewUser.email));
 | 
					            Logger_.information(Poco::format("User '%s' but not retrieved.",NewUser.email));
 | 
				
			||||||
            return NotFound();
 | 
					            return NotFound();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Poco::JSON::Object  UserInfoObject;
 | 
					        Poco::JSON::Object  UserInfoObject;
 | 
				
			||||||
        FilterCredentials(NewUser);
 | 
					        Sanitize(UserInfo_, NewUser);
 | 
				
			||||||
        NewUser.to_json(UserInfoObject);
 | 
					        NewUser.to_json(UserInfoObject);
 | 
				
			||||||
        ReturnObject(UserInfoObject);
 | 
					        ReturnObject(UserInfoObject);
 | 
				
			||||||
        Logger_.information(Poco::format("User '%s' has been added by '%s')",NewUser.email, UserInfo_.userinfo.email));
 | 
					        Logger_.information(Poco::format("User '%s' has been added by '%s')",NewUser.email, UserInfo_.userinfo.email));
 | 
				
			||||||
@@ -132,7 +140,7 @@ namespace OpenWifi {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        SecurityObjects::UserInfo   Existing;
 | 
					        SecurityObjects::UserInfo   Existing;
 | 
				
			||||||
        if(!StorageService()->GetUserById(Id,Existing)) {
 | 
					        if(!StorageService()->UserDB().GetUserById(Id,Existing)) {
 | 
				
			||||||
            return NotFound();
 | 
					            return NotFound();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -151,10 +159,15 @@ namespace OpenWifi {
 | 
				
			|||||||
            return BadRequest(RESTAPI::Errors::InvalidUserRole);
 | 
					            return BadRequest(RESTAPI::Errors::InvalidUserRole);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(RawObject->has("owner")) {
 | 
				
			||||||
 | 
					            if (UserInfo_.userinfo.userRole == SecurityObjects::ROOT && Existing.owner.empty()) {
 | 
				
			||||||
 | 
					                AssignIfPresent(RawObject, "owner", Existing.owner);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // The only valid things to change are: changePassword, name,
 | 
					        // The only valid things to change are: changePassword, name,
 | 
				
			||||||
        AssignIfPresent(RawObject,"name", Existing.name);
 | 
					        AssignIfPresent(RawObject,"name", Existing.name);
 | 
				
			||||||
        AssignIfPresent(RawObject,"description", Existing.description);
 | 
					        AssignIfPresent(RawObject,"description", Existing.description);
 | 
				
			||||||
        AssignIfPresent(RawObject,"owner", Existing.owner);
 | 
					 | 
				
			||||||
        AssignIfPresent(RawObject,"location", Existing.location);
 | 
					        AssignIfPresent(RawObject,"location", Existing.location);
 | 
				
			||||||
        AssignIfPresent(RawObject,"locale", Existing.locale);
 | 
					        AssignIfPresent(RawObject,"locale", Existing.locale);
 | 
				
			||||||
        AssignIfPresent(RawObject,"changePassword", Existing.changePassword);
 | 
					        AssignIfPresent(RawObject,"changePassword", Existing.changePassword);
 | 
				
			||||||
@@ -167,7 +180,7 @@ namespace OpenWifi {
 | 
				
			|||||||
                if(UserInfo_.userinfo.userRole!=SecurityObjects::ROOT && NewRole==SecurityObjects::ROOT) {
 | 
					                if(UserInfo_.userinfo.userRole!=SecurityObjects::ROOT && NewRole==SecurityObjects::ROOT) {
 | 
				
			||||||
                    return UnAuthorized(RESTAPI::Errors::InsufficientAccessRights, ACCESS_DENIED);
 | 
					                    return UnAuthorized(RESTAPI::Errors::InsufficientAccessRights, ACCESS_DENIED);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                if(Id==UserInfo_.userinfo.Id) {
 | 
					                if(Id==UserInfo_.userinfo.id) {
 | 
				
			||||||
                    return UnAuthorized(RESTAPI::Errors::InsufficientAccessRights, ACCESS_DENIED);
 | 
					                    return UnAuthorized(RESTAPI::Errors::InsufficientAccessRights, ACCESS_DENIED);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                Existing.userRole = NewRole;
 | 
					                Existing.userRole = NewRole;
 | 
				
			||||||
@@ -197,42 +210,56 @@ namespace OpenWifi {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(RawObject->has("userTypeProprietaryInfo")) {
 | 
					        if(RawObject->has("userTypeProprietaryInfo")) {
 | 
				
			||||||
            bool ChangingMFA = NewUser.userTypeProprietaryInfo.mfa.enabled && !Existing.userTypeProprietaryInfo.mfa.enabled;
 | 
					            if(NewUser.userTypeProprietaryInfo.mfa.enabled) {
 | 
				
			||||||
 | 
					                if (!MFAMETHODS::Validate(NewUser.userTypeProprietaryInfo.mfa.method)) {
 | 
				
			||||||
 | 
					                    return BadRequest(RESTAPI::Errors::BadMFAMethod);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                bool ChangingMFA =
 | 
				
			||||||
 | 
					                        NewUser.userTypeProprietaryInfo.mfa.enabled && !Existing.userTypeProprietaryInfo.mfa.enabled;
 | 
				
			||||||
                Existing.userTypeProprietaryInfo.mfa.enabled = NewUser.userTypeProprietaryInfo.mfa.enabled;
 | 
					                Existing.userTypeProprietaryInfo.mfa.enabled = NewUser.userTypeProprietaryInfo.mfa.enabled;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                auto PropInfo = RawObject->get("userTypeProprietaryInfo");
 | 
					                auto PropInfo = RawObject->get("userTypeProprietaryInfo");
 | 
				
			||||||
 | 
					                if (ChangingMFA && NewUser.userTypeProprietaryInfo.mfa.method == MFAMETHODS::SMS) {
 | 
				
			||||||
                    auto PInfo = PropInfo.extract<Poco::JSON::Object::Ptr>();
 | 
					                    auto PInfo = PropInfo.extract<Poco::JSON::Object::Ptr>();
 | 
				
			||||||
 | 
					                    if (PInfo->isArray("mobiles")) {
 | 
				
			||||||
            if(PInfo->isArray("mobiles")) {
 | 
					 | 
				
			||||||
                        Existing.userTypeProprietaryInfo.mobiles = NewUser.userTypeProprietaryInfo.mobiles;
 | 
					                        Existing.userTypeProprietaryInfo.mobiles = NewUser.userTypeProprietaryInfo.mobiles;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					                    if (NewUser.userTypeProprietaryInfo.mobiles.empty() ||
 | 
				
			||||||
            if(ChangingMFA && !NewUser.userTypeProprietaryInfo.mobiles.empty() && !SMSSender()->IsNumberValid(NewUser.userTypeProprietaryInfo.mobiles[0].number,UserInfo_.userinfo.email)){
 | 
					                        !SMSSender()->IsNumberValid(NewUser.userTypeProprietaryInfo.mobiles[0].number,
 | 
				
			||||||
 | 
					                                                    UserInfo_.userinfo.email)) {
 | 
				
			||||||
                        return BadRequest(RESTAPI::Errors::NeedMobileNumber);
 | 
					                        return BadRequest(RESTAPI::Errors::NeedMobileNumber);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					                    Existing.userTypeProprietaryInfo.authenticatorSecret.clear();
 | 
				
			||||||
            if(NewUser.userTypeProprietaryInfo.mfa.method=="sms" && Existing.userTypeProprietaryInfo.mobiles.empty()) {
 | 
					                } else if (ChangingMFA && NewUser.userTypeProprietaryInfo.mfa.method == MFAMETHODS::AUTHENTICATOR) {
 | 
				
			||||||
                return BadRequest(RESTAPI::Errors::NeedMobileNumber);
 | 
					                    std::string Secret;
 | 
				
			||||||
 | 
					                    Existing.userTypeProprietaryInfo.mobiles.clear();
 | 
				
			||||||
 | 
					                    if(Existing.userTypeProprietaryInfo.authenticatorSecret.empty() && TotpCache()->CompleteValidation(UserInfo_.userinfo,false,Secret)) {
 | 
				
			||||||
 | 
					                        Existing.userTypeProprietaryInfo.authenticatorSecret = Secret;
 | 
				
			||||||
 | 
					                    } else if (!Existing.userTypeProprietaryInfo.authenticatorSecret.empty()) {
 | 
				
			||||||
 | 
					                        // we allow someone to use their old secret
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        return BadRequest(RESTAPI::Errors::AuthenticatorVerificationIncomplete);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					                } else if (ChangingMFA && NewUser.userTypeProprietaryInfo.mfa.method == MFAMETHODS::EMAIL) {
 | 
				
			||||||
            if(!NewUser.userTypeProprietaryInfo.mfa.method.empty()) {
 | 
					                    // nothing to do for email.
 | 
				
			||||||
                if(NewUser.userTypeProprietaryInfo.mfa.method!="email" && NewUser.userTypeProprietaryInfo.mfa.method!="sms" ) {
 | 
					                    Existing.userTypeProprietaryInfo.mobiles.clear();
 | 
				
			||||||
                    return BadRequest("Unknown MFA method");
 | 
					                    Existing.userTypeProprietaryInfo.authenticatorSecret.clear();
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                Existing.userTypeProprietaryInfo.mfa.method=NewUser.userTypeProprietaryInfo.mfa.method;
 | 
					                Existing.userTypeProprietaryInfo.mfa.method = NewUser.userTypeProprietaryInfo.mfa.method;
 | 
				
			||||||
            }
 | 
					                Existing.userTypeProprietaryInfo.mfa.enabled = true;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
            if(Existing.userTypeProprietaryInfo.mfa.enabled && Existing.userTypeProprietaryInfo.mfa.method.empty()) {
 | 
					                Existing.userTypeProprietaryInfo.authenticatorSecret.clear();
 | 
				
			||||||
                return BadRequest("Illegal MFA method");
 | 
					                Existing.userTypeProprietaryInfo.mobiles.clear();
 | 
				
			||||||
 | 
					                Existing.userTypeProprietaryInfo.mfa.enabled = false;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(StorageService()->UpdateUserInfo(UserInfo_.userinfo.email,Id,Existing)) {
 | 
					        if(StorageService()->UserDB().UpdateUserInfo(UserInfo_.userinfo.email,Id,Existing)) {
 | 
				
			||||||
            SecurityObjects::UserInfo   NewUserInfo;
 | 
					            SecurityObjects::UserInfo   NewUserInfo;
 | 
				
			||||||
            StorageService()->GetUserByEmail(UserInfo_.userinfo.email,NewUserInfo);
 | 
					            StorageService()->UserDB().GetUserByEmail(UserInfo_.userinfo.email,NewUserInfo);
 | 
				
			||||||
            Poco::JSON::Object  ModifiedObject;
 | 
					            Poco::JSON::Object  ModifiedObject;
 | 
				
			||||||
            FilterCredentials(NewUserInfo);
 | 
					            Sanitize(UserInfo_, NewUserInfo);
 | 
				
			||||||
            NewUserInfo.to_json(ModifiedObject);
 | 
					            NewUserInfo.to_json(ModifiedObject);
 | 
				
			||||||
            return ReturnObject(ModifiedObject);
 | 
					            return ReturnObject(ModifiedObject);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,15 +2,14 @@
 | 
				
			|||||||
// Created by stephane bourque on 2021-06-21.
 | 
					// Created by stephane bourque on 2021-06-21.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef UCENTRALSEC_RESTAPI_USER_HANDLER_H
 | 
					#pragma once
 | 
				
			||||||
#define UCENTRALSEC_RESTAPI_USER_HANDLER_H
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "framework/MicroService.h"
 | 
					#include "framework/MicroService.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
    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, RESTAPI_GenericServer &Server, uint64_t TransactionId, bool Internal)
 | 
				
			||||||
                : RESTAPIHandler(bindings, L,
 | 
					                : RESTAPIHandler(bindings, L,
 | 
				
			||||||
                                 std::vector<std::string>
 | 
					                                 std::vector<std::string>
 | 
				
			||||||
                                         {Poco::Net::HTTPRequest::HTTP_POST,
 | 
					                                         {Poco::Net::HTTPRequest::HTTP_POST,
 | 
				
			||||||
@@ -19,6 +18,7 @@ namespace OpenWifi {
 | 
				
			|||||||
                                          Poco::Net::HTTPRequest::HTTP_DELETE,
 | 
					                                          Poco::Net::HTTPRequest::HTTP_DELETE,
 | 
				
			||||||
                                          Poco::Net::HTTPRequest::HTTP_OPTIONS},
 | 
					                                          Poco::Net::HTTPRequest::HTTP_OPTIONS},
 | 
				
			||||||
                                          Server,
 | 
					                                          Server,
 | 
				
			||||||
 | 
					                                          TransactionId,
 | 
				
			||||||
                                          Internal) {}
 | 
					                                          Internal) {}
 | 
				
			||||||
        static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/user/{id}"}; };
 | 
					        static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/user/{id}"}; };
 | 
				
			||||||
        void DoGet() final;
 | 
					        void DoGet() final;
 | 
				
			||||||
@@ -29,6 +29,3 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif //UCENTRALSEC_RESTAPI_USER_HANDLER_H
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,6 +6,7 @@
 | 
				
			|||||||
#include "StorageService.h"
 | 
					#include "StorageService.h"
 | 
				
			||||||
#include "framework/RESTAPI_protocol.h"
 | 
					#include "framework/RESTAPI_protocol.h"
 | 
				
			||||||
#include "framework/MicroService.h"
 | 
					#include "framework/MicroService.h"
 | 
				
			||||||
 | 
					#include "RESTAPI/RESTAPI_db_helpers.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
    void RESTAPI_users_handler::DoGet() {
 | 
					    void RESTAPI_users_handler::DoGet() {
 | 
				
			||||||
@@ -15,15 +16,13 @@ namespace OpenWifi {
 | 
				
			|||||||
        if(QB_.Select.empty()) {
 | 
					        if(QB_.Select.empty()) {
 | 
				
			||||||
            Poco::JSON::Array ArrayObj;
 | 
					            Poco::JSON::Array ArrayObj;
 | 
				
			||||||
            Poco::JSON::Object Answer;
 | 
					            Poco::JSON::Object Answer;
 | 
				
			||||||
            if (StorageService()->GetUsers(QB_.Offset, QB_.Limit, Users)) {
 | 
					            if (StorageService()->UserDB().GetUsers(QB_.Offset, QB_.Limit, Users)) {
 | 
				
			||||||
                for (auto &i : Users) {
 | 
					                for (auto &i : Users) {
 | 
				
			||||||
                    Poco::JSON::Object Obj;
 | 
					                    Poco::JSON::Object Obj;
 | 
				
			||||||
                    if (IdOnly) {
 | 
					                    if (IdOnly) {
 | 
				
			||||||
                        ArrayObj.add(i.Id);
 | 
					                        ArrayObj.add(i.id);
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                        i.currentPassword.clear();
 | 
					                        Sanitize(UserInfo_, i);
 | 
				
			||||||
                        i.lastPasswords.clear();
 | 
					 | 
				
			||||||
                        i.oauthType.clear();
 | 
					 | 
				
			||||||
                        i.to_json(Obj);
 | 
					                        i.to_json(Obj);
 | 
				
			||||||
                        ArrayObj.add(Obj);
 | 
					                        ArrayObj.add(Obj);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
@@ -32,18 +31,16 @@ namespace OpenWifi {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            return ReturnObject(Answer);
 | 
					            return ReturnObject(Answer);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            Types::StringVec IDs = Utils::Split(QB_.Select);
 | 
					 | 
				
			||||||
            Poco::JSON::Array ArrayObj;
 | 
					            Poco::JSON::Array ArrayObj;
 | 
				
			||||||
            for(auto &i:IDs) {
 | 
					            for(auto &i:SelectedRecords()) {
 | 
				
			||||||
                SecurityObjects::UserInfo   UInfo;
 | 
					                SecurityObjects::UserInfo   UInfo;
 | 
				
			||||||
                if(StorageService()->GetUserById(i,UInfo)) {
 | 
					                auto tI{i};
 | 
				
			||||||
 | 
					                if(StorageService()->UserDB().GetUserById(i,UInfo)) {
 | 
				
			||||||
                    Poco::JSON::Object Obj;
 | 
					                    Poco::JSON::Object Obj;
 | 
				
			||||||
                    if (IdOnly) {
 | 
					                    if (IdOnly) {
 | 
				
			||||||
                        ArrayObj.add(UInfo.Id);
 | 
					                        ArrayObj.add(UInfo.id);
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                        UInfo.currentPassword.clear();
 | 
					                        Sanitize(UserInfo_, UInfo);
 | 
				
			||||||
                        UInfo.lastPasswords.clear();
 | 
					 | 
				
			||||||
                        UInfo.oauthType.clear();
 | 
					 | 
				
			||||||
                        UInfo.to_json(Obj);
 | 
					                        UInfo.to_json(Obj);
 | 
				
			||||||
                        ArrayObj.add(Obj);
 | 
					                        ArrayObj.add(Obj);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,20 +2,20 @@
 | 
				
			|||||||
// Created by stephane bourque on 2021-06-21.
 | 
					// Created by stephane bourque on 2021-06-21.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef UCENTRALSEC_RESTAPI_USERS_HANDLER_H
 | 
					#pragma once
 | 
				
			||||||
#define UCENTRALSEC_RESTAPI_USERS_HANDLER_H
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "framework/MicroService.h"
 | 
					#include "framework/MicroService.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
    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, RESTAPI_GenericServer &Server, uint64_t TransactionId, bool Internal)
 | 
				
			||||||
                : RESTAPIHandler(bindings, L,
 | 
					                : RESTAPIHandler(bindings, L,
 | 
				
			||||||
                                 std::vector<std::string>
 | 
					                                 std::vector<std::string>
 | 
				
			||||||
                                 {Poco::Net::HTTPRequest::HTTP_GET,
 | 
					                                 {Poco::Net::HTTPRequest::HTTP_GET,
 | 
				
			||||||
                                  Poco::Net::HTTPRequest::HTTP_OPTIONS},
 | 
					                                  Poco::Net::HTTPRequest::HTTP_OPTIONS},
 | 
				
			||||||
                                  Server,
 | 
					                                  Server,
 | 
				
			||||||
 | 
					                                  TransactionId,
 | 
				
			||||||
                                  Internal) {}
 | 
					                                  Internal) {}
 | 
				
			||||||
        static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/users"}; };
 | 
					        static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/users"}; };
 | 
				
			||||||
        void DoGet() final;
 | 
					        void DoGet() final;
 | 
				
			||||||
@@ -25,5 +25,3 @@ namespace OpenWifi {
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif //UCENTRALSEC_RESTAPI_USERS_HANDLER_H
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										26
									
								
								src/RESTAPI/RESTAPI_validate_sub_token_handler.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/RESTAPI/RESTAPI_validate_sub_token_handler.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Created by stephane bourque on 2021-11-30.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "RESTAPI_validate_sub_token_handler.h"
 | 
				
			||||||
 | 
					#include "AuthService.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					    void RESTAPI_validate_sub_token_handler::DoGet() {
 | 
				
			||||||
 | 
					        Poco::URI URI(Request->getURI());
 | 
				
			||||||
 | 
					        auto Parameters = URI.getQueryParameters();
 | 
				
			||||||
 | 
					        for(auto const &i:Parameters) {
 | 
				
			||||||
 | 
					            if (i.first == "token") {
 | 
				
			||||||
 | 
					                //  can we find this token?
 | 
				
			||||||
 | 
					                SecurityObjects::UserInfoAndPolicy SecObj;
 | 
				
			||||||
 | 
					                bool Expired = false;
 | 
				
			||||||
 | 
					                if (AuthService()->IsValidSubToken(i.second, SecObj.webtoken, SecObj.userinfo, Expired)) {
 | 
				
			||||||
 | 
					                    Poco::JSON::Object Obj;
 | 
				
			||||||
 | 
					                    SecObj.to_json(Obj);
 | 
				
			||||||
 | 
					                    return ReturnObject(Obj);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return NotFound();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										26
									
								
								src/RESTAPI/RESTAPI_validate_sub_token_handler.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/RESTAPI/RESTAPI_validate_sub_token_handler.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Created by stephane bourque on 2021-11-30.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "framework/MicroService.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					    class RESTAPI_validate_sub_token_handler : public RESTAPIHandler {
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        RESTAPI_validate_sub_token_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, uint64_t TransactionId, bool Internal)
 | 
				
			||||||
 | 
					        : RESTAPIHandler(bindings, L,
 | 
				
			||||||
 | 
					                         std::vector<std::string>
 | 
				
			||||||
 | 
					                         {Poco::Net::HTTPRequest::HTTP_GET,
 | 
				
			||||||
 | 
					                          Poco::Net::HTTPRequest::HTTP_OPTIONS},
 | 
				
			||||||
 | 
					                          Server,
 | 
				
			||||||
 | 
					                          TransactionId,
 | 
				
			||||||
 | 
					                          Internal) {};
 | 
				
			||||||
 | 
					        static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/validateSubToken"}; };
 | 
				
			||||||
 | 
					        void DoGet() final;
 | 
				
			||||||
 | 
					        void DoPost() final {};
 | 
				
			||||||
 | 
					        void DoDelete() final {};
 | 
				
			||||||
 | 
					        void DoPut() final {};
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -2,11 +2,11 @@
 | 
				
			|||||||
// Created by stephane bourque on 2021-07-01.
 | 
					// Created by stephane bourque on 2021-07-01.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "RESTAPI_validateToken_handler.h"
 | 
					#include "RESTAPI_validate_token_handler.h"
 | 
				
			||||||
#include "AuthService.h"
 | 
					#include "AuthService.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
    void RESTAPI_validateToken_handler::DoGet() {
 | 
					    void RESTAPI_validate_token_handler::DoGet() {
 | 
				
			||||||
        Poco::URI URI(Request->getURI());
 | 
					        Poco::URI URI(Request->getURI());
 | 
				
			||||||
        auto Parameters = URI.getQueryParameters();
 | 
					        auto Parameters = URI.getQueryParameters();
 | 
				
			||||||
        for(auto const &i:Parameters) {
 | 
					        for(auto const &i:Parameters) {
 | 
				
			||||||
@@ -2,20 +2,20 @@
 | 
				
			|||||||
// Created by stephane bourque on 2021-07-01.
 | 
					// Created by stephane bourque on 2021-07-01.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef UCENTRALSEC_RESTAPI_VALIDATETOKEN_HANDLER_H
 | 
					#pragma once
 | 
				
			||||||
#define UCENTRALSEC_RESTAPI_VALIDATETOKEN_HANDLER_H
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "framework/MicroService.h"
 | 
					#include "framework/MicroService.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
    class RESTAPI_validateToken_handler : public RESTAPIHandler {
 | 
					    class RESTAPI_validate_token_handler : public RESTAPIHandler {
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        RESTAPI_validateToken_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, bool Internal)
 | 
					        RESTAPI_validate_token_handler(const RESTAPIHandler::BindingMap &bindings, Poco::Logger &L, RESTAPI_GenericServer &Server, uint64_t TransactionId, bool Internal)
 | 
				
			||||||
                : RESTAPIHandler(bindings, L,
 | 
					                : RESTAPIHandler(bindings, L,
 | 
				
			||||||
                                 std::vector<std::string>
 | 
					                                 std::vector<std::string>
 | 
				
			||||||
                                         {Poco::Net::HTTPRequest::HTTP_GET,
 | 
					                                         {Poco::Net::HTTPRequest::HTTP_GET,
 | 
				
			||||||
                                          Poco::Net::HTTPRequest::HTTP_OPTIONS},
 | 
					                                          Poco::Net::HTTPRequest::HTTP_OPTIONS},
 | 
				
			||||||
                                          Server,
 | 
					                                          Server,
 | 
				
			||||||
 | 
					                                          TransactionId,
 | 
				
			||||||
                                          Internal) {};
 | 
					                                          Internal) {};
 | 
				
			||||||
        static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/validateToken"}; };
 | 
					        static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/validateToken"}; };
 | 
				
			||||||
        void DoGet() final;
 | 
					        void DoGet() final;
 | 
				
			||||||
@@ -25,4 +25,3 @@ namespace OpenWifi {
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif //UCENTRALSEC_RESTAPI_VALIDATETOKEN_HANDLER_H
 | 
					 | 
				
			||||||
							
								
								
									
										178
									
								
								src/RESTObjects/RESTAPI_CertObjects.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								src/RESTObjects/RESTAPI_CertObjects.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,178 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Created by stephane bourque on 2021-12-07.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "RESTAPI_CertObjects.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using OpenWifi::RESTAPI_utils::field_to_json;
 | 
				
			||||||
 | 
					using OpenWifi::RESTAPI_utils::field_from_json;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					    namespace  CertObjects {
 | 
				
			||||||
 | 
					        void CertificateEntry::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
 | 
					            field_to_json(Obj,"id", id);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"entity", entity);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"creator", creator);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"type", type);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"status", status);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"certificate", certificate);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"key", key);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"devid", devid);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"cas", cas);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"manufacturer", manufacturer);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"model", model);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"redirector", redirector);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"commonName", commonName);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"certificateId", certificateId);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"batch", batch);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"created", created);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"modified", modified);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"revoked", revoked);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"revokeCount", revokeCount);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        bool CertificateEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
					            try {
 | 
				
			||||||
 | 
					                field_from_json(Obj,"id", id);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"entity", entity);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"creator", creator);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"type", type);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"status", status);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"certificate", certificate);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"key", key);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"devid", devid);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"cas", cas);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"manufacturer", manufacturer);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"model", model);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"redirector", redirector);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"commonName", commonName);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"certificateId", certificateId);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"batch", batch);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"created", created);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"modified", modified);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"revoked", revoked);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"revokeCount", revokeCount);
 | 
				
			||||||
 | 
					                return true;
 | 
				
			||||||
 | 
					            } catch (...) {
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void EntityEntry::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
 | 
					            field_to_json(Obj,"id", id);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"creator", creator);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"name", name);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"description", description);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"defaultRedirector", defaultRedirector);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"apiKey", apiKey);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"serverEnrollmentProfile", serverEnrollmentProfile);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"clientEnrollmentProfile", clientEnrollmentProfile);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"organization", organization);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"created", created);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"modified", modified);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"suspended", suspended);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"deleted", deleted);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"notes", notes);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        bool EntityEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
					            try {
 | 
				
			||||||
 | 
					                field_from_json(Obj,"id", id);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"creator", creator);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"name", name);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"description", description);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"defaultRedirector", defaultRedirector);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"apiKey", apiKey);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"serverEnrollmentProfile", serverEnrollmentProfile);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"clientEnrollmentProfile", clientEnrollmentProfile);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"organization", organization);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"created", created);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"modified", modified);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"suspended", suspended);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"deleted", deleted);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"notes", notes);
 | 
				
			||||||
 | 
					                return true;
 | 
				
			||||||
 | 
					            } catch (...) {
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void BatchEntry::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
 | 
					            field_to_json(Obj,"id", id);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"entity", entity);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"creator", creator);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"name", name);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"description", description);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"manufacturer", manufacturer);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"model", model);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"redirector", redirector);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"commonNames", commonNames);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"jobHistory", jobHistory);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"notes", notes);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"submitted", submitted);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"started", started);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"completed", completed);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"modified", modified);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        bool BatchEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
					            try {
 | 
				
			||||||
 | 
					                field_from_json(Obj,"id", id);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"entity", entity);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"creator", creator);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"name", name);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"description", description);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"manufacturer", manufacturer);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"model", model);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"redirector", redirector);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"commonNames", commonNames);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"jobHistory", jobHistory);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"notes", notes);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"submitted", submitted);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"started", started);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"completed", completed);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"modified", modified);
 | 
				
			||||||
 | 
					                return true;
 | 
				
			||||||
 | 
					            } catch (...) {
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void JobEntry::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
 | 
					            field_to_json(Obj,"id", id);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"entity", entity);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"creator", creator);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"batch", batch);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"commonNames", commonNames);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"completedNames", completedNames);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"errorNames", errorNames);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"status", status);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"command", command);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"parameters", parameters);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"submitted", submitted);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"started", started);
 | 
				
			||||||
 | 
					            field_to_json(Obj,"completed", completed);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        bool JobEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
					            try {
 | 
				
			||||||
 | 
					                field_from_json(Obj,"id", id);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"entity", entity);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"creator", creator);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"batch", batch);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"commonNames", commonNames);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"completedNames", completedNames);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"errorNames", errorNames);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"status", status);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"command", command);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"parameters", parameters);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"submitted", submitted);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"started", started);
 | 
				
			||||||
 | 
					                field_from_json(Obj,"completed", completed);
 | 
				
			||||||
 | 
					                return true;
 | 
				
			||||||
 | 
					            } catch (...) {
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										101
									
								
								src/RESTObjects/RESTAPI_CertObjects.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								src/RESTObjects/RESTAPI_CertObjects.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,101 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Created by stephane bourque on 2021-12-07.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					#include "framework/MicroService.h"
 | 
				
			||||||
 | 
					#include "framework/OpenWifiTypes.h"
 | 
				
			||||||
 | 
					#include "RESTObjects/RESTAPI_SecurityObjects.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    namespace CertObjects {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        struct CertificateEntry {
 | 
				
			||||||
 | 
					            OpenWifi::Types::UUID_t         id;
 | 
				
			||||||
 | 
					            OpenWifi::Types::UUID_t         entity;
 | 
				
			||||||
 | 
					            OpenWifi::Types::UUID_t         creator;
 | 
				
			||||||
 | 
					            std::string                     type;
 | 
				
			||||||
 | 
					            std::string                     status;
 | 
				
			||||||
 | 
					            std::string                     certificate;
 | 
				
			||||||
 | 
					            std::string                     key;
 | 
				
			||||||
 | 
					            std::string                     devid;
 | 
				
			||||||
 | 
					            std::string                     cas;
 | 
				
			||||||
 | 
					            std::string                     manufacturer;
 | 
				
			||||||
 | 
					            std::string                     model;
 | 
				
			||||||
 | 
					            std::string                     redirector;
 | 
				
			||||||
 | 
					            std::string                     commonName;
 | 
				
			||||||
 | 
					            std::string                     certificateId;
 | 
				
			||||||
 | 
					            OpenWifi::Types::UUID_t         batch;
 | 
				
			||||||
 | 
					            uint64_t                        created = 0;
 | 
				
			||||||
 | 
					            uint64_t                        modified = 0;
 | 
				
			||||||
 | 
					            uint64_t                        revoked = 0;
 | 
				
			||||||
 | 
					            uint64_t                        revokeCount = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
 | 
					            bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        struct EntityEntry {
 | 
				
			||||||
 | 
					            OpenWifi::Types::UUID_t         id;
 | 
				
			||||||
 | 
					            OpenWifi::Types::UUID_t         creator;
 | 
				
			||||||
 | 
					            std::string                     name;
 | 
				
			||||||
 | 
					            std::string                     description;
 | 
				
			||||||
 | 
					            std::string                     defaultRedirector;
 | 
				
			||||||
 | 
					            std::string                     apiKey;
 | 
				
			||||||
 | 
					            std::string                     serverEnrollmentProfile;
 | 
				
			||||||
 | 
					            std::string                     clientEnrollmentProfile;
 | 
				
			||||||
 | 
					            std::string                     organization;
 | 
				
			||||||
 | 
					            SecurityObjects::NoteInfoVec    notes;
 | 
				
			||||||
 | 
					            bool                            suspended=false;
 | 
				
			||||||
 | 
					            bool                            deleted=false;
 | 
				
			||||||
 | 
					            uint64_t                        created = 0 ;
 | 
				
			||||||
 | 
					            uint64_t                        modified = 0 ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
 | 
					            bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        struct BatchEntry {
 | 
				
			||||||
 | 
					            OpenWifi::Types::UUID_t         id;
 | 
				
			||||||
 | 
					            OpenWifi::Types::UUID_t         entity;
 | 
				
			||||||
 | 
					            OpenWifi::Types::UUID_t         creator;
 | 
				
			||||||
 | 
					            std::string                     name;
 | 
				
			||||||
 | 
					            std::string                     description;
 | 
				
			||||||
 | 
					            std::string                     manufacturer;
 | 
				
			||||||
 | 
					            std::string                     model;
 | 
				
			||||||
 | 
					            std::string                     redirector;
 | 
				
			||||||
 | 
					            std::vector<std::string>        commonNames;
 | 
				
			||||||
 | 
					            std::vector<std::string>        jobHistory;
 | 
				
			||||||
 | 
					            SecurityObjects::NoteInfoVec    notes;
 | 
				
			||||||
 | 
					            uint64_t                        submitted = 0 ;
 | 
				
			||||||
 | 
					            uint64_t                        started = 0 ;
 | 
				
			||||||
 | 
					            uint64_t                        completed = 0 ;
 | 
				
			||||||
 | 
					            uint64_t                        modified = 0 ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
 | 
					            bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        struct JobEntry {
 | 
				
			||||||
 | 
					            OpenWifi::Types::UUID_t         id;
 | 
				
			||||||
 | 
					            OpenWifi::Types::UUID_t         entity;
 | 
				
			||||||
 | 
					            OpenWifi::Types::UUID_t         creator;
 | 
				
			||||||
 | 
					            OpenWifi::Types::UUID_t         batch;
 | 
				
			||||||
 | 
					            std::string                     command;
 | 
				
			||||||
 | 
					            OpenWifi::Types::StringVec      commonNames;
 | 
				
			||||||
 | 
					            OpenWifi::Types::StringVec      completedNames;
 | 
				
			||||||
 | 
					            OpenWifi::Types::StringVec      errorNames;
 | 
				
			||||||
 | 
					            Types::StringPairVec            parameters;
 | 
				
			||||||
 | 
					            std::string                     status;
 | 
				
			||||||
 | 
					            uint64_t                        submitted=0;
 | 
				
			||||||
 | 
					            uint64_t                        started=0;
 | 
				
			||||||
 | 
					            uint64_t                        completed=0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
 | 
					            bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -29,7 +29,7 @@ namespace OpenWifi::FMSObjects {
 | 
				
			|||||||
        std::string     location;
 | 
					        std::string     location;
 | 
				
			||||||
        std::string     uploader;
 | 
					        std::string     uploader;
 | 
				
			||||||
        std::string     digest;
 | 
					        std::string     digest;
 | 
				
			||||||
        bool            latest=false;
 | 
					        bool            latest=0;
 | 
				
			||||||
        SecurityObjects::NoteInfoVec    notes;
 | 
					        SecurityObjects::NoteInfoVec    notes;
 | 
				
			||||||
        uint64_t        created=0;
 | 
					        uint64_t        created=0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,6 +12,7 @@
 | 
				
			|||||||
#include "Daemon.h"
 | 
					#include "Daemon.h"
 | 
				
			||||||
#ifdef	TIP_GATEWAY_SERVICE
 | 
					#ifdef	TIP_GATEWAY_SERVICE
 | 
				
			||||||
#include "DeviceRegistry.h"
 | 
					#include "DeviceRegistry.h"
 | 
				
			||||||
 | 
					#include "CapabilitiesCache.h"
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "RESTAPI_GWobjects.h"
 | 
					#include "RESTAPI_GWobjects.h"
 | 
				
			||||||
@@ -26,7 +27,7 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
	void Device::to_json(Poco::JSON::Object &Obj) const {
 | 
						void Device::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
		field_to_json(Obj,"serialNumber", SerialNumber);
 | 
							field_to_json(Obj,"serialNumber", SerialNumber);
 | 
				
			||||||
#ifdef TIP_GATEWAY_SERVICE
 | 
					#ifdef TIP_GATEWAY_SERVICE
 | 
				
			||||||
		field_to_json(Obj,"deviceType", Daemon::instance()->IdentifyDevice(Compatible));
 | 
							field_to_json(Obj,"deviceType", CapabilitiesCache::instance()->Get(Compatible));
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
		field_to_json(Obj,"macAddress", MACAddress);
 | 
							field_to_json(Obj,"macAddress", MACAddress);
 | 
				
			||||||
		field_to_json(Obj,"manufacturer", Manufacturer);
 | 
							field_to_json(Obj,"manufacturer", Manufacturer);
 | 
				
			||||||
@@ -145,6 +146,7 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
		field_to_json(Obj,"custom", Custom);
 | 
							field_to_json(Obj,"custom", Custom);
 | 
				
			||||||
		field_to_json(Obj,"waitingForFile", WaitingForFile);
 | 
							field_to_json(Obj,"waitingForFile", WaitingForFile);
 | 
				
			||||||
		field_to_json(Obj,"attachFile", AttachDate);
 | 
							field_to_json(Obj,"attachFile", AttachDate);
 | 
				
			||||||
 | 
							field_to_json(Obj,"executionTime", executionTime);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool DefaultConfiguration::from_json(Poco::JSON::Object::Ptr &Obj) {
 | 
						bool DefaultConfiguration::from_json(Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
@@ -179,7 +181,6 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void ConnectionState::to_json(Poco::JSON::Object &Obj) const {
 | 
						void ConnectionState::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
		field_to_json(Obj,"serialNumber", SerialNumber);
 | 
					 | 
				
			||||||
		field_to_json(Obj,"ipAddress", Address);
 | 
							field_to_json(Obj,"ipAddress", Address);
 | 
				
			||||||
		field_to_json(Obj,"txBytes", TX);
 | 
							field_to_json(Obj,"txBytes", TX);
 | 
				
			||||||
		field_to_json(Obj,"rxBytes", RX);
 | 
							field_to_json(Obj,"rxBytes", RX);
 | 
				
			||||||
@@ -190,6 +191,10 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
		field_to_json(Obj,"lastContact", LastContact);
 | 
							field_to_json(Obj,"lastContact", LastContact);
 | 
				
			||||||
		field_to_json(Obj,"associations_2G", Associations_2G);
 | 
							field_to_json(Obj,"associations_2G", Associations_2G);
 | 
				
			||||||
		field_to_json(Obj,"associations_5G", Associations_5G);
 | 
							field_to_json(Obj,"associations_5G", Associations_5G);
 | 
				
			||||||
 | 
							field_to_json(Obj,"webSocketClients", webSocketClients);
 | 
				
			||||||
 | 
							field_to_json(Obj,"websocketPackets", websocketPackets);
 | 
				
			||||||
 | 
							field_to_json(Obj,"kafkaClients", kafkaClients);
 | 
				
			||||||
 | 
							field_to_json(Obj,"kafkaPackets", kafkaPackets);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		switch(VerifiedCertificate) {
 | 
							switch(VerifiedCertificate) {
 | 
				
			||||||
			case NO_CERTIFICATE:
 | 
								case NO_CERTIFICATE:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,8 +6,7 @@
 | 
				
			|||||||
//	Arilia Wireless Inc.
 | 
					//	Arilia Wireless Inc.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef UCENTRAL_RESTAPI_OBJECTS_H
 | 
					#pragma once
 | 
				
			||||||
#define UCENTRAL_RESTAPI_OBJECTS_H
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "Poco/JSON/Object.h"
 | 
					#include "Poco/JSON/Object.h"
 | 
				
			||||||
#include "RESTAPI_SecurityObjects.h"
 | 
					#include "RESTAPI_SecurityObjects.h"
 | 
				
			||||||
@@ -23,7 +22,6 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	struct ConnectionState {
 | 
						struct ConnectionState {
 | 
				
			||||||
		uint64_t MessageCount = 0 ;
 | 
							uint64_t MessageCount = 0 ;
 | 
				
			||||||
		std::string SerialNumber;
 | 
					 | 
				
			||||||
		std::string Address;
 | 
							std::string Address;
 | 
				
			||||||
		uint64_t UUID = 0 ;
 | 
							uint64_t UUID = 0 ;
 | 
				
			||||||
		uint64_t PendingUUID = 0 ;
 | 
							uint64_t PendingUUID = 0 ;
 | 
				
			||||||
@@ -35,6 +33,10 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
		std::string Firmware;
 | 
							std::string Firmware;
 | 
				
			||||||
		CertificateValidation VerifiedCertificate = NO_CERTIFICATE;
 | 
							CertificateValidation VerifiedCertificate = NO_CERTIFICATE;
 | 
				
			||||||
		std::string Compatible;
 | 
							std::string Compatible;
 | 
				
			||||||
 | 
							uint64_t 	kafkaClients=0;
 | 
				
			||||||
 | 
							uint64_t 	webSocketClients=0;
 | 
				
			||||||
 | 
							uint64_t 	kafkaPackets=0;
 | 
				
			||||||
 | 
							uint64_t 	websocketPackets=0;
 | 
				
			||||||
		void to_json(Poco::JSON::Object &Obj) const;
 | 
							void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -50,11 +52,11 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
		std::string Firmware;
 | 
							std::string Firmware;
 | 
				
			||||||
		std::string Compatible;
 | 
							std::string Compatible;
 | 
				
			||||||
		std::string FWUpdatePolicy;
 | 
							std::string FWUpdatePolicy;
 | 
				
			||||||
		uint64_t UUID;
 | 
							uint64_t UUID = 0 ;
 | 
				
			||||||
		uint64_t CreationTimestamp;
 | 
							uint64_t CreationTimestamp = 0 ;
 | 
				
			||||||
		uint64_t LastConfigurationChange;
 | 
							uint64_t LastConfigurationChange = 0 ;
 | 
				
			||||||
		uint64_t LastConfigurationDownload;
 | 
							uint64_t LastConfigurationDownload = 0 ;
 | 
				
			||||||
		uint64_t LastFWUpdate;
 | 
							uint64_t LastFWUpdate = 0 ;
 | 
				
			||||||
		std::string Venue;
 | 
							std::string Venue;
 | 
				
			||||||
		std::string DevicePassword;
 | 
							std::string DevicePassword;
 | 
				
			||||||
		void to_json(Poco::JSON::Object &Obj) const;
 | 
							void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
@@ -65,25 +67,25 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	struct Statistics {
 | 
						struct Statistics {
 | 
				
			||||||
		std::string SerialNumber;
 | 
							std::string SerialNumber;
 | 
				
			||||||
		uint64_t 	UUID;
 | 
							uint64_t 	UUID = 0 ;
 | 
				
			||||||
		std::string Data;
 | 
							std::string Data;
 | 
				
			||||||
		uint64_t 	Recorded;
 | 
							uint64_t 	Recorded = 0;
 | 
				
			||||||
		void to_json(Poco::JSON::Object &Obj) const;
 | 
							void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct HealthCheck {
 | 
						struct HealthCheck {
 | 
				
			||||||
		std::string SerialNumber;
 | 
							std::string SerialNumber;
 | 
				
			||||||
		uint64_t 	UUID;
 | 
							uint64_t 	UUID = 0 ;
 | 
				
			||||||
		std::string Data;
 | 
							std::string Data;
 | 
				
			||||||
		uint64_t 	Recorded;
 | 
							uint64_t 	Recorded = 0 ;
 | 
				
			||||||
		uint64_t 	Sanity;
 | 
							uint64_t 	Sanity = 0 ;
 | 
				
			||||||
		void to_json(Poco::JSON::Object &Obj) const;
 | 
							void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct Capabilities {
 | 
						struct Capabilities {
 | 
				
			||||||
		std::string Capabilities;
 | 
							std::string Capabilities;
 | 
				
			||||||
		uint64_t 	FirstUpdate;
 | 
							uint64_t 	FirstUpdate = 0 ;
 | 
				
			||||||
		uint64_t 	LastUpdate;
 | 
							uint64_t 	LastUpdate = 0 ;
 | 
				
			||||||
		void 		to_json(Poco::JSON::Object &Obj) const;
 | 
							void 		to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -101,17 +103,17 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
		std::string SerialNumber;
 | 
							std::string SerialNumber;
 | 
				
			||||||
		std::string Log;
 | 
							std::string Log;
 | 
				
			||||||
		std::string Data;
 | 
							std::string Data;
 | 
				
			||||||
		uint64_t 	Severity;
 | 
							uint64_t 	Severity = 0 ;
 | 
				
			||||||
		uint64_t 	Recorded;
 | 
							uint64_t 	Recorded = 0 ;
 | 
				
			||||||
		uint64_t 	LogType;
 | 
							uint64_t 	LogType = 0 ;
 | 
				
			||||||
		uint64_t 	UUID;
 | 
							uint64_t 	UUID = 0 ;
 | 
				
			||||||
		void 		to_json(Poco::JSON::Object &Obj) const;
 | 
							void 		to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct DefaultConfiguration {
 | 
						struct DefaultConfiguration {
 | 
				
			||||||
		std::string Name;
 | 
							std::string Name;
 | 
				
			||||||
		std::string Configuration;
 | 
							std::string Configuration;
 | 
				
			||||||
		std::string Models;
 | 
							Types::StringVec Models;
 | 
				
			||||||
		std::string Description;
 | 
							std::string Description;
 | 
				
			||||||
		uint64_t 	Created;
 | 
							uint64_t 	Created;
 | 
				
			||||||
		uint64_t 	LastModified;
 | 
							uint64_t 	LastModified;
 | 
				
			||||||
@@ -138,6 +140,7 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
		uint64_t AttachDate = 0 ;
 | 
							uint64_t AttachDate = 0 ;
 | 
				
			||||||
		uint64_t AttachSize = 0 ;
 | 
							uint64_t AttachSize = 0 ;
 | 
				
			||||||
		std::string AttachType;
 | 
							std::string AttachType;
 | 
				
			||||||
 | 
							double 		executionTime = 0.0;
 | 
				
			||||||
		void to_json(Poco::JSON::Object &Obj) const;
 | 
							void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -153,20 +156,20 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
	struct RttySessionDetails {
 | 
						struct RttySessionDetails {
 | 
				
			||||||
		std::string SerialNumber;
 | 
							std::string SerialNumber;
 | 
				
			||||||
		std::string Server;
 | 
							std::string Server;
 | 
				
			||||||
		uint64_t 	Port;
 | 
							uint64_t 	Port = 0 ;
 | 
				
			||||||
		std::string Token;
 | 
							std::string Token;
 | 
				
			||||||
		uint64_t 	TimeOut;
 | 
							uint64_t 	TimeOut = 0 ;
 | 
				
			||||||
		std::string ConnectionId;
 | 
							std::string ConnectionId;
 | 
				
			||||||
		uint64_t 	Started;
 | 
							uint64_t 	Started = 0 ;
 | 
				
			||||||
		std::string CommandUUID;
 | 
							std::string CommandUUID;
 | 
				
			||||||
		uint64_t 	ViewPort;
 | 
							uint64_t 	ViewPort = 0 ;
 | 
				
			||||||
		std::string DevicePassword;
 | 
							std::string DevicePassword;
 | 
				
			||||||
		void to_json(Poco::JSON::Object &Obj) const;
 | 
							void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct Dashboard {
 | 
						struct Dashboard {
 | 
				
			||||||
		uint64_t 		  snapshot;
 | 
							uint64_t 		  snapshot = 0 ;
 | 
				
			||||||
		uint64_t 		  numberOfDevices;
 | 
							uint64_t 		  numberOfDevices = 0 ;
 | 
				
			||||||
		Types::CountedMap commands;
 | 
							Types::CountedMap commands;
 | 
				
			||||||
		Types::CountedMap upTimes;
 | 
							Types::CountedMap upTimes;
 | 
				
			||||||
		Types::CountedMap memoryUsed;
 | 
							Types::CountedMap memoryUsed;
 | 
				
			||||||
@@ -191,5 +194,3 @@ namespace OpenWifi::GWObjects {
 | 
				
			|||||||
		void to_json(Poco::JSON::Object &Obj) const;
 | 
							void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif //UCENTRAL_RESTAPI_OBJECTS_H
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -309,6 +309,7 @@ namespace OpenWifi::ProvObjects {
 | 
				
			|||||||
        field_to_json( Obj,"deviceConfiguration",deviceConfiguration);
 | 
					        field_to_json( Obj,"deviceConfiguration",deviceConfiguration);
 | 
				
			||||||
        field_to_json( Obj,"rrm",rrm);
 | 
					        field_to_json( Obj,"rrm",rrm);
 | 
				
			||||||
        field_to_json( Obj,"managementPolicy",managementPolicy);
 | 
					        field_to_json( Obj,"managementPolicy",managementPolicy);
 | 
				
			||||||
 | 
					        field_to_json( Obj,"state",state);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool InventoryTag::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
					    bool InventoryTag::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
@@ -326,6 +327,7 @@ namespace OpenWifi::ProvObjects {
 | 
				
			|||||||
            field_from_json( Obj,"deviceConfiguration",deviceConfiguration);
 | 
					            field_from_json( Obj,"deviceConfiguration",deviceConfiguration);
 | 
				
			||||||
            field_from_json( Obj,"rrm",rrm);
 | 
					            field_from_json( Obj,"rrm",rrm);
 | 
				
			||||||
            field_from_json( Obj,"managementPolicy",managementPolicy);
 | 
					            field_from_json( Obj,"managementPolicy",managementPolicy);
 | 
				
			||||||
 | 
					            field_from_json( Obj,"state",state);
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
        } catch(...) {
 | 
					        } catch(...) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -333,6 +335,20 @@ namespace OpenWifi::ProvObjects {
 | 
				
			|||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void InventoryTagList::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
 | 
					        field_to_json( Obj,"taglist",taglist);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool InventoryTagList::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            field_from_json( Obj,"taglist",taglist);
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        } catch (...) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void DeviceConfigurationElement::to_json(Poco::JSON::Object &Obj) const {
 | 
					    void DeviceConfigurationElement::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
        field_to_json( Obj,"name", name);
 | 
					        field_to_json( Obj,"name", name);
 | 
				
			||||||
        field_to_json( Obj,"description", description);
 | 
					        field_to_json( Obj,"description", description);
 | 
				
			||||||
@@ -440,11 +456,11 @@ namespace OpenWifi::ProvObjects {
 | 
				
			|||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void UserList::to_json(Poco::JSON::Object &Obj) const {
 | 
					    void UuidList::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
        field_to_json(Obj, "list", list);
 | 
					        field_to_json(Obj, "list", list);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool UserList::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
					    bool UuidList::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            field_from_json(Obj, "list", list);
 | 
					            field_from_json(Obj, "list", list);
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
@@ -454,14 +470,46 @@ namespace OpenWifi::ProvObjects {
 | 
				
			|||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void field_to_json(Poco::JSON::Object &Obj, const char * FieldName, ACLACCESS A) {
 | 
				
			||||||
 | 
					        switch(A) {
 | 
				
			||||||
 | 
					            case READ: Obj.set(FieldName,"read"); break;
 | 
				
			||||||
 | 
					            case MODIFY: Obj.set(FieldName,"modify"); break;
 | 
				
			||||||
 | 
					            case CREATE: Obj.set(FieldName,"create"); break;
 | 
				
			||||||
 | 
					            case DELETE: Obj.set(FieldName,"delete"); break;
 | 
				
			||||||
 | 
					            case NONE:
 | 
				
			||||||
 | 
					                default:
 | 
				
			||||||
 | 
					                    Obj.set(FieldName,"none");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char * FieldName, ACLACCESS &A) {
 | 
				
			||||||
 | 
					        if(Obj->has(FieldName)) {
 | 
				
			||||||
 | 
					            auto V = Obj->getValue<std::string>(FieldName);
 | 
				
			||||||
 | 
					            if(V=="read")
 | 
				
			||||||
 | 
					                A = READ;
 | 
				
			||||||
 | 
					            else if(V=="modify")
 | 
				
			||||||
 | 
					                A = MODIFY;
 | 
				
			||||||
 | 
					            else if(V=="create")
 | 
				
			||||||
 | 
					                A = CREATE;
 | 
				
			||||||
 | 
					            else if(V=="delete")
 | 
				
			||||||
 | 
					                A = DELETE;
 | 
				
			||||||
 | 
					            else if(V=="none")
 | 
				
			||||||
 | 
					                A = NONE;
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					                throw Poco::Exception("invalid JSON");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void ObjectACL::to_json(Poco::JSON::Object &Obj) const {
 | 
					    void ObjectACL::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
        field_to_json(Obj, "users", users);
 | 
					        RESTAPI_utils::field_to_json(Obj, "users", users);
 | 
				
			||||||
 | 
					        RESTAPI_utils::field_to_json(Obj, "roles", roles);
 | 
				
			||||||
        field_to_json(Obj, "access", access);
 | 
					        field_to_json(Obj, "access", access);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool ObjectACL::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
					    bool ObjectACL::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            field_from_json(Obj, "users", users);
 | 
					            RESTAPI_utils::field_from_json(Obj, "users", users);
 | 
				
			||||||
 | 
					            RESTAPI_utils::field_from_json(Obj, "roles", roles);
 | 
				
			||||||
            field_from_json(Obj, "access", access);
 | 
					            field_from_json(Obj, "access", access);
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
        } catch(...) {
 | 
					        } catch(...) {
 | 
				
			||||||
@@ -471,12 +519,12 @@ namespace OpenWifi::ProvObjects {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    void ObjectACLList::to_json(Poco::JSON::Object &Obj) const {
 | 
					    void ObjectACLList::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
        field_to_json(Obj, "list", list);
 | 
					        RESTAPI_utils::field_to_json(Obj, "list", list);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool ObjectACLList::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
					    bool ObjectACLList::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            field_from_json(Obj, "list", list);
 | 
					            RESTAPI_utils::field_from_json(Obj, "list", list);
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
        } catch(...) {
 | 
					        } catch(...) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -484,23 +532,54 @@ namespace OpenWifi::ProvObjects {
 | 
				
			|||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::string to_string(VISIBILITY A) {
 | 
				
			||||||
 | 
					        switch(A) {
 | 
				
			||||||
 | 
					            case PUBLIC: return "public";
 | 
				
			||||||
 | 
					            case SELECT: return "select";
 | 
				
			||||||
 | 
					            case PRIVATE:
 | 
				
			||||||
 | 
					            default:
 | 
				
			||||||
 | 
					                return "private";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void field_to_json(Poco::JSON::Object &Obj, const char * FieldName, VISIBILITY A) {
 | 
				
			||||||
 | 
					        Obj.set(FieldName,to_string(A));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    VISIBILITY visibility_from_string(const std::string &V) {
 | 
				
			||||||
 | 
					        if(V=="public")
 | 
				
			||||||
 | 
					            return PUBLIC;
 | 
				
			||||||
 | 
					        else if(V=="select")
 | 
				
			||||||
 | 
					            return SELECT;
 | 
				
			||||||
 | 
					        else if(V=="private")
 | 
				
			||||||
 | 
					            return PRIVATE;
 | 
				
			||||||
 | 
					        throw Poco::Exception("invalid json");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void field_from_json(const Poco::JSON::Object::Ptr &Obj, const char * FieldName, VISIBILITY &A) {
 | 
				
			||||||
 | 
					        if(Obj->has(FieldName)) {
 | 
				
			||||||
 | 
					            auto V = Obj->getValue<std::string>(FieldName);
 | 
				
			||||||
 | 
					            A = visibility_from_string(V);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void Map::to_json(Poco::JSON::Object &Obj) const {
 | 
					    void Map::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
        info.to_json(Obj);
 | 
					        info.to_json(Obj);
 | 
				
			||||||
        field_to_json( Obj,"data",data);
 | 
					        RESTAPI_utils::field_to_json( Obj,"data",data);
 | 
				
			||||||
        field_to_json( Obj,"entity",entity);
 | 
					        RESTAPI_utils::field_to_json( Obj,"entity",entity);
 | 
				
			||||||
        field_to_json( Obj,"creator",creator);
 | 
					        RESTAPI_utils::field_to_json( Obj,"creator",creator);
 | 
				
			||||||
        field_to_json( Obj,"visibility",visibility);
 | 
					        field_to_json( Obj,"visibility",visibility);
 | 
				
			||||||
        field_to_json( Obj,"access",access);
 | 
					        RESTAPI_utils::field_to_json( Obj,"access",access);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool Map::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
					    bool Map::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            info.from_json(Obj);
 | 
					            info.from_json(Obj);
 | 
				
			||||||
            field_from_json( Obj,"data",data);
 | 
					            RESTAPI_utils::field_from_json( Obj,"data",data);
 | 
				
			||||||
            field_from_json( Obj,"entity",entity);
 | 
					            RESTAPI_utils::field_from_json( Obj,"entity",entity);
 | 
				
			||||||
            field_from_json( Obj,"creator",creator);
 | 
					            RESTAPI_utils::field_from_json( Obj,"creator",creator);
 | 
				
			||||||
            field_from_json( Obj,"visibility",visibility);
 | 
					            field_from_json( Obj,"visibility",visibility);
 | 
				
			||||||
            field_from_json( Obj,"access",access);
 | 
					            RESTAPI_utils::field_from_json( Obj,"access",access);
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
        } catch(...) {
 | 
					        } catch(...) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -509,12 +588,12 @@ namespace OpenWifi::ProvObjects {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void MapList::to_json(Poco::JSON::Object &Obj) const {
 | 
					    void MapList::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
        field_to_json( Obj,"list",list);
 | 
					        RESTAPI_utils::field_to_json( Obj,"list",list);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool MapList::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
					    bool MapList::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            field_from_json( Obj,"list",list);
 | 
					            RESTAPI_utils::field_from_json( Obj,"list",list);
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
        } catch(...) {
 | 
					        } catch(...) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -566,4 +645,5 @@ namespace OpenWifi::ProvObjects {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
};
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,9 +6,7 @@
 | 
				
			|||||||
//	Arilia Wireless Inc.
 | 
					//	Arilia Wireless Inc.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
#ifndef OWPROV_RESTAPI_PROVOBJECTS_H
 | 
					 | 
				
			||||||
#define OWPROV_RESTAPI_PROVOBJECTS_H
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
#include "RESTAPI_SecurityObjects.h"
 | 
					#include "RESTAPI_SecurityObjects.h"
 | 
				
			||||||
@@ -286,12 +284,22 @@ namespace OpenWifi::ProvObjects {
 | 
				
			|||||||
        std::string     deviceConfiguration;
 | 
					        std::string     deviceConfiguration;
 | 
				
			||||||
        std::string     rrm;
 | 
					        std::string     rrm;
 | 
				
			||||||
        Types::UUID_t   managementPolicy;
 | 
					        Types::UUID_t   managementPolicy;
 | 
				
			||||||
 | 
					        std::string     state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void to_json(Poco::JSON::Object &Obj) const;
 | 
					        void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
					        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    typedef std::vector<InventoryTag>      InventoryTagVec;
 | 
					    typedef std::vector<InventoryTag>      InventoryTagVec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct InventoryTagList {
 | 
				
			||||||
 | 
					        InventoryTagVec     taglist;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
 | 
					        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    struct Report {
 | 
					    struct Report {
 | 
				
			||||||
        uint64_t            snapShot=0;
 | 
					        uint64_t            snapShot=0;
 | 
				
			||||||
        Types::CountedMap   tenants;
 | 
					        Types::CountedMap   tenants;
 | 
				
			||||||
@@ -324,16 +332,21 @@ namespace OpenWifi::ProvObjects {
 | 
				
			|||||||
        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
					        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    struct UserList {
 | 
					    struct UuidList {
 | 
				
			||||||
        std::vector<std::string>    list;
 | 
					        std::vector<std::string>    list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void to_json(Poco::JSON::Object &Obj) const;
 | 
					        void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
					        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    enum ACLACCESS {
 | 
				
			||||||
 | 
					        NONE, READ, MODIFY, CREATE, DELETE
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    struct ObjectACL {
 | 
					    struct ObjectACL {
 | 
				
			||||||
        UserList        users;
 | 
					        UuidList        users;
 | 
				
			||||||
        std::string     access;
 | 
					        UuidList        roles;
 | 
				
			||||||
 | 
					        ACLACCESS       access = NONE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void to_json(Poco::JSON::Object &Obj) const;
 | 
					        void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
					        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
@@ -346,12 +359,19 @@ namespace OpenWifi::ProvObjects {
 | 
				
			|||||||
        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
					        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    enum VISIBILITY {
 | 
				
			||||||
 | 
					        PUBLIC, PRIVATE, SELECT
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::string to_string(VISIBILITY A);
 | 
				
			||||||
 | 
					    VISIBILITY visibility_from_string(const std::string &V);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    struct Map {
 | 
					    struct Map {
 | 
				
			||||||
        ObjectInfo          info;
 | 
					        ObjectInfo          info;
 | 
				
			||||||
        std::string         data;
 | 
					        std::string         data;
 | 
				
			||||||
        std::string         entity;
 | 
					        std::string         entity;
 | 
				
			||||||
        std::string         creator;
 | 
					        std::string         creator;
 | 
				
			||||||
        std::string         visibility;
 | 
					        VISIBILITY          visibility = PRIVATE;
 | 
				
			||||||
        ObjectACLList       access;
 | 
					        ObjectACLList       access;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void to_json(Poco::JSON::Object &Obj) const;
 | 
					        void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
@@ -367,8 +387,4 @@ namespace OpenWifi::ProvObjects {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    bool UpdateObjectInfo(const Poco::JSON::Object::Ptr &O, const SecurityObjects::UserInfo &U, ObjectInfo &I);
 | 
					    bool UpdateObjectInfo(const Poco::JSON::Object::Ptr &O, const SecurityObjects::UserInfo &U, ObjectInfo &I);
 | 
				
			||||||
    bool CreateObjectInfo(const Poco::JSON::Object::Ptr &O, const SecurityObjects::UserInfo &U, ObjectInfo &I);
 | 
					    bool CreateObjectInfo(const Poco::JSON::Object::Ptr &O, const SecurityObjects::UserInfo &U, ObjectInfo &I);
 | 
				
			||||||
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif //OWPROV_RESTAPI_PROVOBJECTS_H
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -54,6 +54,8 @@ namespace OpenWifi::SecurityObjects {
 | 
				
			|||||||
            return ADMIN;
 | 
					            return ADMIN;
 | 
				
			||||||
        else if (!Poco::icompare(U,"subscriber"))
 | 
					        else if (!Poco::icompare(U,"subscriber"))
 | 
				
			||||||
            return SUBSCRIBER;
 | 
					            return SUBSCRIBER;
 | 
				
			||||||
 | 
					        else if (!Poco::icompare(U,"partner"))
 | 
				
			||||||
 | 
					            return PARTNER;
 | 
				
			||||||
        else if (!Poco::icompare(U,"csr"))
 | 
					        else if (!Poco::icompare(U,"csr"))
 | 
				
			||||||
            return CSR;
 | 
					            return CSR;
 | 
				
			||||||
        else if (!Poco::icompare(U, "system"))
 | 
					        else if (!Poco::icompare(U, "system"))
 | 
				
			||||||
@@ -72,6 +74,7 @@ namespace OpenWifi::SecurityObjects {
 | 
				
			|||||||
            case ROOT: return "root";
 | 
					            case ROOT: return "root";
 | 
				
			||||||
            case ADMIN: return "admin";
 | 
					            case ADMIN: return "admin";
 | 
				
			||||||
            case SUBSCRIBER: return "subscriber";
 | 
					            case SUBSCRIBER: return "subscriber";
 | 
				
			||||||
 | 
					            case PARTNER: return "partner";
 | 
				
			||||||
            case CSR: return "csr";
 | 
					            case CSR: return "csr";
 | 
				
			||||||
            case SYSTEM: return "system";
 | 
					            case SYSTEM: return "system";
 | 
				
			||||||
            case INSTALLER: return "installer";
 | 
					            case INSTALLER: return "installer";
 | 
				
			||||||
@@ -169,12 +172,14 @@ namespace OpenWifi::SecurityObjects {
 | 
				
			|||||||
	void UserLoginLoginExtensions::to_json(Poco::JSON::Object &Obj) const {
 | 
						void UserLoginLoginExtensions::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
	    field_to_json(Obj, "mobiles", mobiles);
 | 
						    field_to_json(Obj, "mobiles", mobiles);
 | 
				
			||||||
	    field_to_json(Obj, "mfa", mfa);
 | 
						    field_to_json(Obj, "mfa", mfa);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "authenticatorSecret", authenticatorSecret);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool UserLoginLoginExtensions::from_json(Poco::JSON::Object::Ptr &Obj) {
 | 
						bool UserLoginLoginExtensions::from_json(Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
	    try {
 | 
						    try {
 | 
				
			||||||
	        field_from_json(Obj,"mobiles",mobiles);
 | 
						        field_from_json(Obj, "mobiles",mobiles);
 | 
				
			||||||
	        field_from_json(Obj,"mfa",mfa);
 | 
						        field_from_json(Obj, "mfa",mfa);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "authenticatorSecret", authenticatorSecret);
 | 
				
			||||||
	        return true;
 | 
						        return true;
 | 
				
			||||||
	    } catch (...) {
 | 
						    } catch (...) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -221,7 +226,7 @@ namespace OpenWifi::SecurityObjects {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void UserInfo::to_json(Poco::JSON::Object &Obj) const {
 | 
					    void UserInfo::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
		field_to_json(Obj,"Id",Id);
 | 
							field_to_json(Obj,"id",id);
 | 
				
			||||||
		field_to_json(Obj,"name",name);
 | 
							field_to_json(Obj,"name",name);
 | 
				
			||||||
		field_to_json(Obj,"description", description);
 | 
							field_to_json(Obj,"description", description);
 | 
				
			||||||
		field_to_json(Obj,"avatar", avatar);
 | 
							field_to_json(Obj,"avatar", avatar);
 | 
				
			||||||
@@ -251,11 +256,12 @@ namespace OpenWifi::SecurityObjects {
 | 
				
			|||||||
		field_to_json(Obj,"lastPasswords",lastPasswords);
 | 
							field_to_json(Obj,"lastPasswords",lastPasswords);
 | 
				
			||||||
		field_to_json(Obj,"oauthType",oauthType);
 | 
							field_to_json(Obj,"oauthType",oauthType);
 | 
				
			||||||
		field_to_json(Obj,"oauthUserInfo",oauthUserInfo);
 | 
							field_to_json(Obj,"oauthUserInfo",oauthUserInfo);
 | 
				
			||||||
 | 
					        field_to_json(Obj,"modified",modified);
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool UserInfo::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
					    bool UserInfo::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
			field_from_json(Obj,"Id",Id);
 | 
								field_from_json(Obj,"id",id);
 | 
				
			||||||
			field_from_json(Obj,"name",name);
 | 
								field_from_json(Obj,"name",name);
 | 
				
			||||||
			field_from_json(Obj,"description",description);
 | 
								field_from_json(Obj,"description",description);
 | 
				
			||||||
			field_from_json(Obj,"avatar",avatar);
 | 
								field_from_json(Obj,"avatar",avatar);
 | 
				
			||||||
@@ -265,6 +271,8 @@ namespace OpenWifi::SecurityObjects {
 | 
				
			|||||||
			field_from_json(Obj,"currentLoginURI",currentLoginURI);
 | 
								field_from_json(Obj,"currentLoginURI",currentLoginURI);
 | 
				
			||||||
			field_from_json(Obj,"locale",locale);
 | 
								field_from_json(Obj,"locale",locale);
 | 
				
			||||||
			field_from_json(Obj,"notes",notes);
 | 
								field_from_json(Obj,"notes",notes);
 | 
				
			||||||
 | 
					            field_from_json(Obj,"location", location);
 | 
				
			||||||
 | 
					            field_from_json(Obj,"owner", owner);
 | 
				
			||||||
			field_from_json<USER_ROLE>(Obj,"userRole",userRole, UserTypeFromString);
 | 
								field_from_json<USER_ROLE>(Obj,"userRole",userRole, UserTypeFromString);
 | 
				
			||||||
			field_from_json(Obj,"securityPolicy",securityPolicy);
 | 
								field_from_json(Obj,"securityPolicy",securityPolicy);
 | 
				
			||||||
			field_from_json(Obj,"userTypeProprietaryInfo",userTypeProprietaryInfo);
 | 
								field_from_json(Obj,"userTypeProprietaryInfo",userTypeProprietaryInfo);
 | 
				
			||||||
@@ -283,6 +291,7 @@ namespace OpenWifi::SecurityObjects {
 | 
				
			|||||||
			field_from_json(Obj,"lastPasswords",lastPasswords);
 | 
								field_from_json(Obj,"lastPasswords",lastPasswords);
 | 
				
			||||||
			field_from_json(Obj,"oauthType",oauthType);
 | 
								field_from_json(Obj,"oauthType",oauthType);
 | 
				
			||||||
			field_from_json(Obj,"oauthUserInfo",oauthUserInfo);
 | 
								field_from_json(Obj,"oauthUserInfo",oauthUserInfo);
 | 
				
			||||||
 | 
					            field_from_json(Obj,"modified",modified);
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
        } catch (const Poco::Exception &E) {
 | 
					        } catch (const Poco::Exception &E) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -491,7 +500,7 @@ namespace OpenWifi::SecurityObjects {
 | 
				
			|||||||
	    field_to_json(Obj,"expires",expires);
 | 
						    field_to_json(Obj,"expires",expires);
 | 
				
			||||||
	    field_to_json(Obj,"completed",completed);
 | 
						    field_to_json(Obj,"completed",completed);
 | 
				
			||||||
	    field_to_json(Obj,"canceled",canceled);
 | 
						    field_to_json(Obj,"canceled",canceled);
 | 
				
			||||||
 | 
					        field_to_json(Obj,"userAction",userAction);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool ActionLink::from_json(Poco::JSON::Object::Ptr &Obj) {
 | 
					    bool ActionLink::from_json(Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
@@ -508,11 +517,86 @@ namespace OpenWifi::SecurityObjects {
 | 
				
			|||||||
	        field_from_json(Obj,"expires",expires);
 | 
						        field_from_json(Obj,"expires",expires);
 | 
				
			||||||
	        field_from_json(Obj,"completed",completed);
 | 
						        field_from_json(Obj,"completed",completed);
 | 
				
			||||||
	        field_from_json(Obj,"canceled",canceled);
 | 
						        field_from_json(Obj,"canceled",canceled);
 | 
				
			||||||
 | 
					            field_from_json(Obj,"userAction",userAction);
 | 
				
			||||||
	        return true;
 | 
						        return true;
 | 
				
			||||||
	    } catch(...) {
 | 
						    } catch(...) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	    }
 | 
						    }
 | 
				
			||||||
	    return false;
 | 
						    return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void Preferences::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
 | 
						    field_to_json(Obj,"id",id);
 | 
				
			||||||
 | 
						    field_to_json(Obj,"modified",modified);
 | 
				
			||||||
 | 
						    field_to_json(Obj,"data",data);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool Preferences::from_json(Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
						    try {
 | 
				
			||||||
 | 
						        field_from_json(Obj,"id",id);
 | 
				
			||||||
 | 
						        field_from_json(Obj,"modified",modified);
 | 
				
			||||||
 | 
						        field_from_json(Obj,"data",data);
 | 
				
			||||||
 | 
						        return true;
 | 
				
			||||||
 | 
						    } catch(...) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						    return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void SubMfaConfig::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
 | 
						    field_to_json(Obj,"id",id);
 | 
				
			||||||
 | 
						    field_to_json(Obj,"type",type);
 | 
				
			||||||
 | 
						    field_to_json(Obj,"sms",sms);
 | 
				
			||||||
 | 
						    field_to_json(Obj,"email",email);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool SubMfaConfig::from_json(Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
						    try {
 | 
				
			||||||
 | 
						        field_from_json(Obj,"id",id);
 | 
				
			||||||
 | 
						        field_from_json(Obj,"type",type);
 | 
				
			||||||
 | 
						        field_from_json(Obj,"sms",sms);
 | 
				
			||||||
 | 
						        field_from_json(Obj,"email",email);
 | 
				
			||||||
 | 
						        return true;
 | 
				
			||||||
 | 
						    } catch(...) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						    return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void Token::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
 | 
					        field_to_json(Obj,"token",token);
 | 
				
			||||||
 | 
					        field_to_json(Obj,"refreshToken",refreshToken);
 | 
				
			||||||
 | 
					        field_to_json(Obj,"tokenType",tokenType);
 | 
				
			||||||
 | 
					        field_to_json(Obj,"userName",userName);
 | 
				
			||||||
 | 
					        field_to_json(Obj,"created",created);
 | 
				
			||||||
 | 
					        field_to_json(Obj,"expires",expires);
 | 
				
			||||||
 | 
					        field_to_json(Obj,"idleTimeout",idleTimeout);
 | 
				
			||||||
 | 
					        field_to_json(Obj,"revocationDate",revocationDate);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool Token::from_json(Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            field_from_json(Obj,"token",token);
 | 
				
			||||||
 | 
					            field_from_json(Obj,"refreshToken",refreshToken);
 | 
				
			||||||
 | 
					            field_from_json(Obj,"tokenType",tokenType);
 | 
				
			||||||
 | 
					            field_from_json(Obj,"userName",userName);
 | 
				
			||||||
 | 
					            field_from_json(Obj,"created",created);
 | 
				
			||||||
 | 
					            field_from_json(Obj,"expires",expires);
 | 
				
			||||||
 | 
					            field_from_json(Obj,"idleTimeout",idleTimeout);
 | 
				
			||||||
 | 
					            field_from_json(Obj,"revocationDate",revocationDate);
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        } catch(...) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void LoginRecordInfo::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
 | 
					        field_to_json(Obj,"sessionId",sessionId);
 | 
				
			||||||
 | 
					        field_to_json(Obj,"userId",userId);
 | 
				
			||||||
 | 
					        field_to_json(Obj,"email",email);
 | 
				
			||||||
 | 
					        field_to_json(Obj,"login",login);
 | 
				
			||||||
 | 
					        field_to_json(Obj,"logout",logout);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,13 +6,18 @@
 | 
				
			|||||||
//	Arilia Wireless Inc.
 | 
					//	Arilia Wireless Inc.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef UCENTRAL_RESTAPI_SECURITYOBJECTS_H
 | 
					#pragma once
 | 
				
			||||||
#define UCENTRAL_RESTAPI_SECURITYOBJECTS_H
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "Poco/JSON/Object.h"
 | 
					#include <string>
 | 
				
			||||||
#include "framework/OpenWifiTypes.h"
 | 
					#include "framework/OpenWifiTypes.h"
 | 
				
			||||||
 | 
					#include "Poco/JSON/Object.h"
 | 
				
			||||||
 | 
					#include "Poco/Data/LOB.h"
 | 
				
			||||||
 | 
					#include "Poco/Data/LOBStream.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi::SecurityObjects {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					    namespace SecurityObjects {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        typedef std::string USER_ID_TYPE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        struct AclTemplate {
 | 
					        struct AclTemplate {
 | 
				
			||||||
            bool Read_ = true;
 | 
					            bool Read_ = true;
 | 
				
			||||||
@@ -42,7 +47,7 @@ namespace OpenWifi::SecurityObjects {
 | 
				
			|||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        enum USER_ROLE {
 | 
					        enum USER_ROLE {
 | 
				
			||||||
        UNKNOWN, ROOT, ADMIN, SUBSCRIBER, CSR, SYSTEM, INSTALLER, NOC, ACCOUNTING
 | 
					            UNKNOWN, ROOT, ADMIN, SUBSCRIBER, CSR, SYSTEM, INSTALLER, NOC, ACCOUNTING, PARTNER
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        USER_ROLE UserTypeFromString(const std::string &U);
 | 
					        USER_ROLE UserTypeFromString(const std::string &U);
 | 
				
			||||||
@@ -77,6 +82,7 @@ namespace OpenWifi::SecurityObjects {
 | 
				
			|||||||
        struct UserLoginLoginExtensions {
 | 
					        struct UserLoginLoginExtensions {
 | 
				
			||||||
            std::vector<MobilePhoneNumber>  mobiles;
 | 
					            std::vector<MobilePhoneNumber>  mobiles;
 | 
				
			||||||
            struct MfaAuthInfo              mfa;
 | 
					            struct MfaAuthInfo              mfa;
 | 
				
			||||||
 | 
					            std::string                     authenticatorSecret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            void to_json(Poco::JSON::Object &Obj) const;
 | 
					            void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
            bool from_json(Poco::JSON::Object::Ptr &Obj);
 | 
					            bool from_json(Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
@@ -101,7 +107,7 @@ namespace OpenWifi::SecurityObjects {
 | 
				
			|||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        struct UserInfo {
 | 
					        struct UserInfo {
 | 
				
			||||||
        std::string Id;
 | 
					            std::string id;
 | 
				
			||||||
            std::string name;
 | 
					            std::string name;
 | 
				
			||||||
            std::string description;
 | 
					            std::string description;
 | 
				
			||||||
            std::string avatar;
 | 
					            std::string avatar;
 | 
				
			||||||
@@ -128,9 +134,10 @@ namespace OpenWifi::SecurityObjects {
 | 
				
			|||||||
            std::string securityPolicy;
 | 
					            std::string securityPolicy;
 | 
				
			||||||
            uint64_t    securityPolicyChange = 0 ;
 | 
					            uint64_t    securityPolicyChange = 0 ;
 | 
				
			||||||
            std::string currentPassword;
 | 
					            std::string currentPassword;
 | 
				
			||||||
		Types::StringVec lastPasswords;
 | 
					            OpenWifi::Types::StringVec lastPasswords;
 | 
				
			||||||
            std::string oauthType;
 | 
					            std::string oauthType;
 | 
				
			||||||
            std::string oauthUserInfo;
 | 
					            std::string oauthUserInfo;
 | 
				
			||||||
 | 
					            uint64_t    modified;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            void to_json(Poco::JSON::Object &Obj) const;
 | 
					            void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
            bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
					            bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
@@ -224,7 +231,9 @@ namespace OpenWifi::SecurityObjects {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        enum LinkActions {
 | 
					        enum LinkActions {
 | 
				
			||||||
            FORGOT_PASSWORD=1,
 | 
					            FORGOT_PASSWORD=1,
 | 
				
			||||||
	    VERIFY_EMAIL
 | 
					            VERIFY_EMAIL,
 | 
				
			||||||
 | 
					            SUB_FORGOT_PASSWORD,
 | 
				
			||||||
 | 
					            SUB_VERIFY_EMAIL
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        struct ActionLink {
 | 
					        struct ActionLink {
 | 
				
			||||||
@@ -240,10 +249,60 @@ namespace OpenWifi::SecurityObjects {
 | 
				
			|||||||
            uint64_t            expires=0;
 | 
					            uint64_t            expires=0;
 | 
				
			||||||
            uint64_t            completed=0;
 | 
					            uint64_t            completed=0;
 | 
				
			||||||
            uint64_t            canceled=0;
 | 
					            uint64_t            canceled=0;
 | 
				
			||||||
 | 
					            bool                userAction=true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            void to_json(Poco::JSON::Object &Obj) const;
 | 
					            void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
            bool from_json(Poco::JSON::Object::Ptr &Obj);
 | 
					            bool from_json(Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif //UCENTRAL_RESTAPI_SECURITYOBJECTS_H
 | 
					        struct Preferences {
 | 
				
			||||||
 | 
					            std::string                         id;
 | 
				
			||||||
 | 
					            uint64_t                            modified;
 | 
				
			||||||
 | 
					            Types::StringPairVec                data;
 | 
				
			||||||
 | 
					            void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
 | 
					            bool from_json(Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        struct SubMfaConfig {
 | 
				
			||||||
 | 
					            std::string                         id;
 | 
				
			||||||
 | 
					            std::string                         type;
 | 
				
			||||||
 | 
					            std::string                         sms;
 | 
				
			||||||
 | 
					            std::string                         email;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
 | 
					            bool from_json(Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        struct Token {
 | 
				
			||||||
 | 
					            std::string         token;
 | 
				
			||||||
 | 
					            std::string         refreshToken;
 | 
				
			||||||
 | 
					            std::string         tokenType;
 | 
				
			||||||
 | 
					            std::string         userName;
 | 
				
			||||||
 | 
					            uint64_t            created=0;
 | 
				
			||||||
 | 
					            uint64_t            expires=0;
 | 
				
			||||||
 | 
					            uint64_t            idleTimeout=0;
 | 
				
			||||||
 | 
					            uint64_t            revocationDate=0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
 | 
					            bool from_json(Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        struct Avatar {
 | 
				
			||||||
 | 
					            std::string             id;
 | 
				
			||||||
 | 
					            std::string             type;
 | 
				
			||||||
 | 
					            uint64_t                created=0;
 | 
				
			||||||
 | 
					            std::string             name;
 | 
				
			||||||
 | 
					            Poco::Data::LOB<char>   avatar;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        struct LoginRecordInfo {
 | 
				
			||||||
 | 
					            std::string sessionId;
 | 
				
			||||||
 | 
					            std::string userId;
 | 
				
			||||||
 | 
					            std::string email;
 | 
				
			||||||
 | 
					            uint64_t    login=0;
 | 
				
			||||||
 | 
					            uint64_t    logout=0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										547
									
								
								src/RESTObjects/RESTAPI_SubObjects.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										547
									
								
								src/RESTObjects/RESTAPI_SubObjects.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,547 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Created by stephane bourque on 2021-10-27.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "RESTAPI_SubObjects.h"
 | 
				
			||||||
 | 
					#include "framework/MicroService.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					using OpenWifi::RESTAPI_utils::field_to_json;
 | 
				
			||||||
 | 
					using OpenWifi::RESTAPI_utils::field_from_json;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace OpenWifi::SubObjects {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void HomeDeviceMode::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
 | 
					        field_to_json(Obj, "enableLEDS", enableLEDS);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "type", type);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "subnet", subnet);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "subnetMask", subnetMask);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "startIP", startIP);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "endIP", endIP);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "created", created);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "modified", modified);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "subnetV6", subnetV6);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "subnetMaskV6", subnetMaskV6);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "startIPV6", startIPV6);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "endIPV6", endIPV6);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool HomeDeviceMode::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            field_from_json(Obj, "enableLEDS", enableLEDS);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "type", type);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "subnet", subnet);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "subnetMask", subnetMask);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "startIP", startIP);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "endIP", endIP);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "created", created);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "modified", modified);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "subnetV6", subnetV6);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "subnetMaskV6", subnetMaskV6);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "startIPV6", startIPV6);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "endIPV6", endIPV6);
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        } catch (...) {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void IPReservation::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
 | 
					        field_to_json(Obj, "nickname", nickname);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "ipAddress", ipAddress);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "macAddress", macAddress);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool IPReservation::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            field_from_json(Obj, "nickname", nickname);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "ipAddress", ipAddress);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "macAddress", macAddress);
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        } catch (...) {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void IPReservationList::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
 | 
					        field_to_json(Obj, "id", id);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "reservations", reservations);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "created", created);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "modified", modified);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool IPReservationList::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            field_from_json(Obj, "id", id);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "reservations", reservations);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "created", created);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "modified", modified);
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        } catch (...) {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void DnsConfiguration::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
 | 
					        field_to_json(Obj, "ISP", ISP);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "custom", custom);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "primary", primary);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "secondary", secondary);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "primaryV6", primaryV6);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "secondaryV6", secondaryV6);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool DnsConfiguration::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            field_from_json(Obj, "ISP", ISP);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "custom", custom);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "primary", primary);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "secondary", secondary);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "primaryV6", primaryV6);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "secondaryV6", secondaryV6);
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        } catch (...) {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void InternetConnection::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
 | 
					        field_to_json(Obj, "type", type);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "username", username);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "password", password);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "ipAddress", ipAddress);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "subnetMask", subnetMask);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "defaultGateway", defaultGateway);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "sendHostname", sendHostname);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "primaryDns", primaryDns);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "secondaryDns", secondaryDns);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "created", created);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "modified", modified);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "ipV6Support", ipV6Support);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "ipAddressV6", ipAddressV6);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "subnetMaskV6", subnetMaskV6);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "defaultGatewayV6", defaultGatewayV6);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "primaryDnsV6", primaryDnsV6);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "secondaryDnsV6", secondaryDnsV6);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool InternetConnection::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            field_from_json(Obj, "type", type);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "username", username);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "password", password);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "ipAddress", ipAddress);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "subnetMask", subnetMask);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "defaultGateway", defaultGateway);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "sendHostname", sendHostname);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "primaryDns", primaryDns);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "secondaryDns", secondaryDns);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "created", created);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "modified", modified);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "ipV6Support", ipV6Support);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "ipAddressV6", ipAddressV6);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "subnetMaskV6", subnetMaskV6);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "defaultGatewayV6", defaultGatewayV6);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "primaryDnsV6", primaryDnsV6);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "secondaryDnsV6", secondaryDnsV6);
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        } catch (...) {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void WifiNetwork::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
 | 
					        field_to_json(Obj, "type", type);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "name", name);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "password", password);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "encryption", encryption);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "bands", bands);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool WifiNetwork::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            field_from_json(Obj, "type", type);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "name", name);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "password", password);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "encryption", encryption);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "bands", bands);
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        } catch (...) {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void WifiNetworkList::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
 | 
					        field_to_json(Obj, "wifiNetworks", wifiNetworks);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "created", created);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "modified", modified);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool WifiNetworkList::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            field_from_json(Obj, "wifiNetworks", wifiNetworks);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "created", created);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "modified", modified);
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        } catch (...) {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void AccessTime::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
 | 
					        field_to_json(Obj, "day", day);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "rangeList", rangeList);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool AccessTime::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            field_from_json(Obj, "day", day);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "rangeList", rangeList);
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        } catch (...) {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void AccessTimes::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
 | 
					        field_to_json(Obj, "schedule", schedule);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "created", created);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "modified", modified);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool AccessTimes::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            field_from_json(Obj, "schedule", schedule);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "created", created);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "modified", modified);
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        } catch (...) {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void SubscriberDevice::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
 | 
					        field_to_json(Obj, "name", name);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "description", description);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "macAddress", macAddress);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "manufacturer", manufacturer);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "firstContact", firstContact);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "lastContact", lastContact);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "group", group);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "icon", icon);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "suspended", suspended);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "ip", ip);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "schedule", schedule);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool SubscriberDevice::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            field_from_json(Obj, "name", name);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "description", description);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "macAddress", macAddress);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "manufacturer", manufacturer);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "firstContact", firstContact);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "lastContact", lastContact);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "group", group);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "icon", icon);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "suspended", suspended);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "ip", ip);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "schedule", schedule);
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        } catch (...) {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void SubscriberDeviceList::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
 | 
					        field_to_json(Obj, "devices", devices);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "created", created);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "modified", modified);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool SubscriberDeviceList::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            field_from_json(Obj, "devices", devices);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "created", created);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "modified", modified);
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        } catch (...) {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void Association::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
 | 
					        field_to_json(Obj, "name", name);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "ssid", ssid);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "macAddress", macAddress);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "rssi", rssi);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "power", power);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "ipv4", ipv4);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "ipv6", ipv6);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "tx", tx);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "rx", rx);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool Association::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            field_from_json(Obj, "name", name);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "ssid", ssid);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "macAddress", macAddress);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "rssi", rssi);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "power", power);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "ipv4", ipv4);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "ipv6", ipv6);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "tx", tx);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "rx", rx);
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        } catch (...) {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void AssociationList::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
 | 
					        field_to_json(Obj, "associations", associations);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "created", created);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "modified", modified);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool AssociationList::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            field_from_json(Obj, "associations", associations);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "created", created);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "modified", modified);
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        } catch (...) {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void Client::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
 | 
					        field_to_json(Obj, "macAddress", macAddress);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "speed", speed);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "mode", mode);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "ipv4", ipv4);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "ipv6", ipv6);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "tx", tx);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "rx", rx);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool Client::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            field_from_json(Obj, "macAddress", macAddress);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "speed", speed);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "mode", mode);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "ipv4", ipv4);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "ipv6", ipv6);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "tx", tx);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "rx", rx);
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        } catch (...) {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void ClientList::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
 | 
					        field_to_json(Obj, "clients", clients);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "created", created);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "modified", modified);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool ClientList::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            field_from_json(Obj, "clients", clients);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "created", created);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "modified", modified);
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        } catch (...) {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void Location::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
 | 
					        field_to_json(Obj, "buildingName", buildingName);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "addressLines", addressLines);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "city", city);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "state", state);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "postal", postal);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "country", country);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "phones", phones);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "mobiles", mobiles);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool Location::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            field_from_json(Obj, "buildingName", buildingName);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "addressLines", addressLines);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "city", city);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "state", state);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "postal", postal);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "country", country);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "phones", phones);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "mobiles", mobiles);
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        } catch (...) {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void RadioHE::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
 | 
					        field_to_json(Obj, "multipleBSSID", multipleBSSID);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "ema", ema);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "bssColor", bssColor);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool RadioHE::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            field_from_json(Obj, "multipleBSSID", multipleBSSID);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "ema", ema);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "bssColor", bssColor);
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        } catch (...) {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void RadioRates::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
 | 
					        field_to_json(Obj, "beacon", beacon);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "multicast", multicast);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool RadioRates::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            field_from_json(Obj, "beacon", beacon);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "multicast", multicast);
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        } catch (...) {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void RadioInformation::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
 | 
					        field_to_json(Obj, "band", band);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "bandwidth", bandwidth);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "channel", channel);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "country", country);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "channelMode", channelMode);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "channelWidth", channelWidth);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "requireMode", requireMode);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "txpower", txpower);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "legacyRates", legacyRates);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "beaconInterval", beaconInterval);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "dtimPeriod", dtimPeriod);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "maximumClients", maximumClients);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "rates", rates);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "he", he);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "rawInfo", rawInfo);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool RadioInformation::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            field_from_json(Obj, "band", band);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "bandwidth", bandwidth);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "channel", channel);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "country", country);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "channelMode", channelMode);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "channelWidth", channelWidth);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "requireMode", requireMode);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "txpower", txpower);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "legacyRates", legacyRates);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "beaconInterval", beaconInterval);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "dtimPeriod", dtimPeriod);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "maximumClients", maximumClients);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "rates", rates);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "he", he);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "rawInfo", rawInfo);
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        } catch (...) {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void AccessPoint::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
 | 
					        field_to_json(Obj, "id", id);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "macAddress", macAddress);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "name", name);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "deviceType", deviceType);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "subscriberDevices", subscriberDevices);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "ipReservations", ipReservations);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "address", address);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "wifiNetworks", wifiNetworks);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "internetConnection", internetConnection);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "deviceMode", deviceMode);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "dnsConfiguration", dnsConfiguration);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "radios", radios);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "automaticUpgrade", automaticUpgrade);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "configurationUUID", configurationUUID);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool AccessPoint::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            field_from_json(Obj, "id", id);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "macAddress", macAddress);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "name", name);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "deviceType", deviceType);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "subscriberDevices", subscriberDevices);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "ipReservations", ipReservations);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "address", address);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "wifiNetworks", wifiNetworks);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "internetConnection", internetConnection);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "deviceMode", deviceMode);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "dnsConfiguration", dnsConfiguration);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "radios", radios);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "automaticUpgrade", automaticUpgrade);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "configurationUUID", configurationUUID);
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        } catch (...) {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void AccessPointList::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
 | 
					        field_to_json(Obj, "list", list);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool AccessPointList::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            field_from_json(Obj, "list", list);
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        } catch (...) {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void SubscriberInfo::to_json(Poco::JSON::Object &Obj) const {
 | 
				
			||||||
 | 
					        field_to_json(Obj, "id", id);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "userId", userId);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "firstName", firstName);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "initials", initials);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "lastName", lastName);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "phoneNumber", phoneNumber);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "secondaryEmail", secondaryEmail);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "accessPoints", accessPoints);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "serviceAddress", serviceAddress);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "billingAddress", billingAddress);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "created", created);
 | 
				
			||||||
 | 
					        field_to_json(Obj, "modified", modified);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool SubscriberInfo::from_json(const Poco::JSON::Object::Ptr &Obj) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            field_from_json(Obj, "id", id);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "userId", userId);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "firstName", firstName);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "initials", initials);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "lastName", lastName);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "phoneNumber", phoneNumber);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "secondaryEmail", secondaryEmail);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "accessPoints", accessPoints);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "serviceAddress", serviceAddress);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "billingAddress", billingAddress);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "created", created);
 | 
				
			||||||
 | 
					            field_from_json(Obj, "modified", modified);
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        } catch (...) {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										293
									
								
								src/RESTObjects/RESTAPI_SubObjects.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										293
									
								
								src/RESTObjects/RESTAPI_SubObjects.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,293 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Created by stephane bourque on 2021-10-27.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef OWSUB_RESTAPI_SUBOBJECTS_H
 | 
				
			||||||
 | 
					#define OWSUB_RESTAPI_SUBOBJECTS_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "Poco/JSON/Object.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace OpenWifi::SubObjects {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct HomeDeviceMode {
 | 
				
			||||||
 | 
					        bool            enableLEDS = true;
 | 
				
			||||||
 | 
					        std::string     type;       // bridge, manual, automatic
 | 
				
			||||||
 | 
					        std::string     subnet;
 | 
				
			||||||
 | 
					        std::string     subnetMask;
 | 
				
			||||||
 | 
					        std::string     startIP;
 | 
				
			||||||
 | 
					        std::string     endIP;
 | 
				
			||||||
 | 
					        uint64_t        created = 0 ;
 | 
				
			||||||
 | 
					        uint64_t        modified = 0 ;
 | 
				
			||||||
 | 
					        std::string     subnetV6;
 | 
				
			||||||
 | 
					        int             subnetMaskV6=0;
 | 
				
			||||||
 | 
					        std::string     startIPV6;
 | 
				
			||||||
 | 
					        std::string     endIPV6;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
 | 
					        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct IPReservation  {
 | 
				
			||||||
 | 
					        std::string     nickname;
 | 
				
			||||||
 | 
					        std::string     ipAddress;
 | 
				
			||||||
 | 
					        std::string     macAddress;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
 | 
					        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct IPReservationList {
 | 
				
			||||||
 | 
					        std::string                 id;
 | 
				
			||||||
 | 
					        std::vector<IPReservation>  reservations;
 | 
				
			||||||
 | 
					        uint64_t created = 0 ;
 | 
				
			||||||
 | 
					        uint64_t modified = 0 ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
 | 
					        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct DnsConfiguration {
 | 
				
			||||||
 | 
					        bool            ISP=false;
 | 
				
			||||||
 | 
					        bool            custom=false;
 | 
				
			||||||
 | 
					        std::string     primary;
 | 
				
			||||||
 | 
					        std::string     secondary;
 | 
				
			||||||
 | 
					        std::string     primaryV6;
 | 
				
			||||||
 | 
					        std::string     secondaryV6;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
 | 
					        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct InternetConnection {
 | 
				
			||||||
 | 
					        std::string     type; // automatic, pppoe, manual
 | 
				
			||||||
 | 
					        std::string     username;
 | 
				
			||||||
 | 
					        std::string     password;
 | 
				
			||||||
 | 
					        std::string     ipAddress;
 | 
				
			||||||
 | 
					        std::string     subnetMask;
 | 
				
			||||||
 | 
					        std::string     defaultGateway;
 | 
				
			||||||
 | 
					        bool            sendHostname = true;
 | 
				
			||||||
 | 
					        std::string     primaryDns;
 | 
				
			||||||
 | 
					        std::string     secondaryDns;
 | 
				
			||||||
 | 
					        uint64_t        created=0;
 | 
				
			||||||
 | 
					        uint64_t        modified=0;
 | 
				
			||||||
 | 
					        bool            ipV6Support=false;
 | 
				
			||||||
 | 
					        std::string     ipAddressV6;
 | 
				
			||||||
 | 
					        int             subnetMaskV6=0;
 | 
				
			||||||
 | 
					        std::string     defaultGatewayV6;
 | 
				
			||||||
 | 
					        std::string     primaryDnsV6;
 | 
				
			||||||
 | 
					        std::string     secondaryDnsV6;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
 | 
					        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct WifiNetwork {
 | 
				
			||||||
 | 
					        std::string     type;       // main, guest
 | 
				
			||||||
 | 
					        std::string     name;
 | 
				
			||||||
 | 
					        std::string     password;
 | 
				
			||||||
 | 
					        std::string     encryption;
 | 
				
			||||||
 | 
					        std::vector<std::string>    bands;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
 | 
					        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct WifiNetworkList {
 | 
				
			||||||
 | 
					        std::vector<WifiNetwork>    wifiNetworks;
 | 
				
			||||||
 | 
					        uint64_t                    created=0;
 | 
				
			||||||
 | 
					        uint64_t                    modified=0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
 | 
					        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct AccessTime {
 | 
				
			||||||
 | 
					        std::string day;
 | 
				
			||||||
 | 
					        std::vector<std::string>    rangeList;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
 | 
					        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct AccessTimes {
 | 
				
			||||||
 | 
					        std::vector<AccessTime> schedule;
 | 
				
			||||||
 | 
					        uint64_t        created=0;
 | 
				
			||||||
 | 
					        uint64_t        modified=0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
 | 
					        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct SubscriberDevice {
 | 
				
			||||||
 | 
					        std::string     name;
 | 
				
			||||||
 | 
					        std::string     description;
 | 
				
			||||||
 | 
					        std::string     macAddress;
 | 
				
			||||||
 | 
					        std::string     manufacturer;
 | 
				
			||||||
 | 
					        uint64_t        firstContact=0;
 | 
				
			||||||
 | 
					        uint64_t        lastContact=0;
 | 
				
			||||||
 | 
					        std::string     group;
 | 
				
			||||||
 | 
					        std::string     icon;
 | 
				
			||||||
 | 
					        bool            suspended=false;
 | 
				
			||||||
 | 
					        std::string     ip;
 | 
				
			||||||
 | 
					        std::vector<AccessTimes>    schedule;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
 | 
					        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct SubscriberDeviceList {
 | 
				
			||||||
 | 
					        std::vector<SubscriberDevice>   devices;
 | 
				
			||||||
 | 
					        uint64_t        created=0;
 | 
				
			||||||
 | 
					        uint64_t        modified=0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
 | 
					        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct Association {
 | 
				
			||||||
 | 
					        std::string     name;
 | 
				
			||||||
 | 
					        std::string     ssid;
 | 
				
			||||||
 | 
					        std::string     macAddress;
 | 
				
			||||||
 | 
					        int             rssi=0;
 | 
				
			||||||
 | 
					        int             power=0;
 | 
				
			||||||
 | 
					        std::string     ipv4;
 | 
				
			||||||
 | 
					        std::string     ipv6;
 | 
				
			||||||
 | 
					        uint64_t        tx=0;
 | 
				
			||||||
 | 
					        uint64_t        rx=0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
 | 
					        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct AssociationList {
 | 
				
			||||||
 | 
					        std::vector<Association>    associations;
 | 
				
			||||||
 | 
					        uint64_t        created=0;
 | 
				
			||||||
 | 
					        uint64_t        modified=0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
 | 
					        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct Client {
 | 
				
			||||||
 | 
					        std::string     macAddress;
 | 
				
			||||||
 | 
					        std::string     speed;
 | 
				
			||||||
 | 
					        std::string     mode;
 | 
				
			||||||
 | 
					        std::string     ipv4;
 | 
				
			||||||
 | 
					        std::string     ipv6;
 | 
				
			||||||
 | 
					        uint64_t        tx=0;
 | 
				
			||||||
 | 
					        uint64_t        rx=0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
 | 
					        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct ClientList {
 | 
				
			||||||
 | 
					        std::vector<Client> clients;
 | 
				
			||||||
 | 
					        uint64_t        created=0;
 | 
				
			||||||
 | 
					        uint64_t        modified=0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
 | 
					        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct Location {
 | 
				
			||||||
 | 
					        std::string                 buildingName;
 | 
				
			||||||
 | 
					        std::vector<std::string>    addressLines;
 | 
				
			||||||
 | 
					        std::string                 city;
 | 
				
			||||||
 | 
					        std::string                 state;
 | 
				
			||||||
 | 
					        std::string                 postal;
 | 
				
			||||||
 | 
					        std::string                 country;
 | 
				
			||||||
 | 
					        std::vector<std::string>    phones;
 | 
				
			||||||
 | 
					        std::vector<std::string>    mobiles;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
 | 
					        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct RadioHE {
 | 
				
			||||||
 | 
					        bool                        multipleBSSID = false;
 | 
				
			||||||
 | 
					        bool                        ema = false;
 | 
				
			||||||
 | 
					        uint64_t                    bssColor = 64;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
 | 
					        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct RadioRates {
 | 
				
			||||||
 | 
					        uint64_t                    beacon = 6000;
 | 
				
			||||||
 | 
					        uint64_t                    multicast = 24000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
 | 
					        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct RadioInformation {
 | 
				
			||||||
 | 
					        std::string             band;
 | 
				
			||||||
 | 
					        uint64_t                bandwidth;
 | 
				
			||||||
 | 
					        uint64_t                channel = 0 ;
 | 
				
			||||||
 | 
					        std::string             country;
 | 
				
			||||||
 | 
					        std::string             channelMode{"HE"};
 | 
				
			||||||
 | 
					        uint64_t                channelWidth = 80;
 | 
				
			||||||
 | 
					        std::string             requireMode;
 | 
				
			||||||
 | 
					        uint64_t                txpower=0;
 | 
				
			||||||
 | 
					        bool                    legacyRates = false;
 | 
				
			||||||
 | 
					        uint64_t                beaconInterval = 100;
 | 
				
			||||||
 | 
					        uint64_t                dtimPeriod = 2;
 | 
				
			||||||
 | 
					        uint64_t                maximumClients = 64;
 | 
				
			||||||
 | 
					        RadioRates              rates;
 | 
				
			||||||
 | 
					        RadioHE                 he;
 | 
				
			||||||
 | 
					        std::vector<std::string>    rawInfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
 | 
					        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct AccessPoint {
 | 
				
			||||||
 | 
					        std::string                 id;
 | 
				
			||||||
 | 
					        std::string                 macAddress;
 | 
				
			||||||
 | 
					        std::string                 name;
 | 
				
			||||||
 | 
					        std::string                 deviceType;
 | 
				
			||||||
 | 
					        SubscriberDeviceList        subscriberDevices;
 | 
				
			||||||
 | 
					        IPReservationList           ipReservations;
 | 
				
			||||||
 | 
					        Location                    address;
 | 
				
			||||||
 | 
					        WifiNetworkList             wifiNetworks;
 | 
				
			||||||
 | 
					        InternetConnection          internetConnection;
 | 
				
			||||||
 | 
					        HomeDeviceMode              deviceMode;
 | 
				
			||||||
 | 
					        DnsConfiguration            dnsConfiguration;
 | 
				
			||||||
 | 
					        std::vector<RadioInformation>   radios;
 | 
				
			||||||
 | 
					        bool                        automaticUpgrade = true;
 | 
				
			||||||
 | 
					        std::string                 configurationUUID;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
 | 
					        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct AccessPointList {
 | 
				
			||||||
 | 
					        std::vector<AccessPoint>   list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
 | 
					        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct SubscriberInfo {
 | 
				
			||||||
 | 
					        std::string                 id;
 | 
				
			||||||
 | 
					        std::string                 userId;
 | 
				
			||||||
 | 
					        std::string                 firstName;
 | 
				
			||||||
 | 
					        std::string                 initials;
 | 
				
			||||||
 | 
					        std::string                 lastName;
 | 
				
			||||||
 | 
					        std::string                 phoneNumber;
 | 
				
			||||||
 | 
					        std::string                 secondaryEmail;
 | 
				
			||||||
 | 
					        AccessPointList             accessPoints;
 | 
				
			||||||
 | 
					        Location                    serviceAddress;
 | 
				
			||||||
 | 
					        Location                    billingAddress;
 | 
				
			||||||
 | 
					        uint64_t                    created = 0;
 | 
				
			||||||
 | 
					        uint64_t                    modified = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void to_json(Poco::JSON::Object &Obj) const;
 | 
				
			||||||
 | 
					        bool from_json(const Poco::JSON::Object::Ptr &Obj);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif //OWSUB_RESTAPI_SUBOBJECTS_H
 | 
				
			||||||
@@ -20,12 +20,13 @@ namespace OpenWifi {
 | 
				
			|||||||
        if(Enabled_) {
 | 
					        if(Enabled_) {
 | 
				
			||||||
            Provider_ = MicroService::instance().ConfigGetString("smssender.provider","aws");
 | 
					            Provider_ = MicroService::instance().ConfigGetString("smssender.provider","aws");
 | 
				
			||||||
            if(Provider_=="aws") {
 | 
					            if(Provider_=="aws") {
 | 
				
			||||||
                ProviderImpl_ = std::make_unique<SMS_provider_aws>(Logger_);
 | 
					                ProviderImpl_ = std::make_unique<SMS_provider_aws>(Logger());
 | 
				
			||||||
            } else if(Provider_=="twilio") {
 | 
					            } else if(Provider_=="twilio") {
 | 
				
			||||||
                ProviderImpl_ = std::make_unique<SMS_provider_twilio>(Logger_);
 | 
					                ProviderImpl_ = std::make_unique<SMS_provider_twilio>(Logger());
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            Enabled_ = ProviderImpl_->Initialize();
 | 
					            Enabled_ = ProviderImpl_->Initialize();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -76,7 +77,7 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    bool SMSSender::Send(const std::string &PhoneNumber, const std::string &Message) {
 | 
					    bool SMSSender::Send(const std::string &PhoneNumber, const std::string &Message) {
 | 
				
			||||||
        if(!Enabled_) {
 | 
					        if(!Enabled_) {
 | 
				
			||||||
            Logger_.information("SMS has not been enabled. Messages cannot be sent.");
 | 
					            Logger().information("SMS has not been enabled. Messages cannot be sent.");
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return ProviderImpl_->Send(PhoneNumber,Message);
 | 
					        return ProviderImpl_->Send(PhoneNumber,Message);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,7 +17,7 @@ namespace OpenWifi {
 | 
				
			|||||||
        Region_ = MicroService::instance().ConfigGetString("smssender.aws.region","");
 | 
					        Region_ = MicroService::instance().ConfigGetString("smssender.aws.region","");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(SecretKey_.empty() || AccessKey_.empty() || Region_.empty()) {
 | 
					        if(SecretKey_.empty() || AccessKey_.empty() || Region_.empty()) {
 | 
				
			||||||
            Logger_.debug("SMSSender is disabled. Please provide key, secret, and region.");
 | 
					            Logger().debug("SMSSender is disabled. Please provide key, secret, and region.");
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        Running_=true;
 | 
					        Running_=true;
 | 
				
			||||||
@@ -51,16 +51,16 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            auto psms_out = sns.Publish(psms_req);
 | 
					            auto psms_out = sns.Publish(psms_req);
 | 
				
			||||||
            if (psms_out.IsSuccess()) {
 | 
					            if (psms_out.IsSuccess()) {
 | 
				
			||||||
                Logger_.debug(Poco::format("SMS sent to %s",PhoneNumber));
 | 
					                Logger().debug(Poco::format("SMS sent to %s",PhoneNumber));
 | 
				
			||||||
                return true;
 | 
					                return true;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            std::string ErrMsg{psms_out.GetError().GetMessage()};
 | 
					            std::string ErrMsg{psms_out.GetError().GetMessage()};
 | 
				
			||||||
            Logger_.debug(Poco::format("SMS NOT sent to %s: %s",PhoneNumber, ErrMsg));
 | 
					            Logger().debug(Poco::format("SMS NOT sent to %s: %s",PhoneNumber, ErrMsg));
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        } catch (...) {
 | 
					        } catch (...) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        Logger_.debug(Poco::format("SMS NOT sent to %s: failure in SMS service",PhoneNumber));
 | 
					        Logger().debug(Poco::format("SMS NOT sent to %s: failure in SMS service",PhoneNumber));
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,6 +21,7 @@ namespace OpenWifi {
 | 
				
			|||||||
        bool Stop() final ;
 | 
					        bool Stop() final ;
 | 
				
			||||||
        bool Send(const std::string &Number, const std::string &Message) final;
 | 
					        bool Send(const std::string &Number, const std::string &Message) final;
 | 
				
			||||||
        bool Running() final;
 | 
					        bool Running() final;
 | 
				
			||||||
 | 
					        inline Poco::Logger & Logger() { return Logger_; }
 | 
				
			||||||
    private:
 | 
					    private:
 | 
				
			||||||
        bool                                Running_=false;
 | 
					        bool                                Running_=false;
 | 
				
			||||||
        Poco::Logger                        &Logger_;
 | 
					        Poco::Logger                        &Logger_;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,7 +18,7 @@ namespace OpenWifi {
 | 
				
			|||||||
        PhoneNumber_ = MicroService::instance().ConfigGetString("smssender.twilio.phonenumber","");
 | 
					        PhoneNumber_ = MicroService::instance().ConfigGetString("smssender.twilio.phonenumber","");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(Sid_.empty() || Token_.empty() || PhoneNumber_.empty()) {
 | 
					        if(Sid_.empty() || Token_.empty() || PhoneNumber_.empty()) {
 | 
				
			||||||
            Logger_.debug("SMSSender is disabled. Please provide SID, TOKEN, and PHONE NUMBER.");
 | 
					            Logger().debug("SMSSender is disabled. Please provide SID, TOKEN, and PHONE NUMBER.");
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        Running_=true;
 | 
					        Running_=true;
 | 
				
			||||||
@@ -64,12 +64,12 @@ namespace OpenWifi {
 | 
				
			|||||||
        std::istream& rs = session.receiveResponse(res);
 | 
					        std::istream& rs = session.receiveResponse(res);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(res.getStatus()==Poco::Net::HTTPResponse::HTTP_OK) {
 | 
					        if(res.getStatus()==Poco::Net::HTTPResponse::HTTP_OK) {
 | 
				
			||||||
            Logger_.information(Poco::format("Message sent to %s", PhoneNumber));
 | 
					            Logger().information(Poco::format("Message sent to %s", PhoneNumber));
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            std::ostringstream os;
 | 
					            std::ostringstream os;
 | 
				
			||||||
            Poco::StreamCopier::copyStream(rs,os);
 | 
					            Poco::StreamCopier::copyStream(rs,os);
 | 
				
			||||||
            Logger_.information(Poco::format("Message was not to %s: Error:%s", PhoneNumber, os.str()));
 | 
					            Logger().information(Poco::format("Message was not to %s: Error:%s", PhoneNumber, os.str()));
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,6 +17,7 @@ namespace OpenWifi {
 | 
				
			|||||||
        bool Stop() final ;
 | 
					        bool Stop() final ;
 | 
				
			||||||
        bool Send(const std::string &Number, const std::string &Message) final;
 | 
					        bool Send(const std::string &Number, const std::string &Message) final;
 | 
				
			||||||
        bool Running() final;
 | 
					        bool Running() final;
 | 
				
			||||||
 | 
					        inline Poco::Logger & Logger() { return Logger_; }
 | 
				
			||||||
    private:
 | 
					    private:
 | 
				
			||||||
        bool                                Running_=false;
 | 
					        bool                                Running_=false;
 | 
				
			||||||
        Poco::Logger                        &Logger_;
 | 
					        Poco::Logger                        &Logger_;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -49,7 +49,7 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    void SMTPMailerService::reinitialize(Poco::Util::Application &self) {
 | 
					    void SMTPMailerService::reinitialize(Poco::Util::Application &self) {
 | 
				
			||||||
        MicroService::instance().LoadConfigurationFile();
 | 
					        MicroService::instance().LoadConfigurationFile();
 | 
				
			||||||
        Logger_.information("Reinitializing.");
 | 
					        Logger().information("Reinitializing.");
 | 
				
			||||||
        LoadMyConfig();
 | 
					        LoadMyConfig();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -83,14 +83,14 @@ namespace OpenWifi {
 | 
				
			|||||||
                uint64_t Now = std::time(nullptr);
 | 
					                uint64_t Now = std::time(nullptr);
 | 
				
			||||||
                if((i->LastTry==0 || (Now-i->LastTry)>MailRetry_)) {
 | 
					                if((i->LastTry==0 || (Now-i->LastTry)>MailRetry_)) {
 | 
				
			||||||
                    if (SendIt(*i)) {
 | 
					                    if (SendIt(*i)) {
 | 
				
			||||||
                        Logger_.information(Poco::format("Attempting to deliver for mail '%s'.", Recipient));
 | 
					                        Logger().information(Poco::format("Attempting to deliver for mail '%s'.", Recipient));
 | 
				
			||||||
                        i = Messages_.erase(i);
 | 
					                        i = Messages_.erase(i);
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                        i->LastTry = Now;
 | 
					                        i->LastTry = Now;
 | 
				
			||||||
                        ++i;
 | 
					                        ++i;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                } else if ((Now-i->Posted)>MailAbandon_) {
 | 
					                } else if ((Now-i->Posted)>MailAbandon_) {
 | 
				
			||||||
                    Logger_.information(Poco::format("Mail for '%s' has timed out and will not be sent.", Recipient));
 | 
					                    Logger().information(Poco::format("Mail for '%s' has timed out and will not be sent.", Recipient));
 | 
				
			||||||
                    i = Messages_.erase(i);
 | 
					                    i = Messages_.erase(i);
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    ++i;
 | 
					                    ++i;
 | 
				
			||||||
@@ -121,7 +121,7 @@ namespace OpenWifi {
 | 
				
			|||||||
                TheSender = Sender_ ;
 | 
					                TheSender = Sender_ ;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            Message.setSender( TheSender );
 | 
					            Message.setSender( TheSender );
 | 
				
			||||||
            Logger_.information(Poco::format("Sending message to:%s from %s",Recipient,TheSender));
 | 
					            Logger().information(Poco::format("Sending message to:%s from %s",Recipient,TheSender));
 | 
				
			||||||
            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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -145,7 +145,7 @@ namespace OpenWifi {
 | 
				
			|||||||
                    Poco::StreamCopier::copyStream(IF, OS);
 | 
					                    Poco::StreamCopier::copyStream(IF, OS);
 | 
				
			||||||
                    Message.addAttachment("logo", new Poco::Net::StringPartSource(OS.str(), "image/png"));
 | 
					                    Message.addAttachment("logo", new Poco::Net::StringPartSource(OS.str(), "image/png"));
 | 
				
			||||||
                } catch (...) {
 | 
					                } catch (...) {
 | 
				
			||||||
                    Logger_.warning(Poco::format("Cannot add '%s' logo in email",AuthService::GetLogoAssetFileName()));
 | 
					                    Logger().warning(Poco::format("Cannot add '%s' logo in email",AuthService::GetLogoAssetFileName()));
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -172,10 +172,10 @@ namespace OpenWifi {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        catch (const Poco::Exception& E)
 | 
					        catch (const Poco::Exception& E)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            Logger_.log(E);
 | 
					            Logger().log(E);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        catch (const std::exception &E) {
 | 
					        catch (const std::exception &E) {
 | 
				
			||||||
            Logger_.warning(Poco::format("Cannot send message to:%s, error: %s",Recipient, E.what()));
 | 
					            Logger().warning(Poco::format("Cannot send message to:%s, error: %s",Recipient, E.what()));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										37
									
								
								src/SpecialUserHelpers.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								src/SpecialUserHelpers.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Created by stephane bourque on 2021-12-28.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "StorageService.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    namespace SpecialUserHelpers {
 | 
				
			||||||
 | 
					        static inline std::string NewDefaultUseridStockUUID{"11111111-0000-0000-6666-999999999999"};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        inline bool InitializeDefaultUser() {
 | 
				
			||||||
 | 
					            SecurityObjects::UserInfo U;
 | 
				
			||||||
 | 
					            bool DefaultUserCreated = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            AppServiceRegistry().Get("defaultusercreated", DefaultUserCreated);
 | 
				
			||||||
 | 
					            if (!StorageService()->UserDB().GetUserById(NewDefaultUseridStockUUID, U) && !DefaultUserCreated) {
 | 
				
			||||||
 | 
					                U.currentPassword = MicroService::instance().ConfigGetString("authentication.default.password", "");
 | 
				
			||||||
 | 
					                U.lastPasswords.push_back(U.currentPassword);
 | 
				
			||||||
 | 
					                U.email = MicroService::instance().ConfigGetString("authentication.default.username", "");
 | 
				
			||||||
 | 
					                U.id = NewDefaultUseridStockUUID;
 | 
				
			||||||
 | 
					                U.userRole = SecurityObjects::ROOT;
 | 
				
			||||||
 | 
					                U.creationDate = std::time(nullptr);
 | 
				
			||||||
 | 
					                U.validated = true;
 | 
				
			||||||
 | 
					                U.name = "Default User";
 | 
				
			||||||
 | 
					                U.description = "Default user should be deleted.";
 | 
				
			||||||
 | 
					                U.changePassword = true;
 | 
				
			||||||
 | 
					                StorageService()->UserDB().CreateUser("SYSTEM", U, true);
 | 
				
			||||||
 | 
					                AppServiceRegistry().Set("defaultusercreated", true);
 | 
				
			||||||
 | 
					                return true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -7,15 +7,46 @@
 | 
				
			|||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "StorageService.h"
 | 
					#include "StorageService.h"
 | 
				
			||||||
 | 
					#include "SpecialUserHelpers.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int Storage::Start() {
 | 
					    int StorageService::Start() {
 | 
				
			||||||
		std::lock_guard		Guard(Mutex_);
 | 
							std::lock_guard		Guard(Mutex_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		StorageClass::Start();
 | 
							StorageClass::Start();
 | 
				
			||||||
		Create_Tables();
 | 
					
 | 
				
			||||||
		InitializeDefaultUser();
 | 
					        UserCache_ = std::make_unique<OpenWifi::UserCache>(64,1200000,true);
 | 
				
			||||||
 | 
					        SubCache_ = std::make_unique<OpenWifi::UserCache>(2048,1200000,false);
 | 
				
			||||||
 | 
					        UserTokenCache_ = std::make_unique<OpenWifi::TokenCache>(64,1200000, true);
 | 
				
			||||||
 | 
					        SubTokenCache_ = std::make_unique<OpenWifi::TokenCache>(2048,1200000,false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        UserDB_ = std::make_unique<OpenWifi::BaseUserDB>("Users", "usr", dbType_,*Pool_, Logger(), UserCache_.get(), true);
 | 
				
			||||||
 | 
					        SubDB_ = std::make_unique<OpenWifi::BaseUserDB>("Subscribers", "sub", dbType_,*Pool_, Logger(), SubCache_.get(), false);
 | 
				
			||||||
 | 
					        UserTokenDB_ = std::make_unique<OpenWifi::BaseTokenDB>("Tokens", "tok", dbType_,*Pool_, Logger(), UserTokenCache_.get(), true);
 | 
				
			||||||
 | 
					        SubTokenDB_ = std::make_unique<OpenWifi::BaseTokenDB>("SubTokens", "stk", dbType_,*Pool_, Logger(), SubTokenCache_.get(), false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        PreferencesDB_ = std::make_unique<OpenWifi::PreferencesDB>("Preferences", "pre", dbType_,*Pool_, Logger());
 | 
				
			||||||
 | 
					        SubPreferencesDB_ = std::make_unique<OpenWifi::PreferencesDB>("SubPreferences", "prs", dbType_,*Pool_, Logger());
 | 
				
			||||||
 | 
					        ActionLinksDB_ = std::make_unique<OpenWifi::ActionLinkDB>("Actions", "act", dbType_,*Pool_, Logger());
 | 
				
			||||||
 | 
					        AvatarDB_ = std::make_unique<OpenWifi::AvatarDB>("Avatars", "ava", dbType_,*Pool_, Logger());
 | 
				
			||||||
 | 
					        SubAvatarDB_ = std::make_unique<OpenWifi::AvatarDB>("SubAvatars", "avs", dbType_,*Pool_, Logger());
 | 
				
			||||||
 | 
					        LoginDB_ = std::make_unique<OpenWifi::LoginDB>("Logins", "lin", dbType_,*Pool_, Logger());
 | 
				
			||||||
 | 
					        SubLoginDB_ = std::make_unique<OpenWifi::LoginDB>("SubLogins", "lis", dbType_,*Pool_, Logger());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        UserDB_->Create();
 | 
				
			||||||
 | 
					        SubDB_->Create();
 | 
				
			||||||
 | 
					        UserTokenDB_->Create();
 | 
				
			||||||
 | 
					        SubTokenDB_->Create();
 | 
				
			||||||
 | 
					        ActionLinksDB_->Create();
 | 
				
			||||||
 | 
					        PreferencesDB_->Create();
 | 
				
			||||||
 | 
					        SubPreferencesDB_->Create();
 | 
				
			||||||
 | 
					        AvatarDB_->Create();
 | 
				
			||||||
 | 
					        SubAvatarDB_->Create();
 | 
				
			||||||
 | 
					        LoginDB_->Create();
 | 
				
			||||||
 | 
					        SubLoginDB_->Create();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							OpenWifi::SpecialUserHelpers::InitializeDefaultUser();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Archivercallback_ = std::make_unique<Poco::TimerCallback<Archiver>>(Archiver_,&Archiver::onTimer);
 | 
							Archivercallback_ = std::make_unique<Poco::TimerCallback<Archiver>>(Archiver_,&Archiver::onTimer);
 | 
				
			||||||
		Timer_.setStartInterval( 5 * 60 * 1000);  // first run in 5 minutes
 | 
							Timer_.setStartInterval( 5 * 60 * 1000);  // first run in 5 minutes
 | 
				
			||||||
@@ -25,8 +56,8 @@ namespace OpenWifi {
 | 
				
			|||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void Storage::Stop() {
 | 
					    void StorageService::Stop() {
 | 
				
			||||||
        Logger_.notice("Stopping.");
 | 
					        Logger().notice("Stopping.");
 | 
				
			||||||
        Timer_.stop();
 | 
					        Timer_.stop();
 | 
				
			||||||
        StorageClass::Stop();
 | 
					        StorageClass::Stop();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -34,9 +65,10 @@ namespace OpenWifi {
 | 
				
			|||||||
    void Archiver::onTimer(Poco::Timer &timer) {
 | 
					    void Archiver::onTimer(Poco::Timer &timer) {
 | 
				
			||||||
        Poco::Logger &logger = Poco::Logger::get("STORAGE-ARCHIVER");
 | 
					        Poco::Logger &logger = Poco::Logger::get("STORAGE-ARCHIVER");
 | 
				
			||||||
        logger.information("Squiggy the DB: removing old tokens.");
 | 
					        logger.information("Squiggy the DB: removing old tokens.");
 | 
				
			||||||
        StorageService()->CleanExpiredTokens();
 | 
					        StorageService()->SubTokenDB().CleanExpiredTokens();
 | 
				
			||||||
 | 
					        StorageService()->UserTokenDB().CleanExpiredTokens();
 | 
				
			||||||
        logger.information("Squiggy the DB: removing old actionLinks.");
 | 
					        logger.information("Squiggy the DB: removing old actionLinks.");
 | 
				
			||||||
        StorageService()->CleanOldActionLinks();
 | 
					        StorageService()->ActionLinksDB().CleanOldActionLinks();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,138 +15,69 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "Poco/Timer.h"
 | 
					#include "Poco/Timer.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "storage/orm_users.h"
 | 
				
			||||||
 | 
					#include "storage/orm_tokens.h"
 | 
				
			||||||
 | 
					#include "storage/orm_preferences.h"
 | 
				
			||||||
 | 
					#include "storage/orm_actionLinks.h"
 | 
				
			||||||
 | 
					#include "storage/orm_avatar.h"
 | 
				
			||||||
 | 
					#include "storage/orm_logins.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static const std::string AllEmailTemplatesFieldsForCreation {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    static const std::string AllEmailTemplatesFieldsForSelect {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    static const std::string AllEmailTemplatesFieldsForUpdate {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    class Archiver {
 | 
					    class Archiver {
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
        void onTimer(Poco::Timer & timer);
 | 
					        void onTimer(Poco::Timer & timer);
 | 
				
			||||||
    private:
 | 
					    private:
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Storage : public StorageClass {
 | 
					    class StorageService : public StorageClass {
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        enum AUTH_ERROR {
 | 
					        static auto instance() {
 | 
				
			||||||
            SUCCESS,
 | 
					            static auto instance_ = new StorageService;
 | 
				
			||||||
            PASSWORD_CHANGE_REQUIRED,
 | 
					 | 
				
			||||||
            PASSWORD_DOES_NOT_MATCH,
 | 
					 | 
				
			||||||
            PASSWORD_ALREADY_USED,
 | 
					 | 
				
			||||||
            USERNAME_PENDING_VERIFICATION,
 | 
					 | 
				
			||||||
            PASSWORD_INVALID,
 | 
					 | 
				
			||||||
            INTERNAL_ERROR
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        enum USER_TYPE {
 | 
					 | 
				
			||||||
            UNKNOWN, ROOT, ADMIN, SUBSCRIBER, CSR, SYSTEM, SPECIAL
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        typedef std::string USER_ID_TYPE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        static USER_TYPE to_userType(const std::string &U) {
 | 
					 | 
				
			||||||
            if (U=="root")
 | 
					 | 
				
			||||||
                return ROOT;
 | 
					 | 
				
			||||||
            else if (U=="admin")
 | 
					 | 
				
			||||||
                return ADMIN;
 | 
					 | 
				
			||||||
            else if (U=="subscriber")
 | 
					 | 
				
			||||||
                return SUBSCRIBER;
 | 
					 | 
				
			||||||
            else if (U=="csr")
 | 
					 | 
				
			||||||
                return CSR;
 | 
					 | 
				
			||||||
            else if (U=="system")
 | 
					 | 
				
			||||||
                return SYSTEM;
 | 
					 | 
				
			||||||
            else if (U=="SPECIAL")
 | 
					 | 
				
			||||||
                return SPECIAL;
 | 
					 | 
				
			||||||
            return UNKNOWN;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        static std::string from_userType(USER_TYPE U) {
 | 
					 | 
				
			||||||
            switch(U) {
 | 
					 | 
				
			||||||
                case ROOT: return "root";
 | 
					 | 
				
			||||||
                case ADMIN: return "admin";
 | 
					 | 
				
			||||||
                case SUBSCRIBER: return "subscriber";
 | 
					 | 
				
			||||||
                case CSR: return "csr";
 | 
					 | 
				
			||||||
                case SYSTEM: return "system";
 | 
					 | 
				
			||||||
                case SPECIAL: return "special";
 | 
					 | 
				
			||||||
                case UNKNOWN:
 | 
					 | 
				
			||||||
                default: return "unknown";
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        static Storage *instance() {
 | 
					 | 
				
			||||||
            static auto * instance_ = new Storage;
 | 
					 | 
				
			||||||
            return instance_;
 | 
					            return instance_;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        int 	Start() override;
 | 
					        int 	Start() override;
 | 
				
			||||||
        void 	Stop() override;
 | 
					        void 	Stop() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /*
 | 
					        OpenWifi::BaseUserDB & UserDB() { return *UserDB_; }
 | 
				
			||||||
         *  All user management functions
 | 
					        OpenWifi::BaseUserDB & SubDB() { return *SubDB_; }
 | 
				
			||||||
         */
 | 
					        OpenWifi::BaseTokenDB & UserTokenDB() { return *UserTokenDB_; }
 | 
				
			||||||
        bool InitializeDefaultUser();
 | 
					        OpenWifi::BaseTokenDB & SubTokenDB() { return *SubTokenDB_; }
 | 
				
			||||||
        bool CreateUser(const std::string & Admin, SecurityObjects::UserInfo & NewUser, bool PasswordHashedAlready = false);
 | 
					        OpenWifi::PreferencesDB & PreferencesDB() { return *PreferencesDB_; }
 | 
				
			||||||
        bool GetUserByEmail(std::string & email, SecurityObjects::UserInfo & User);
 | 
					        OpenWifi::PreferencesDB & SubPreferencesDB() { return *SubPreferencesDB_; }
 | 
				
			||||||
        bool GetUserById(USER_ID_TYPE & Id, SecurityObjects::UserInfo & User);
 | 
					        OpenWifi::ActionLinkDB & ActionLinksDB() { return *ActionLinksDB_; }
 | 
				
			||||||
        bool DeleteUser(const std::string & Admin, USER_ID_TYPE & Id);
 | 
					        OpenWifi::AvatarDB & AvatarDB() { return *AvatarDB_; }
 | 
				
			||||||
        bool SetOwner(const std::string & Admin, USER_ID_TYPE & Id, const std::string &Owner);
 | 
					        OpenWifi::AvatarDB & SubAvatarDB() { return *SubAvatarDB_; }
 | 
				
			||||||
        bool SetLocation(const std::string & Admin, USER_ID_TYPE & Id, const std::string &Location);
 | 
					        OpenWifi::LoginDB & LoginDB() { return *LoginDB_; }
 | 
				
			||||||
        AUTH_ERROR ChangePassword(const std::string & Admin, USER_ID_TYPE & Id, const std::string &OldPassword, const std::string &NewPassword);
 | 
					        OpenWifi::LoginDB & SubLoginDB() { return *SubLoginDB_; }
 | 
				
			||||||
        bool AddNotes(const std::string & Admin, USER_ID_TYPE & Id, const std::string &Notes);
 | 
					 | 
				
			||||||
        bool SetPolicyChange(const std::string & Admin, USER_ID_TYPE & Id, const std::string &NewPolicy);
 | 
					 | 
				
			||||||
        bool UpdateUserInfo(const std::string & Admin, USER_ID_TYPE & Id, SecurityObjects::UserInfo &UInfo);
 | 
					 | 
				
			||||||
        bool GetUsers( uint64_t Offset, uint64_t Limit, SecurityObjects::UserInfoVec & Users);
 | 
					 | 
				
			||||||
        bool SetLastLogin(USER_ID_TYPE & Id);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        bool SetAvatar(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 AddToken(std::string &UserId, 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 CleanExpiredTokens();
 | 
					 | 
				
			||||||
        bool RevokeAllTokens( std::string & UserName );
 | 
					 | 
				
			||||||
        bool GetToken(std::string &Token, SecurityObjects::UserInfoAndPolicy &UInfo, uint64_t &RevocationDate);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /*
 | 
					 | 
				
			||||||
         *  All ActionLinks functions
 | 
					 | 
				
			||||||
         */
 | 
					 | 
				
			||||||
        bool CreateAction( SecurityObjects::ActionLink & A);
 | 
					 | 
				
			||||||
        bool DeleteAction(std::string &ActionId);
 | 
					 | 
				
			||||||
        bool CompleteAction(std::string &ActionId);
 | 
					 | 
				
			||||||
        bool CancelAction(std::string &ActionId);
 | 
					 | 
				
			||||||
        bool SentAction(std::string &ActionId);
 | 
					 | 
				
			||||||
        bool GetActionLink(std::string &ActionId, SecurityObjects::ActionLink &A);
 | 
					 | 
				
			||||||
        bool GetActions(std::vector<SecurityObjects::ActionLink> &Links, uint64_t Max=200);
 | 
					 | 
				
			||||||
        void CleanOldActionLinks();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  private:
 | 
						  private:
 | 
				
			||||||
        int Create_Tables();
 | 
					
 | 
				
			||||||
        int Create_UserTable();
 | 
					        std::unique_ptr<OpenWifi::BaseUserDB>           UserDB_;
 | 
				
			||||||
        int Create_AvatarTable();
 | 
					        std::unique_ptr<OpenWifi::BaseUserDB>           SubDB_;
 | 
				
			||||||
        int Create_TokensTable();
 | 
					        std::unique_ptr<OpenWifi::BaseTokenDB>          UserTokenDB_;
 | 
				
			||||||
        int Create_ActionLinkTable();
 | 
					        std::unique_ptr<OpenWifi::BaseTokenDB>          SubTokenDB_;
 | 
				
			||||||
 | 
					        std::unique_ptr<OpenWifi::PreferencesDB>        PreferencesDB_;
 | 
				
			||||||
 | 
					        std::unique_ptr<OpenWifi::PreferencesDB>        SubPreferencesDB_;
 | 
				
			||||||
 | 
					        std::unique_ptr<OpenWifi::ActionLinkDB>         ActionLinksDB_;
 | 
				
			||||||
 | 
					        std::unique_ptr<OpenWifi::AvatarDB>             AvatarDB_;
 | 
				
			||||||
 | 
					        std::unique_ptr<OpenWifi::AvatarDB>             SubAvatarDB_;
 | 
				
			||||||
 | 
					        std::unique_ptr<OpenWifi::LoginDB>              LoginDB_;
 | 
				
			||||||
 | 
					        std::unique_ptr<OpenWifi::LoginDB>              SubLoginDB_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::unique_ptr<OpenWifi::UserCache>            UserCache_;
 | 
				
			||||||
 | 
					        std::unique_ptr<OpenWifi::UserCache>            SubCache_;
 | 
				
			||||||
 | 
					        std::unique_ptr<OpenWifi::TokenCache>           UserTokenCache_;
 | 
				
			||||||
 | 
					        std::unique_ptr<OpenWifi::TokenCache>           SubTokenCache_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Poco::Timer                     Timer_;
 | 
					        Poco::Timer                     Timer_;
 | 
				
			||||||
        Archiver                        Archiver_;
 | 
					        Archiver                        Archiver_;
 | 
				
			||||||
        std::unique_ptr<Poco::TimerCallback<Archiver>>   Archivercallback_;
 | 
					        std::unique_ptr<Poco::TimerCallback<Archiver>>   Archivercallback_;
 | 
				
			||||||
 | 
					 | 
				
			||||||
        /// This is to support a mistake that was deployed...
 | 
					 | 
				
			||||||
        void ReplaceOldDefaultUUID();
 | 
					 | 
				
			||||||
   };
 | 
					   };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    inline Storage * StorageService() { return Storage::instance(); };
 | 
					    inline auto StorageService() { return StorageService::instance(); };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}  // namespace
 | 
					}  // namespace
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										173
									
								
								src/TotpCache.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										173
									
								
								src/TotpCache.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,173 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Created by stephane bourque on 2022-01-31.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef OWSEC_TOTPCACHE_H
 | 
				
			||||||
 | 
					#define OWSEC_TOTPCACHE_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "framework/MicroService.h"
 | 
				
			||||||
 | 
					#include "seclibs/cpptotp/bytes.h"
 | 
				
			||||||
 | 
					#include "seclibs/qrcode/qrcodegen.hpp"
 | 
				
			||||||
 | 
					#include "seclibs/cpptotp/otp.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class TotpCache : public SubSystemServer {
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        struct Entry {
 | 
				
			||||||
 | 
					            bool        Subscriber=false;
 | 
				
			||||||
 | 
					            uint64_t    Start = 0;
 | 
				
			||||||
 | 
					            uint64_t    Done = 0 ;
 | 
				
			||||||
 | 
					            uint64_t    Verifications = 0 ;
 | 
				
			||||||
 | 
					            std::string Secret;
 | 
				
			||||||
 | 
					            std::string QRCode;
 | 
				
			||||||
 | 
					            std::string LastCode;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        static auto instance() {
 | 
				
			||||||
 | 
					            static auto instance = new TotpCache;
 | 
				
			||||||
 | 
					            return instance;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        static std::string GenerateSecret(uint Size, std::string & Base32Secret) {
 | 
				
			||||||
 | 
					            std::string R;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for(;Size;Size--) {
 | 
				
			||||||
 | 
					                R += (char) MicroService::instance().Random(33,127);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            Base32Secret = CppTotp::Bytes::toBase32( CppTotp::Bytes::ByteString{ (const u_char *)R.c_str()});
 | 
				
			||||||
 | 
					            return R;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        std::string GenerateQRCode(const std::string &Secret, const std::string &email) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            std::string uri{
 | 
				
			||||||
 | 
					                "otpauth://totp/" + Issuer_ + ":" +
 | 
				
			||||||
 | 
					                email + "?secret=" + Secret + "&issuer=" + Issuer_
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            qrcodegen::QrCode qr0 = qrcodegen::QrCode::encodeText(uri.c_str(), qrcodegen::QrCode::Ecc::MEDIUM);
 | 
				
			||||||
 | 
					            std::string svg = qrcodegen::toSvgString(qr0, 4);  // See QrCodeGeneratorDemo
 | 
				
			||||||
 | 
					            return svg;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        static bool ValidateCode( const std::string &Secret, const std::string &Code, std::string & Expecting) {
 | 
				
			||||||
 | 
					            uint64_t Now = std::time(nullptr);
 | 
				
			||||||
 | 
					            uint32_t p = CppTotp::totp(CppTotp::Bytes::ByteString{ (const u_char *)Secret.c_str()}, Now, 0, 30, 6);
 | 
				
			||||||
 | 
					            char buffer[16];
 | 
				
			||||||
 | 
					            sprintf(buffer,"%06u",p);
 | 
				
			||||||
 | 
					            Expecting = buffer;
 | 
				
			||||||
 | 
					            return Code == buffer;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int Start() override {
 | 
				
			||||||
 | 
					            Issuer_ = MicroService::instance().ConfigGetString("totp.issuer","OpenWiFi");
 | 
				
			||||||
 | 
					            return 0;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void Stop() override {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        inline bool StartValidation(const SecurityObjects::UserInfo &User, bool Subscriber, std::string & QRCode, bool Reset) {
 | 
				
			||||||
 | 
					            auto Hint = Cache_.find(User.id);
 | 
				
			||||||
 | 
					            if(Hint!=Cache_.end() && Hint->second.Subscriber==Subscriber) {
 | 
				
			||||||
 | 
					                if(Reset) {
 | 
				
			||||||
 | 
					                    std::string Base32Secret;
 | 
				
			||||||
 | 
					                    Hint->second.Subscriber = Subscriber;
 | 
				
			||||||
 | 
					                    Hint->second.Start = std::time(nullptr);
 | 
				
			||||||
 | 
					                    Hint->second.Done = 0;
 | 
				
			||||||
 | 
					                    Hint->second.Verifications = 0;
 | 
				
			||||||
 | 
					                    Hint->second.Secret = GenerateSecret(20,Base32Secret);
 | 
				
			||||||
 | 
					                    Hint->second.QRCode = QRCode = GenerateQRCode(Base32Secret, User.email);
 | 
				
			||||||
 | 
					                    Hint->second.LastCode.clear();
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    QRCode = Hint->second.QRCode;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                return true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            std::string Base32Secret;
 | 
				
			||||||
 | 
					            auto Secret = GenerateSecret(20, Base32Secret);
 | 
				
			||||||
 | 
					            QRCode = GenerateQRCode(Base32Secret, User.email);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Entry E{ .Subscriber = Subscriber,
 | 
				
			||||||
 | 
					                     .Start = (uint64_t )std::time(nullptr),
 | 
				
			||||||
 | 
					                     .Done = 0,
 | 
				
			||||||
 | 
					                     .Verifications = 0,
 | 
				
			||||||
 | 
					                     .Secret = Secret,
 | 
				
			||||||
 | 
					                     .QRCode = QRCode
 | 
				
			||||||
 | 
					                     };
 | 
				
			||||||
 | 
					            Cache_[User.id] = E;
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        inline bool ContinueValidation(const SecurityObjects::UserInfo &User, bool Subscriber, const std::string & Code,
 | 
				
			||||||
 | 
					                                       uint64_t &NextIndex, bool &MoreCodes, uint64_t & ErrorCode, std::string & ErrorText ) {
 | 
				
			||||||
 | 
					            auto Hint = Cache_.find(User.id);
 | 
				
			||||||
 | 
					            uint64_t Now = std::time(nullptr);
 | 
				
			||||||
 | 
					            ErrorCode = 0;
 | 
				
			||||||
 | 
					            if(Hint!=Cache_.end() && Subscriber==Hint->second.Subscriber && (Now-Hint->second.Start)<(15*60)) {
 | 
				
			||||||
 | 
					                std::string Expecting;
 | 
				
			||||||
 | 
					                if (NextIndex == 1 && Hint->second.Verifications == 0 && ValidateCode(Hint->second.Secret, Code, Expecting)) {
 | 
				
			||||||
 | 
					                    NextIndex++;
 | 
				
			||||||
 | 
					                    Hint->second.Verifications++;
 | 
				
			||||||
 | 
					                    MoreCodes = true;
 | 
				
			||||||
 | 
					                    Hint->second.LastCode = Code;
 | 
				
			||||||
 | 
					                    return true;
 | 
				
			||||||
 | 
					                } else if (NextIndex == 2 && Hint->second.Verifications == 1 && Code != Hint->second.LastCode &&
 | 
				
			||||||
 | 
					                            ValidateCode(Hint->second.Secret, Code, Expecting) ) {
 | 
				
			||||||
 | 
					                    MoreCodes = false;
 | 
				
			||||||
 | 
					                    Hint->second.Done = Now;
 | 
				
			||||||
 | 
					                    return true;
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    if(!ValidateCode(Hint->second.Secret, Code, Expecting)) {
 | 
				
			||||||
 | 
					                        ErrorCode = 1;
 | 
				
			||||||
 | 
					                        ErrorText = "Invalid code.";
 | 
				
			||||||
 | 
					                        return false;
 | 
				
			||||||
 | 
					                    } else if(NextIndex!=1 && NextIndex != 2) {
 | 
				
			||||||
 | 
					                        ErrorCode = 2;
 | 
				
			||||||
 | 
					                        ErrorText = "Invalid Index";
 | 
				
			||||||
 | 
					                        return false;
 | 
				
			||||||
 | 
					                    } else if(Code == Hint->second.LastCode) {
 | 
				
			||||||
 | 
					                        ErrorCode = 3;
 | 
				
			||||||
 | 
					                        ErrorText = "Code is repeated. Must be new code.";
 | 
				
			||||||
 | 
					                        return false;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    ErrorCode = 5;
 | 
				
			||||||
 | 
					                    ErrorText = "Invalid protocol sequence.";
 | 
				
			||||||
 | 
					                    return false;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                ErrorCode = 4;
 | 
				
			||||||
 | 
					                ErrorText = "No validation session present.";
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        inline bool CompleteValidation(const SecurityObjects::UserInfo &User, bool Subscriber, std::string & Secret) {
 | 
				
			||||||
 | 
					            auto Hint = Cache_.find(User.id);
 | 
				
			||||||
 | 
					            uint64_t Now = std::time(nullptr);
 | 
				
			||||||
 | 
					            if(Hint!=Cache_.end() && Subscriber==Hint->second.Subscriber && (Now-Hint->second.Start)<(15*60) && Hint->second.Done!=0) {
 | 
				
			||||||
 | 
					                Secret = Hint->second.Secret;
 | 
				
			||||||
 | 
					                Cache_.erase(Hint);
 | 
				
			||||||
 | 
					                return true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private:
 | 
				
			||||||
 | 
					        std::map<std::string,Entry>     Cache_;
 | 
				
			||||||
 | 
					        std::string                     Issuer_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        TotpCache() noexcept:
 | 
				
			||||||
 | 
					            SubSystemServer("TOTP-system", "TOTP-SVR", "totp") {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline auto TotpCache() { return TotpCache::instance(); }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif //OWSEC_TOTPCACHE_H
 | 
				
			||||||
							
								
								
									
										93
									
								
								src/framework/API_Proxy.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								src/framework/API_Proxy.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,93 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Created by stephane bourque on 2021-11-30.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "framework/MicroService.h"
 | 
				
			||||||
 | 
					#include "Poco/JSON/Parser.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					    inline void API_Proxy( Poco::Logger &Logger,
 | 
				
			||||||
 | 
					                    Poco::Net::HTTPServerRequest *Request,
 | 
				
			||||||
 | 
					                    Poco::Net::HTTPServerResponse *Response,
 | 
				
			||||||
 | 
					                    const char * ServiceType,
 | 
				
			||||||
 | 
					                    const char * PathRewrite,
 | 
				
			||||||
 | 
					                    uint64_t msTimeout_ = 10000 ) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            auto Services = MicroService::instance().GetServices(ServiceType);
 | 
				
			||||||
 | 
					            for(auto const &Svc:Services) {
 | 
				
			||||||
 | 
					                Poco::URI   SourceURI(Request->getURI());
 | 
				
			||||||
 | 
					                Poco::URI	DestinationURI(Svc.PrivateEndPoint);
 | 
				
			||||||
 | 
					                DestinationURI.setPath(PathRewrite);
 | 
				
			||||||
 | 
					                DestinationURI.setQuery(SourceURI.getQuery());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // std::cout << "     Source: " << SourceURI.toString() << std::endl;
 | 
				
			||||||
 | 
					                // std::cout << "Destination: " << DestinationURI.toString() << std::endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                Poco::Net::HTTPSClientSession Session(DestinationURI.getHost(), DestinationURI.getPort());
 | 
				
			||||||
 | 
					                Session.setKeepAlive(true);
 | 
				
			||||||
 | 
					                Session.setTimeout(Poco::Timespan(msTimeout_/1000, msTimeout_ % 1000));
 | 
				
			||||||
 | 
					                Poco::Net::HTTPRequest ProxyRequest(Request->getMethod(),
 | 
				
			||||||
 | 
					                                                    DestinationURI.getPathAndQuery(),
 | 
				
			||||||
 | 
					                                                    Poco::Net::HTTPMessage::HTTP_1_1);
 | 
				
			||||||
 | 
					                if(Request->has("Authorization")) {
 | 
				
			||||||
 | 
					                    ProxyRequest.add("Authorization", Request->get("Authorization"));
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    ProxyRequest.add("X-API-KEY", Svc.AccessKey);
 | 
				
			||||||
 | 
					                    ProxyRequest.add("X-INTERNAL-NAME", MicroService::instance().PublicEndPoint());
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if(Request->getMethod() == Poco::Net::HTTPRequest::HTTP_DELETE) {
 | 
				
			||||||
 | 
					                    Session.sendRequest(ProxyRequest);
 | 
				
			||||||
 | 
					                    Poco::Net::HTTPResponse ProxyResponse;
 | 
				
			||||||
 | 
					                    Session.receiveResponse(ProxyResponse);
 | 
				
			||||||
 | 
					                    Response->setStatus(ProxyResponse.getStatus());
 | 
				
			||||||
 | 
					                    Response->send();
 | 
				
			||||||
 | 
					                    return;
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    Poco::JSON::Parser P;
 | 
				
			||||||
 | 
					                    std::stringstream SS;
 | 
				
			||||||
 | 
					                    try {
 | 
				
			||||||
 | 
					                        auto Body = P.parse(Request->stream()).extract<Poco::JSON::Object::Ptr>();
 | 
				
			||||||
 | 
					                        Poco::JSON::Stringifier::condense(Body,SS);
 | 
				
			||||||
 | 
					                        SS << "\r\n\r\n";
 | 
				
			||||||
 | 
					                    } catch(const Poco::Exception &E) {
 | 
				
			||||||
 | 
					                        Logger.log(E);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if(SS.str().empty()) {
 | 
				
			||||||
 | 
					                        Session.sendRequest(ProxyRequest);
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        ProxyRequest.setContentType("application/json");
 | 
				
			||||||
 | 
					                        ProxyRequest.setContentLength(SS.str().size());
 | 
				
			||||||
 | 
					                        std::ostream & os = Session.sendRequest(ProxyRequest);
 | 
				
			||||||
 | 
					                        os << SS.str() ;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    Poco::Net::HTTPResponse ProxyResponse;
 | 
				
			||||||
 | 
					                    std::stringstream SSR;
 | 
				
			||||||
 | 
					                    try {
 | 
				
			||||||
 | 
					                        std::istream &ProxyResponseStream = Session.receiveResponse(ProxyResponse);
 | 
				
			||||||
 | 
					                        Poco::JSON::Parser  P2;
 | 
				
			||||||
 | 
					                        auto ProxyResponseBody = P2.parse(ProxyResponseStream).extract<Poco::JSON::Object::Ptr>();
 | 
				
			||||||
 | 
					                        Poco::JSON::Stringifier::condense(ProxyResponseBody,SSR);
 | 
				
			||||||
 | 
					                        Response->setContentType("application/json");
 | 
				
			||||||
 | 
					                        Response->setContentLength(SSR.str().size());
 | 
				
			||||||
 | 
					                        Response->setStatus(ProxyResponse.getStatus());
 | 
				
			||||||
 | 
					                        Response->sendBuffer(SSR.str().c_str(),SSR.str().size());
 | 
				
			||||||
 | 
					                        return;
 | 
				
			||||||
 | 
					                    } catch( const Poco::Exception & E) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    Response->setStatus(ProxyResponse.getStatus());
 | 
				
			||||||
 | 
					                    Response->send();
 | 
				
			||||||
 | 
					                    return;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        } catch (const Poco::Exception &E) {
 | 
				
			||||||
 | 
					            Logger.log(E);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -2327,7 +2327,7 @@ namespace OpenWifi {
 | 
				
			|||||||
            if(Utils::wgets(GitUCentralJSONSchemaFile, GitSchema)) {
 | 
					            if(Utils::wgets(GitUCentralJSONSchemaFile, GitSchema)) {
 | 
				
			||||||
                auto schema = json::parse(GitSchema);
 | 
					                auto schema = json::parse(GitSchema);
 | 
				
			||||||
                Validator_->set_root_schema(schema);
 | 
					                Validator_->set_root_schema(schema);
 | 
				
			||||||
                Logger_.information("Using uCentral validation schema from GIT.");
 | 
					                Logger().information("Using uCentral validation schema from GIT.");
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                std::string FileName{ MicroService::instance().DataDir() + "/ucentral.schema.json" };
 | 
					                std::string FileName{ MicroService::instance().DataDir() + "/ucentral.schema.json" };
 | 
				
			||||||
                std::ifstream       input(FileName);
 | 
					                std::ifstream       input(FileName);
 | 
				
			||||||
@@ -2336,11 +2336,11 @@ namespace OpenWifi {
 | 
				
			|||||||
                input.close();
 | 
					                input.close();
 | 
				
			||||||
                auto schema = json::parse(schema_file.str());
 | 
					                auto schema = json::parse(schema_file.str());
 | 
				
			||||||
                Validator_->set_root_schema(schema);
 | 
					                Validator_->set_root_schema(schema);
 | 
				
			||||||
                Logger_.information("Using uCentral validation schema from local file.");
 | 
					                Logger().information("Using uCentral validation schema from local file.");
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } catch (const Poco::Exception &E) {
 | 
					        } catch (const Poco::Exception &E) {
 | 
				
			||||||
            Validator_->set_root_schema(DefaultUCentralSchema);
 | 
					            Validator_->set_root_schema(DefaultUCentralSchema);
 | 
				
			||||||
            Logger_.information("Using uCentral validation from built-in default.");
 | 
					            Logger().information("Using uCentral validation from built-in default.");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        Initialized_ = Working_ = true;
 | 
					        Initialized_ = Working_ = true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -2471,7 +2471,7 @@ namespace OpenWifi {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void ConfigurationValidator::reinitialize(Poco::Util::Application &self) {
 | 
					    void ConfigurationValidator::reinitialize(Poco::Util::Application &self) {
 | 
				
			||||||
        Logger_.information("Reinitializing.");
 | 
					        Logger().information("Reinitializing.");
 | 
				
			||||||
        Working_ = Initialized_ = false;
 | 
					        Working_ = Initialized_ = false;
 | 
				
			||||||
        Init();
 | 
					        Init();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,8 +2,7 @@
 | 
				
			|||||||
// Created by stephane bourque on 2021-09-14.
 | 
					// Created by stephane bourque on 2021-09-14.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef OWPROV_CONFIGURATIONVALIDATOR_H
 | 
					#pragma once
 | 
				
			||||||
#define OWPROV_CONFIGURATIONVALIDATOR_H
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <nlohmann/json-schema.hpp>
 | 
					#include <nlohmann/json-schema.hpp>
 | 
				
			||||||
#include "framework/MicroService.h"
 | 
					#include "framework/MicroService.h"
 | 
				
			||||||
@@ -43,4 +42,3 @@ namespace OpenWifi {
 | 
				
			|||||||
    inline bool ValidateUCentralConfiguration(const std::string &C, std::string &Error) { return ConfigurationValidator::instance()->Validate(C, Error); }
 | 
					    inline bool ValidateUCentralConfiguration(const std::string &C, std::string &Error) { return ConfigurationValidator::instance()->Validate(C, Error); }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif //OWPROV_CONFIGURATIONVALIDATOR_H
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,8 +2,7 @@
 | 
				
			|||||||
// Created by stephane bourque on 2021-10-08.
 | 
					// Created by stephane bourque on 2021-10-08.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef OWPROV_COUNTRYCODES_H
 | 
					#pragma once
 | 
				
			||||||
#define OWPROV_COUNTRYCODES_H
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <vector>
 | 
					#include <vector>
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
@@ -270,4 +269,3 @@ namespace OpenWifi {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif //OWPROV_COUNTRYCODES_H
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,8 +5,8 @@
 | 
				
			|||||||
//	Created by Stephane Bourque on 2021-03-04.
 | 
					//	Created by Stephane Bourque on 2021-03-04.
 | 
				
			||||||
//	Arilia Wireless Inc.
 | 
					//	Arilia Wireless Inc.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
#ifndef UCENTRALGW_KAFKA_TOPICS_H
 | 
					
 | 
				
			||||||
#define UCENTRALGW_KAFKA_TOPICS_H
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi::KafkaTopics {
 | 
					namespace OpenWifi::KafkaTopics {
 | 
				
			||||||
	static const std::string HEALTHCHECK{"healthcheck"};
 | 
						static const std::string HEALTHCHECK{"healthcheck"};
 | 
				
			||||||
@@ -17,6 +17,7 @@ namespace OpenWifi::KafkaTopics {
 | 
				
			|||||||
	static const std::string COMMAND{"command"};
 | 
						static const std::string COMMAND{"command"};
 | 
				
			||||||
	static const std::string SERVICE_EVENTS{"service_events"};
 | 
						static const std::string SERVICE_EVENTS{"service_events"};
 | 
				
			||||||
	static const std::string DEVICE_EVENT_QUEUE{"device_event_queue"};
 | 
						static const std::string DEVICE_EVENT_QUEUE{"device_event_queue"};
 | 
				
			||||||
 | 
						static const std::string DEVICE_TELEMETRY{"device_telemetry"};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	namespace ServiceEvents {
 | 
						namespace ServiceEvents {
 | 
				
			||||||
		static const std::string EVENT_JOIN{"join"};
 | 
							static const std::string EVENT_JOIN{"join"};
 | 
				
			||||||
@@ -37,4 +38,3 @@ namespace OpenWifi::KafkaTopics {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif // UCENTRALGW_KAFKA_TOPICS_H
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,25 +1,17 @@
 | 
				
			|||||||
//
 | 
					//
 | 
				
			||||||
//	License type: BSD 3-Clause License
 | 
					// Created by stephane bourque on 2021-11-16.
 | 
				
			||||||
//	License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
 | 
					 | 
				
			||||||
//
 | 
					 | 
				
			||||||
//	Created by Stephane Bourque on 2021-03-04.
 | 
					 | 
				
			||||||
//	Arilia Wireless Inc.
 | 
					 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef UCENTRALGW_UCENTRALTYPES_H
 | 
					#pragma once
 | 
				
			||||||
#define UCENTRALGW_UCENTRALTYPES_H
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <vector>
 | 
					 | 
				
			||||||
#include <string>
 | 
					 | 
				
			||||||
#include <map>
 | 
					#include <map>
 | 
				
			||||||
#include <functional>
 | 
					 | 
				
			||||||
#include <list>
 | 
					 | 
				
			||||||
#include <utility>
 | 
					#include <utility>
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					#include <functional>
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
#include <queue>
 | 
					#include <queue>
 | 
				
			||||||
 | 
					#include <list>
 | 
				
			||||||
#include "Poco/StringTokenizer.h"
 | 
					#include <set>
 | 
				
			||||||
#include "Poco/JSON/Parser.h"
 | 
					 | 
				
			||||||
#include "Poco/JSON/Stringifier.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi::Types {
 | 
					namespace OpenWifi::Types {
 | 
				
			||||||
    typedef std::pair<std::string,std::string>                  StringPair;
 | 
					    typedef std::pair<std::string,std::string>                  StringPair;
 | 
				
			||||||
@@ -28,15 +20,19 @@ namespace OpenWifi::Types {
 | 
				
			|||||||
    typedef std::vector<std::string>						    StringVec;
 | 
					    typedef std::vector<std::string>						    StringVec;
 | 
				
			||||||
    typedef std::set<std::string>                               StringSet;
 | 
					    typedef std::set<std::string>                               StringSet;
 | 
				
			||||||
    typedef std::map<std::string,std::set<std::string>>		    StringMapStringSet;
 | 
					    typedef std::map<std::string,std::set<std::string>>		    StringMapStringSet;
 | 
				
			||||||
	typedef std::function<void(std::string, std::string)>   TopicNotifyFunction;
 | 
					    typedef std::function<void(const std::string &, const std::string &)>       TopicNotifyFunction;
 | 
				
			||||||
    typedef std::list<std::pair<TopicNotifyFunction,int>>       TopicNotifyFunctionList;
 | 
					    typedef std::list<std::pair<TopicNotifyFunction,int>>       TopicNotifyFunctionList;
 | 
				
			||||||
    typedef std::map<std::string, TopicNotifyFunctionList>      NotifyTable;
 | 
					    typedef std::map<std::string, TopicNotifyFunctionList>      NotifyTable;
 | 
				
			||||||
    typedef std::map<std::string,uint64_t>                      CountedMap;
 | 
					    typedef std::map<std::string,uint64_t>                      CountedMap;
 | 
				
			||||||
    typedef std::vector<uint64_t>                               TagList;
 | 
					    typedef std::vector<uint64_t>                               TagList;
 | 
				
			||||||
    typedef std::string                                         UUID_t;
 | 
					    typedef std::string                                         UUID_t;
 | 
				
			||||||
    typedef std::vector<UUID_t>                                 UUIDvec_t;
 | 
					    typedef std::vector<UUID_t>                                 UUIDvec_t;
 | 
				
			||||||
 | 
					    typedef std::map<std::string,std::map<uint32_t,uint64_t>>   Counted3DMapSII;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    inline void UpdateCountedMap(CountedMap &M, const std::string &S, uint64_t Increment=1) {
 | 
					namespace OpenWifi {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inline void UpdateCountedMap(OpenWifi::Types::CountedMap &M, const std::string &S, uint64_t Increment=1) {
 | 
				
			||||||
        auto it = M.find(S);
 | 
					        auto it = M.find(S);
 | 
				
			||||||
        if(it==M.end())
 | 
					        if(it==M.end())
 | 
				
			||||||
            M[S] = Increment;
 | 
					            M[S] = Increment;
 | 
				
			||||||
@@ -44,60 +40,21 @@ namespace OpenWifi::Types {
 | 
				
			|||||||
            it->second += Increment;
 | 
					            it->second += Increment;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    inline std::string to_string( const StringVec &V) {
 | 
					    inline void UpdateCountedMap(OpenWifi::Types::Counted3DMapSII &M, const std::string &S, uint32_t Index, uint64_t Increment=1) {
 | 
				
			||||||
        Poco::JSON::Array   O;
 | 
					        auto it = M.find(S);
 | 
				
			||||||
        for(const auto &i:V) {
 | 
					        if(it==M.end()) {
 | 
				
			||||||
            O.add(i);
 | 
					            std::map<uint32_t,uint64_t> E;
 | 
				
			||||||
 | 
					            E[Index] = Increment;
 | 
				
			||||||
 | 
					            M[S] = E;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        std::stringstream SS;
 | 
					        else {
 | 
				
			||||||
        Poco::JSON::Stringifier::stringify(O,SS);
 | 
					            std::map<uint32_t,uint64_t> & IndexMap = it->second;
 | 
				
			||||||
        return SS.str();
 | 
					            auto it_index = IndexMap.find(Index);
 | 
				
			||||||
    }
 | 
					            if(it_index == IndexMap.end()) {
 | 
				
			||||||
 | 
					                IndexMap[Index] = Increment;
 | 
				
			||||||
    inline std::string to_string( const StringPairVec &V) {
 | 
					            } else {
 | 
				
			||||||
        Poco::JSON::Array   O;
 | 
					                it_index->second += Increment;
 | 
				
			||||||
        for(const auto &i:V) {
 | 
					 | 
				
			||||||
            Poco::JSON::Array OO;
 | 
					 | 
				
			||||||
            OO.add(i.first);
 | 
					 | 
				
			||||||
            OO.add(i.second);
 | 
					 | 
				
			||||||
            O.add(OO);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        std::stringstream SS;
 | 
					 | 
				
			||||||
        Poco::JSON::Stringifier::stringify(O,SS);
 | 
					 | 
				
			||||||
        return SS.str();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    inline void from_string(const std::string &S, StringPairVec &V) {
 | 
					 | 
				
			||||||
        try {
 | 
					 | 
				
			||||||
            Poco::JSON::Parser      P;
 | 
					 | 
				
			||||||
            auto O = P.parse(S).extract<Poco::JSON::Array::Ptr>();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            for(const auto &i:*O) {
 | 
					 | 
				
			||||||
                auto Inner = i.extract<Poco::JSON::Array::Ptr>();
 | 
					 | 
				
			||||||
                for(const auto &j:*Inner) {
 | 
					 | 
				
			||||||
                    auto S1 = i[0].toString();
 | 
					 | 
				
			||||||
                    auto S2 = i[1].toString();
 | 
					 | 
				
			||||||
                    V.push_back(std::make_pair(S1,S2));
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        } catch (...) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    }
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
    inline void from_string(const std::string &S, StringVec &V) {
 | 
					 | 
				
			||||||
        try {
 | 
					 | 
				
			||||||
            Poco::JSON::Parser      P;
 | 
					 | 
				
			||||||
            auto O = P.parse(S).extract<Poco::JSON::Array::Ptr>();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            for(auto const &i:*O) {
 | 
					 | 
				
			||||||
                V.push_back(i.toString());
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        } catch (...) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif // UCENTRALGW_UCENTRALTYPES_H
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,8 +2,7 @@
 | 
				
			|||||||
// Created by stephane bourque on 2021-09-12.
 | 
					// Created by stephane bourque on 2021-09-12.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef OWPROV_RESTAPI_ERRORS_H
 | 
					#pragma once
 | 
				
			||||||
#define OWPROV_RESTAPI_ERRORS_H
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi::RESTAPI::Errors {
 | 
					namespace OpenWifi::RESTAPI::Errors {
 | 
				
			||||||
    static const std::string MissingUUID{"Missing UUID."};
 | 
					    static const std::string MissingUUID{"Missing UUID."};
 | 
				
			||||||
@@ -15,7 +14,7 @@ namespace OpenWifi::RESTAPI::Errors {
 | 
				
			|||||||
    static const std::string CouldNotBeDeleted{"Element could not be deleted."};
 | 
					    static const std::string CouldNotBeDeleted{"Element could not be deleted."};
 | 
				
			||||||
    static const std::string NameMustBeSet{"The name property must be set."};
 | 
					    static const std::string NameMustBeSet{"The name property must be set."};
 | 
				
			||||||
    static const std::string ConfigBlockInvalid{"Configuration block type invalid."};
 | 
					    static const std::string ConfigBlockInvalid{"Configuration block type invalid."};
 | 
				
			||||||
    static const std::string UnknownId{"Unknown management policy."};
 | 
					    static const std::string UnknownId{"Unknown UUID."};
 | 
				
			||||||
    static const std::string InvalidDeviceTypes{"Unknown or invalid device type(s)."};
 | 
					    static const std::string InvalidDeviceTypes{"Unknown or invalid device type(s)."};
 | 
				
			||||||
    static const std::string RecordNotCreated{"Record could not be created."};
 | 
					    static const std::string RecordNotCreated{"Record could not be created."};
 | 
				
			||||||
    static const std::string RecordNotUpdated{"Record could not be updated."};
 | 
					    static const std::string RecordNotUpdated{"Record could not be updated."};
 | 
				
			||||||
@@ -60,6 +59,10 @@ namespace OpenWifi::RESTAPI::Errors {
 | 
				
			|||||||
    static const std::string MissingAuthenticationInformation{"Missing authentication information."};
 | 
					    static const std::string MissingAuthenticationInformation{"Missing authentication information."};
 | 
				
			||||||
    static const std::string InsufficientAccessRights{"Insufficient access rights to complete the operation."};
 | 
					    static const std::string InsufficientAccessRights{"Insufficient access rights to complete the operation."};
 | 
				
			||||||
    static const std::string ExpiredToken{"Token has expired, user must login."};
 | 
					    static const std::string ExpiredToken{"Token has expired, user must login."};
 | 
				
			||||||
 | 
					    static const std::string SubscriberMustExist{"Subscriber must exist."};
 | 
				
			||||||
 | 
					    static const std::string AuthenticatorVerificationIncomplete{"Authenticator validation is not complete."};
 | 
				
			||||||
 | 
					    static const std::string SMSCouldNotBeSentRetry{"SMS could not be sent to validate device, try later or change the phone number."};
 | 
				
			||||||
 | 
					    static const std::string SMSCouldNotValidate{"Code and number could not be validated"};
 | 
				
			||||||
 | 
					    static const std::string InvalidDeviceClass{"Invalid device class. Must be: any, venue, entity, or subscriber"};
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif //OWPROV_RESTAPI_ERRORS_H
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,8 +6,7 @@
 | 
				
			|||||||
//	Arilia Wireless Inc.
 | 
					//	Arilia Wireless Inc.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef UCENTRALGW_RESTAPI_PROTOCOL_H
 | 
					#pragma once
 | 
				
			||||||
#define UCENTRALGW_RESTAPI_PROTOCOL_H
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace OpenWifi::RESTAPI::Protocol {
 | 
					namespace OpenWifi::RESTAPI::Protocol {
 | 
				
			||||||
	static const char * CAPABILITIES = "capabilities";
 | 
						static const char * CAPABILITIES = "capabilities";
 | 
				
			||||||
@@ -85,11 +84,13 @@ namespace OpenWifi::RESTAPI::Protocol {
 | 
				
			|||||||
	static const char * GETSUBSYSTEMNAMES = "getsubsystemnames";
 | 
						static const char * GETSUBSYSTEMNAMES = "getsubsystemnames";
 | 
				
			||||||
	static const char * GETLOGLEVELNAMES = "getloglevelnames";
 | 
						static const char * GETLOGLEVELNAMES = "getloglevelnames";
 | 
				
			||||||
	static const char * STATS = "stats";
 | 
						static const char * STATS = "stats";
 | 
				
			||||||
 | 
						static const char * PING = "ping";
 | 
				
			||||||
	static const char * PARAMETERS = "parameters";
 | 
						static const char * PARAMETERS = "parameters";
 | 
				
			||||||
	static const char * VALUE = "value";
 | 
						static const char * VALUE = "value";
 | 
				
			||||||
	static const char * LASTONLY = "lastOnly";
 | 
						static const char * LASTONLY = "lastOnly";
 | 
				
			||||||
	static const char * NEWEST = "newest";
 | 
						static const char * NEWEST = "newest";
 | 
				
			||||||
	static const char * ACTIVESCAN = "activeScan";
 | 
						static const char * ACTIVESCAN = "activeScan";
 | 
				
			||||||
 | 
						static const char * OVERRIDEDFS = "override_dfs";
 | 
				
			||||||
	static const char * LIST = "list";
 | 
						static const char * LIST = "list";
 | 
				
			||||||
	static const char * TAG = "tag";
 | 
						static const char * TAG = "tag";
 | 
				
			||||||
	static const char * TAGLIST = "tagList";
 | 
						static const char * TAGLIST = "tagList";
 | 
				
			||||||
@@ -136,5 +137,3 @@ namespace OpenWifi::RESTAPI::Protocol {
 | 
				
			|||||||
    static const char * UI = "UI";
 | 
					    static const char * UI = "UI";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif // UCENTRALGW_RESTAPI_PROTOCOL_H
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,8 +2,7 @@
 | 
				
			|||||||
// Created by stephane bourque on 2021-10-06.
 | 
					// Created by stephane bourque on 2021-10-06.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef OPENWIFI_STORAGE_H
 | 
					#pragma once
 | 
				
			||||||
#define OPENWIFI_STORAGE_H
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "Poco/Data/Session.h"
 | 
					#include "Poco/Data/Session.h"
 | 
				
			||||||
#include "Poco/Data/SessionPool.h"
 | 
					#include "Poco/Data/SessionPool.h"
 | 
				
			||||||
@@ -34,8 +33,8 @@ namespace OpenWifi {
 | 
				
			|||||||
        int Start() override {
 | 
					        int Start() override {
 | 
				
			||||||
            std::lock_guard		Guard(Mutex_);
 | 
					            std::lock_guard		Guard(Mutex_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            Logger_.setLevel(Poco::Message::PRIO_NOTICE);
 | 
					            Logger().setLevel(Poco::Message::PRIO_INFORMATION);
 | 
				
			||||||
            Logger_.notice("Starting.");
 | 
					            Logger().notice("Starting.");
 | 
				
			||||||
            std::string DBType = MicroService::instance().ConfigGetString("storage.type");
 | 
					            std::string DBType = MicroService::instance().ConfigGetString("storage.type");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (DBType == "sqlite") {
 | 
					            if (DBType == "sqlite") {
 | 
				
			||||||
@@ -52,37 +51,6 @@ namespace OpenWifi {
 | 
				
			|||||||
            Pool_->shutdown();
 | 
					            Pool_->shutdown();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        [[nodiscard]] inline std::string ComputeRange(uint64_t From, uint64_t HowMany) {
 | 
					 | 
				
			||||||
            if(dbType_==sqlite) {
 | 
					 | 
				
			||||||
                return " LIMIT " + std::to_string(From-1) + ", " + std::to_string(HowMany) + " ";
 | 
					 | 
				
			||||||
            } else if(dbType_==pgsql) {
 | 
					 | 
				
			||||||
                return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From-1) + " ";
 | 
					 | 
				
			||||||
            } else if(dbType_==mysql) {
 | 
					 | 
				
			||||||
                return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From-1) + " ";
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From-1) + " ";
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        inline std::string ConvertParams(const std::string & S) const {
 | 
					 | 
				
			||||||
            std::string R;
 | 
					 | 
				
			||||||
            R.reserve(S.size()*2+1);
 | 
					 | 
				
			||||||
            if(dbType_==pgsql) {
 | 
					 | 
				
			||||||
                auto Idx=1;
 | 
					 | 
				
			||||||
                for(auto const & i:S)
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    if(i=='?') {
 | 
					 | 
				
			||||||
                        R += '$';
 | 
					 | 
				
			||||||
                        R.append(std::to_string(Idx++));
 | 
					 | 
				
			||||||
                    } else {
 | 
					 | 
				
			||||||
                        R += i;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                R = S;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            return R;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private:
 | 
					    private:
 | 
				
			||||||
        inline int Setup_SQLite();
 | 
					        inline int Setup_SQLite();
 | 
				
			||||||
        inline int Setup_MySQL();
 | 
					        inline int Setup_MySQL();
 | 
				
			||||||
@@ -102,7 +70,7 @@ namespace OpenWifi {
 | 
				
			|||||||
#else
 | 
					#else
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    inline int StorageClass::Setup_SQLite() {
 | 
					    inline int StorageClass::Setup_SQLite() {
 | 
				
			||||||
        Logger_.notice("SQLite StorageClass enabled.");
 | 
					        Logger().notice("SQLite StorageClass enabled.");
 | 
				
			||||||
        dbType_ = sqlite;
 | 
					        dbType_ = sqlite;
 | 
				
			||||||
        auto DBName = MicroService::instance().DataDir() + "/" + MicroService::instance().ConfigGetString("storage.type.sqlite.db");
 | 
					        auto DBName = MicroService::instance().DataDir() + "/" + MicroService::instance().ConfigGetString("storage.type.sqlite.db");
 | 
				
			||||||
        auto NumSessions = MicroService::instance().ConfigGetInt("storage.type.sqlite.maxsessions", 64);
 | 
					        auto NumSessions = MicroService::instance().ConfigGetInt("storage.type.sqlite.maxsessions", 64);
 | 
				
			||||||
@@ -113,7 +81,7 @@ namespace OpenWifi {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    inline int StorageClass::Setup_MySQL() {
 | 
					    inline int StorageClass::Setup_MySQL() {
 | 
				
			||||||
        Logger_.notice("MySQL StorageClass enabled.");
 | 
					        Logger().notice("MySQL StorageClass enabled.");
 | 
				
			||||||
        dbType_ = mysql;
 | 
					        dbType_ = mysql;
 | 
				
			||||||
        auto NumSessions = MicroService::instance().ConfigGetInt("storage.type.mysql.maxsessions", 64);
 | 
					        auto NumSessions = MicroService::instance().ConfigGetInt("storage.type.mysql.maxsessions", 64);
 | 
				
			||||||
        auto IdleTime = MicroService::instance().ConfigGetInt("storage.type.mysql.idletime", 60);
 | 
					        auto IdleTime = MicroService::instance().ConfigGetInt("storage.type.mysql.idletime", 60);
 | 
				
			||||||
@@ -138,7 +106,7 @@ namespace OpenWifi {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    inline int StorageClass::Setup_PostgreSQL() {
 | 
					    inline int StorageClass::Setup_PostgreSQL() {
 | 
				
			||||||
        Logger_.notice("PostgreSQL StorageClass enabled.");
 | 
					        Logger().notice("PostgreSQL StorageClass enabled.");
 | 
				
			||||||
        dbType_ = pgsql;
 | 
					        dbType_ = pgsql;
 | 
				
			||||||
        auto NumSessions = MicroService::instance().ConfigGetInt("storage.type.postgresql.maxsessions", 64);
 | 
					        auto NumSessions = MicroService::instance().ConfigGetInt("storage.type.postgresql.maxsessions", 64);
 | 
				
			||||||
        auto IdleTime = MicroService::instance().ConfigGetInt("storage.type.postgresql.idletime", 60);
 | 
					        auto IdleTime = MicroService::instance().ConfigGetInt("storage.type.postgresql.idletime", 60);
 | 
				
			||||||
@@ -165,5 +133,3 @@ namespace OpenWifi {
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif //OPENWIFI_STORAGE_H
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,8 +6,7 @@
 | 
				
			|||||||
//	Arilia Wireless Inc.
 | 
					//	Arilia Wireless Inc.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef __OPENWIFI_ORM_H__
 | 
					#pragma once
 | 
				
			||||||
#define __OPENWIFI_ORM_H__
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
#include <memory>
 | 
					#include <memory>
 | 
				
			||||||
@@ -33,7 +32,8 @@ namespace ORM {
 | 
				
			|||||||
        FT_BIGINT,
 | 
					        FT_BIGINT,
 | 
				
			||||||
        FT_TEXT,
 | 
					        FT_TEXT,
 | 
				
			||||||
        FT_VARCHAR,
 | 
					        FT_VARCHAR,
 | 
				
			||||||
        FT_BLOB
 | 
					        FT_BLOB,
 | 
				
			||||||
 | 
					        FT_BOOLEAN
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    enum Indextype {
 | 
					    enum Indextype {
 | 
				
			||||||
@@ -97,6 +97,7 @@ namespace ORM {
 | 
				
			|||||||
            case FT_INT:    return "INT";
 | 
					            case FT_INT:    return "INT";
 | 
				
			||||||
            case FT_BIGINT: return "BIGINT";
 | 
					            case FT_BIGINT: return "BIGINT";
 | 
				
			||||||
            case FT_TEXT:   return "TEXT";
 | 
					            case FT_TEXT:   return "TEXT";
 | 
				
			||||||
 | 
					            case FT_BOOLEAN:   return "BOOLEAN";
 | 
				
			||||||
            case FT_VARCHAR:
 | 
					            case FT_VARCHAR:
 | 
				
			||||||
                if(Size)
 | 
					                if(Size)
 | 
				
			||||||
                    return std::string("VARCHAR(") + std::to_string(Size) + std::string(")");
 | 
					                    return std::string("VARCHAR(") + std::to_string(Size) + std::string(")");
 | 
				
			||||||
@@ -154,28 +155,46 @@ namespace ORM {
 | 
				
			|||||||
        return S;
 | 
					        return S;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    template <typename RecordType> class DBCache {
 | 
				
			||||||
 | 
					    public:
 | 
				
			||||||
 | 
					        DBCache(unsigned Size, unsigned Timeout)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        virtual void Create(const RecordType &R)=0;
 | 
				
			||||||
 | 
					        virtual bool GetFromCache(const std::string &FieldName, const std::string &Value, RecordType &R)=0;
 | 
				
			||||||
 | 
					        virtual void UpdateCache(const RecordType &R)=0;
 | 
				
			||||||
 | 
					        virtual void Delete(const std::string &FieldName, const std::string &Value)=0;
 | 
				
			||||||
 | 
					    private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    template <typename RecordTuple, typename RecordType> class DB {
 | 
					    template <typename RecordTuple, typename RecordType> class DB {
 | 
				
			||||||
    public:
 | 
					    public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        typedef const char * field_name_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        DB( OpenWifi::DBType dbtype,
 | 
					        DB( OpenWifi::DBType dbtype,
 | 
				
			||||||
            const char *TableName,
 | 
					            const char *TableName,
 | 
				
			||||||
            const FieldVec & Fields,
 | 
					            const FieldVec & Fields,
 | 
				
			||||||
            const IndexVec & Indexes,
 | 
					            const IndexVec & Indexes,
 | 
				
			||||||
            Poco::Data::SessionPool & Pool,
 | 
					            Poco::Data::SessionPool & Pool,
 | 
				
			||||||
            Poco::Logger &L,
 | 
					            Poco::Logger &L,
 | 
				
			||||||
                const char *Prefix):
 | 
					            const char *Prefix,
 | 
				
			||||||
                Type(dbtype),
 | 
					            DBCache<RecordType> * Cache=nullptr):
 | 
				
			||||||
                DBName(TableName),
 | 
					                Type_(dbtype),
 | 
				
			||||||
 | 
					                TableName_(TableName),
 | 
				
			||||||
                Pool_(Pool),
 | 
					                Pool_(Pool),
 | 
				
			||||||
                Logger_(L),
 | 
					                Logger_(L),
 | 
				
			||||||
                Prefix_(Prefix)
 | 
					                Prefix_(Prefix),
 | 
				
			||||||
 | 
					                Cache_(Cache)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					            assert(RecordTuple::length == Fields.size());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            bool first = true;
 | 
					            bool first = true;
 | 
				
			||||||
            int  Place=0;
 | 
					            int  Place=0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            assert( RecordTuple::length == Fields.size());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            for(const auto &i:Fields) {
 | 
					            for(const auto &i:Fields) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
                FieldNames_[i.Name] = Place;
 | 
					                FieldNames_[i.Name] = Place;
 | 
				
			||||||
                if(!first) {
 | 
					                if(!first) {
 | 
				
			||||||
                    CreateFields_ += ", ";
 | 
					                    CreateFields_ += ", ";
 | 
				
			||||||
@@ -186,7 +205,7 @@ namespace ORM {
 | 
				
			|||||||
                    SelectList_ += "(";
 | 
					                    SelectList_ += "(";
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                CreateFields_ += i.Name + " " + FieldTypeToChar(Type, i.Type,i.Size) + (i.Index ? " unique primary key" : "");
 | 
					                CreateFields_ += i.Name + " " + FieldTypeToChar(Type_, i.Type,i.Size) + (i.Index ? " unique primary key" : "");
 | 
				
			||||||
                SelectFields_ += i.Name ;
 | 
					                SelectFields_ += i.Name ;
 | 
				
			||||||
                UpdateFields_ += i.Name + "=?";
 | 
					                UpdateFields_ += i.Name + "=?";
 | 
				
			||||||
                SelectList_ += "?";
 | 
					                SelectList_ += "?";
 | 
				
			||||||
@@ -196,11 +215,11 @@ namespace ORM {
 | 
				
			|||||||
            SelectList_ += ")";
 | 
					            SelectList_ += ")";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(!Indexes.empty()) {
 | 
					            if(!Indexes.empty()) {
 | 
				
			||||||
                if(Type==OpenWifi::DBType::sqlite || Type==OpenWifi::DBType::pgsql) {
 | 
					                if(Type_==OpenWifi::DBType::sqlite || Type_==OpenWifi::DBType::pgsql) {
 | 
				
			||||||
                    for(const auto &j:Indexes) {
 | 
					                    for(const auto &j:Indexes) {
 | 
				
			||||||
                        std::string IndexLine;
 | 
					                        std::string IndexLine;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        IndexLine = std::string("CREATE INDEX IF NOT EXISTS ") + j.Name + std::string(" ON ") + DBName + " (";
 | 
					                        IndexLine = std::string("CREATE INDEX IF NOT EXISTS ") + j.Name + std::string(" ON ") + TableName_+ " (";
 | 
				
			||||||
                        bool first_entry=true;
 | 
					                        bool first_entry=true;
 | 
				
			||||||
                        for(const auto &k:j.Entries) {
 | 
					                        for(const auto &k:j.Entries) {
 | 
				
			||||||
                            assert(FieldNames_.find(k.FieldName) != FieldNames_.end());
 | 
					                            assert(FieldNames_.find(k.FieldName) != FieldNames_.end());
 | 
				
			||||||
@@ -210,10 +229,10 @@ namespace ORM {
 | 
				
			|||||||
                            first_entry = false;
 | 
					                            first_entry = false;
 | 
				
			||||||
                            IndexLine += k.FieldName + std::string(" ") + std::string(k.Type == Indextype::ASC ? "ASC" : "DESC") ;
 | 
					                            IndexLine += k.FieldName + std::string(" ") + std::string(k.Type == Indextype::ASC ? "ASC" : "DESC") ;
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        IndexLine += " );";
 | 
					                        IndexLine += " )";
 | 
				
			||||||
                        IndexCreation += IndexLine;
 | 
					                        IndexCreation_.template emplace_back(IndexLine);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                } else if(Type==OpenWifi::DBType::mysql) {
 | 
					                } else if(Type_==OpenWifi::DBType::mysql) {
 | 
				
			||||||
                    bool firstIndex = true;
 | 
					                    bool firstIndex = true;
 | 
				
			||||||
                    std::string IndexLine;
 | 
					                    std::string IndexLine;
 | 
				
			||||||
                    for(const auto &j:Indexes) {
 | 
					                    for(const auto &j:Indexes) {
 | 
				
			||||||
@@ -232,7 +251,7 @@ namespace ORM {
 | 
				
			|||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        IndexLine += " ) ";
 | 
					                        IndexLine += " ) ";
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    IndexCreation = IndexLine;
 | 
					                    IndexCreation_.template emplace_back(IndexLine);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -242,22 +261,27 @@ namespace ORM {
 | 
				
			|||||||
        [[nodiscard]] const std::string & SelectList() const { return SelectList_; };
 | 
					        [[nodiscard]] const std::string & SelectList() const { return SelectList_; };
 | 
				
			||||||
        [[nodiscard]] const std::string & UpdateFields() const { return UpdateFields_; };
 | 
					        [[nodiscard]] const std::string & UpdateFields() const { return UpdateFields_; };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inline std::string OP(const char *F, SqlComparison O , int V) {
 | 
					        inline std::string OP(field_name_t F, SqlComparison O , bool V) {
 | 
				
			||||||
 | 
					            assert( FieldNames_.find(F) != FieldNames_.end() );
 | 
				
			||||||
 | 
					            return std::string{"("} + F + SQLCOMPS[O] + (V ? "true" : "false") + ")" ;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        inline std::string OP(field_name_t F, SqlComparison O , int V) {
 | 
				
			||||||
            assert( FieldNames_.find(F) != FieldNames_.end() );
 | 
					            assert( FieldNames_.find(F) != FieldNames_.end() );
 | 
				
			||||||
            return std::string{"("} + F + SQLCOMPS[O] + std::to_string(V) + ")" ;
 | 
					            return std::string{"("} + F + SQLCOMPS[O] + std::to_string(V) + ")" ;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inline std::string OP(const char *F, SqlComparison O , uint64_t V) {
 | 
					        inline std::string OP(field_name_t F, SqlComparison O , uint64_t V) {
 | 
				
			||||||
            assert( FieldNames_.find(F) != FieldNames_.end() );
 | 
					            assert( FieldNames_.find(F) != FieldNames_.end() );
 | 
				
			||||||
            return std::string{"("} + F + SQLCOMPS[O] + std::to_string(V) + ")" ;
 | 
					            return std::string{"("} + F + SQLCOMPS[O] + std::to_string(V) + ")" ;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        std::string OP(const char *F, SqlComparison O , const std::string & V) {
 | 
					        std::string OP(field_name_t F, SqlComparison O , const std::string & V) {
 | 
				
			||||||
            assert( FieldNames_.find(F) != FieldNames_.end() );
 | 
					            assert( FieldNames_.find(F) != FieldNames_.end() );
 | 
				
			||||||
            return std::string{"("} + F + SQLCOMPS[O] + "'" + Escape(V) + "')" ;
 | 
					            return std::string{"("} + F + SQLCOMPS[O] + "'" + Escape(V) + "')" ;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        std::string OP(const char *F, SqlComparison O , const char * V) {
 | 
					        std::string OP(field_name_t F, SqlComparison O , const char * V) {
 | 
				
			||||||
            assert( FieldNames_.find(F) != FieldNames_.end() );
 | 
					            assert( FieldNames_.find(F) != FieldNames_.end() );
 | 
				
			||||||
            return std::string{"("} + F + SQLCOMPS[O] + "'" + Escape(V) + "')" ;
 | 
					            return std::string{"("} + F + SQLCOMPS[O] + "'" + Escape(V) + "')" ;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -278,35 +302,61 @@ namespace ORM {
 | 
				
			|||||||
            return std::string{"("} + P1 + BOPS[BOP] + OP(true, P2, More...);
 | 
					            return std::string{"("} + P1 + BOPS[BOP] + OP(true, P2, More...);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inline bool  Create() {
 | 
					        bool Upgrade() {
 | 
				
			||||||
            std::string S;
 | 
					            uint32_t    To;
 | 
				
			||||||
 | 
					            return Upgrade(0, To);
 | 
				
			||||||
            if(Type==OpenWifi::DBType::mysql) {
 | 
					 | 
				
			||||||
                if(IndexCreation.empty())
 | 
					 | 
				
			||||||
                    S = "create table if not exists " + DBName +" ( " + CreateFields_ + " )" ;
 | 
					 | 
				
			||||||
                else
 | 
					 | 
				
			||||||
                    S = "create table if not exists " + DBName +" ( " + CreateFields_ + " ), " + IndexCreation + " )";
 | 
					 | 
				
			||||||
            } else if (Type==OpenWifi::DBType::pgsql || Type==OpenWifi::DBType::sqlite) {
 | 
					 | 
				
			||||||
                S = "create table if not exists " + DBName + " ( " + CreateFields_ + " ); " + IndexCreation ;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // std::cout << "CREATE-DB: " << S << std::endl;
 | 
					        inline bool  Create() {
 | 
				
			||||||
 | 
					            switch(Type_) {
 | 
				
			||||||
 | 
					                case OpenWifi::DBType::mysql: {
 | 
				
			||||||
                    try {
 | 
					                    try {
 | 
				
			||||||
                        Poco::Data::Session     Session = Pool_.get();
 | 
					                        Poco::Data::Session     Session = Pool_.get();
 | 
				
			||||||
                Poco::Data::Statement   CreateStatement(Session);
 | 
					                        std::string Statement = IndexCreation_.empty() ?    "create table if not exists " + TableName_ +" ( " + CreateFields_ + " )" :
 | 
				
			||||||
 | 
					                                                                            "create table if not exists " + TableName_ +" ( " + CreateFields_ + " ), " + IndexCreation_[0] + " )";
 | 
				
			||||||
                CreateStatement << S;
 | 
					                        Session << Statement , Poco::Data::Keywords::now;
 | 
				
			||||||
                CreateStatement.execute();
 | 
					 | 
				
			||||||
                return true;
 | 
					 | 
				
			||||||
                    } catch (const Poco::Exception &E) {
 | 
					                    } catch (const Poco::Exception &E) {
 | 
				
			||||||
                std::cout << "Exception while creating DB: " << E.name() << std::endl;
 | 
					                        Logger_.error("Failure to create MySQL DB resources.");
 | 
				
			||||||
 | 
					                        Logger_.log(E);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
            return false;
 | 
					                }
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                case OpenWifi::DBType::sqlite: {
 | 
				
			||||||
 | 
					                    try {
 | 
				
			||||||
 | 
					                        Poco::Data::Session     Session = Pool_.get();
 | 
				
			||||||
 | 
					                        std::string Statement = "create table if not exists " + TableName_ + " ( " + CreateFields_ + " )";
 | 
				
			||||||
 | 
					                        Session << Statement , Poco::Data::Keywords::now;
 | 
				
			||||||
 | 
					                        for(const auto &i:IndexCreation_) {
 | 
				
			||||||
 | 
					                            Session << i , Poco::Data::Keywords::now;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    } catch (const Poco::Exception &E) {
 | 
				
			||||||
 | 
					                        Logger_.error("Failure to create SQLITE DB resources.");
 | 
				
			||||||
 | 
					                        Logger_.log(E);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                case OpenWifi::DBType::pgsql: {
 | 
				
			||||||
 | 
					                    try {
 | 
				
			||||||
 | 
					                        Poco::Data::Session     Session = Pool_.get();
 | 
				
			||||||
 | 
					                        std::string Statement = "create table if not exists " + TableName_ + " ( " + CreateFields_ + " )";
 | 
				
			||||||
 | 
					                        Session << Statement , Poco::Data::Keywords::now;
 | 
				
			||||||
 | 
					                        for(const auto &i:IndexCreation_) {
 | 
				
			||||||
 | 
					                            Session << i , Poco::Data::Keywords::now;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    } catch (const Poco::Exception &E) {
 | 
				
			||||||
 | 
					                        Logger_.error("Failure to create POSTGRESQL DB resources.");
 | 
				
			||||||
 | 
					                        Logger_.log(E);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return Upgrade();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        [[nodiscard]] std::string ConvertParams(const std::string & S) const {
 | 
					        [[nodiscard]] std::string ConvertParams(const std::string & S) const {
 | 
				
			||||||
            if(Type!=OpenWifi::DBType::pgsql)
 | 
					            if(Type_!=OpenWifi::DBType::pgsql)
 | 
				
			||||||
                return S;
 | 
					                return S;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            std::string R;
 | 
					            std::string R;
 | 
				
			||||||
@@ -325,45 +375,59 @@ namespace ORM {
 | 
				
			|||||||
            return R;
 | 
					            return R;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void Convert( RecordTuple &in , RecordType &out);
 | 
					        void Convert( const RecordTuple &in , RecordType &out);
 | 
				
			||||||
        void Convert( RecordType &in , RecordTuple &out);
 | 
					        void Convert( const RecordType &in , RecordTuple &out);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inline const std::string & Prefix() { return Prefix_; };
 | 
					        inline const std::string & Prefix() { return Prefix_; };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        bool CreateRecord( RecordType & R) {
 | 
					        bool CreateRecord( const RecordType & R) {
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
                Poco::Data::Session     Session = Pool_.get();
 | 
					                Poco::Data::Session     Session = Pool_.get();
 | 
				
			||||||
                Poco::Data::Statement   Insert(Session);
 | 
					                Poco::Data::Statement   Insert(Session);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                RecordTuple RT;
 | 
					                RecordTuple RT;
 | 
				
			||||||
                Convert(R, RT);
 | 
					                Convert(R, RT);
 | 
				
			||||||
                std::string St = "insert into  " + DBName + " ( " + SelectFields_ + " ) values " + SelectList_;
 | 
					                std::string St = "insert into  " + TableName_ + " ( " + SelectFields_ + " ) values " + SelectList_;
 | 
				
			||||||
                Insert  << ConvertParams(St) ,
 | 
					                Insert  << ConvertParams(St) ,
 | 
				
			||||||
                    Poco::Data::Keywords::use(RT);
 | 
					                    Poco::Data::Keywords::use(RT);
 | 
				
			||||||
                Insert.execute();
 | 
					                Insert.execute();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if(Cache_)
 | 
				
			||||||
 | 
					                    Cache_->Create(R);
 | 
				
			||||||
                return true;
 | 
					                return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            } catch (const Poco::Exception &E) {
 | 
					            } catch (const Poco::Exception &E) {
 | 
				
			||||||
                Logger_.log(E);
 | 
					                Logger_.log(E);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        template<typename T> bool GetRecord( const char * FieldName, T Value,  RecordType & R) {
 | 
					        template<typename T> bool GetRecord(field_name_t FieldName, const T & Value,  RecordType & R) {
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
 | 
					 | 
				
			||||||
                assert( FieldNames_.find(FieldName) != FieldNames_.end() );
 | 
					                assert( FieldNames_.find(FieldName) != FieldNames_.end() );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if(Cache_) {
 | 
				
			||||||
 | 
					                    if(Cache_->GetFromCache(FieldName, Value, R))
 | 
				
			||||||
 | 
					                        return true;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                Poco::Data::Session     Session = Pool_.get();
 | 
					                Poco::Data::Session     Session = Pool_.get();
 | 
				
			||||||
                Poco::Data::Statement   Select(Session);
 | 
					                Poco::Data::Statement   Select(Session);
 | 
				
			||||||
                RecordTuple             RT;
 | 
					                RecordTuple             RT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                std::string St = "select " + SelectFields_ + " from " + DBName + " where " + FieldName + "=?" ;
 | 
					                std::string St = "select " + SelectFields_ + " from " + TableName_ + " where " + FieldName + "=?" ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                auto tValue{Value};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                Select  << ConvertParams(St) ,
 | 
					                Select  << ConvertParams(St) ,
 | 
				
			||||||
                    Poco::Data::Keywords::into(RT),
 | 
					                    Poco::Data::Keywords::into(RT),
 | 
				
			||||||
                    Poco::Data::Keywords::use(Value);
 | 
					                    Poco::Data::Keywords::use(tValue);
 | 
				
			||||||
                if(Select.execute()==1) {
 | 
					                Select.execute();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if(Select.rowsExtracted()==1) {
 | 
				
			||||||
                    Convert(RT,R);
 | 
					                    Convert(RT,R);
 | 
				
			||||||
 | 
					                    if(Cache_)
 | 
				
			||||||
 | 
					                        Cache_->UpdateCache(R);
 | 
				
			||||||
                    return true;
 | 
					                    return true;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                return false;
 | 
					                return false;
 | 
				
			||||||
@@ -376,7 +440,7 @@ namespace ORM {
 | 
				
			|||||||
        typedef std::vector<std::string> StringVec;
 | 
					        typedef std::vector<std::string> StringVec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        template <  typename T,
 | 
					        template <  typename T,
 | 
				
			||||||
                typename T0, typename T1> bool GR(const char *FieldName, T & R,T0 &V0, T1 &V1) {
 | 
					                typename T0, typename T1> bool GR(field_name_t FieldName, T & R,T0 &V0, T1 &V1) {
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                assert( FieldNames_.find(FieldName) != FieldNames_.end() );
 | 
					                assert( FieldNames_.find(FieldName) != FieldNames_.end() );
 | 
				
			||||||
@@ -385,7 +449,7 @@ namespace ORM {
 | 
				
			|||||||
                Poco::Data::Statement   Select(Session);
 | 
					                Poco::Data::Statement   Select(Session);
 | 
				
			||||||
                RecordTuple RT;
 | 
					                RecordTuple RT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                std::string St = "select " + SelectFields_ + " from " + DBName
 | 
					                std::string St = "select " + SelectFields_ + " from " + TableName_
 | 
				
			||||||
                                + " where " + FieldName[0] + "=? and " + FieldName[1] + "=?"  ;
 | 
					                                + " where " + FieldName[0] + "=? and " + FieldName[1] + "=?"  ;
 | 
				
			||||||
                Select  << ConvertParams(St) ,
 | 
					                Select  << ConvertParams(St) ,
 | 
				
			||||||
                    Poco::Data::Keywords::into(RT),
 | 
					                    Poco::Data::Keywords::into(RT),
 | 
				
			||||||
@@ -410,14 +474,15 @@ namespace ORM {
 | 
				
			|||||||
                Poco::Data::Session     Session = Pool_.get();
 | 
					                Poco::Data::Session     Session = Pool_.get();
 | 
				
			||||||
                Poco::Data::Statement   Select(Session);
 | 
					                Poco::Data::Statement   Select(Session);
 | 
				
			||||||
                RecordList RL;
 | 
					                RecordList RL;
 | 
				
			||||||
                std::string St = "select " + SelectFields_ + " from " + DBName +
 | 
					                std::string St = "select " + SelectFields_ + " from " + TableName_ +
 | 
				
			||||||
                        (Where.empty() ? "" : " where " + Where) + OrderBy +
 | 
					                        (Where.empty() ? "" : " where " + Where) + OrderBy +
 | 
				
			||||||
                        ComputeRange(Offset, HowMany) ;
 | 
					                        ComputeRange(Offset, HowMany) ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                Select  << St ,
 | 
					                Select  << St ,
 | 
				
			||||||
                    Poco::Data::Keywords::into(RL);
 | 
					                    Poco::Data::Keywords::into(RL);
 | 
				
			||||||
 | 
					                Select.execute();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if(Select.execute()>0) {
 | 
					                if(Select.rowsExtracted()>0) {
 | 
				
			||||||
                    for(auto &i:RL) {
 | 
					                    for(auto &i:RL) {
 | 
				
			||||||
                        RecordType  R;
 | 
					                        RecordType  R;
 | 
				
			||||||
                        Convert(i, R);
 | 
					                        Convert(i, R);
 | 
				
			||||||
@@ -432,7 +497,7 @@ namespace ORM {
 | 
				
			|||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        template <typename T> bool UpdateRecord( const char *FieldName, T & Value,  RecordType & R) {
 | 
					        template <typename T> bool UpdateRecord(field_name_t FieldName, const T & Value,  const RecordType & R) {
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
                assert( FieldNames_.find(FieldName) != FieldNames_.end() );
 | 
					                assert( FieldNames_.find(FieldName) != FieldNames_.end() );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -443,11 +508,15 @@ namespace ORM {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                Convert(R, RT);
 | 
					                Convert(R, RT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                std::string St = "update " + DBName + " set " + UpdateFields_ + " where " + FieldName + "=?" ;
 | 
					                auto tValue(Value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                std::string St = "update " + TableName_ + " set " + UpdateFields_ + " where " + FieldName + "=?" ;
 | 
				
			||||||
                Update  << ConvertParams(St) ,
 | 
					                Update  << ConvertParams(St) ,
 | 
				
			||||||
                    Poco::Data::Keywords::use(RT),
 | 
					                    Poco::Data::Keywords::use(RT),
 | 
				
			||||||
                    Poco::Data::Keywords::use(Value);
 | 
					                    Poco::Data::Keywords::use(tValue);
 | 
				
			||||||
                Update.execute();
 | 
					                Update.execute();
 | 
				
			||||||
 | 
					                if(Cache_)
 | 
				
			||||||
 | 
					                    Cache_->UpdateCache(R);
 | 
				
			||||||
                return true;
 | 
					                return true;
 | 
				
			||||||
            } catch (const Poco::Exception &E) {
 | 
					            } catch (const Poco::Exception &E) {
 | 
				
			||||||
                Logger_.log(E);
 | 
					                Logger_.log(E);
 | 
				
			||||||
@@ -455,18 +524,32 @@ namespace ORM {
 | 
				
			|||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        template <typename T> bool GetNameAndDescription(const char *FieldName, T & Value, std::string & Name, std::string & Description ) {
 | 
					        template <typename T> bool ReplaceRecord(field_name_t FieldName, const T & Value,  RecordType & R) {
 | 
				
			||||||
 | 
					            try {
 | 
				
			||||||
 | 
					                if(Exists(FieldName, Value)) {
 | 
				
			||||||
 | 
					                    return UpdateRecord(FieldName,Value,R);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                return CreateRecord(R);
 | 
				
			||||||
 | 
					            } catch (const Poco::Exception &E) {
 | 
				
			||||||
 | 
					                Logger_.log(E);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        template <typename T> bool GetNameAndDescription(field_name_t FieldName, const T & Value, std::string & Name, std::string & Description ) {
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
                assert( FieldNames_.find(FieldName) != FieldNames_.end() );
 | 
					                assert( FieldNames_.find(FieldName) != FieldNames_.end() );
 | 
				
			||||||
                Poco::Data::Session     Session = Pool_.get();
 | 
					                Poco::Data::Session     Session = Pool_.get();
 | 
				
			||||||
                Poco::Data::Statement   Select(Session);
 | 
					                Poco::Data::Statement   Select(Session);
 | 
				
			||||||
                RecordTuple             RT;
 | 
					                RecordTuple             RT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                std::string St = "select " + SelectFields_ + " from " + DBName + " where " + FieldName + "=?" ;
 | 
					                std::string St = "select " + SelectFields_ + " from " + TableName_ + " where " + FieldName + "=?" ;
 | 
				
			||||||
                RecordType R;
 | 
					                RecordType R;
 | 
				
			||||||
 | 
					                auto tValue{Value};
 | 
				
			||||||
                Select  << ConvertParams(St) ,
 | 
					                Select  << ConvertParams(St) ,
 | 
				
			||||||
                    Poco::Data::Keywords::into(RT),
 | 
					                    Poco::Data::Keywords::into(RT),
 | 
				
			||||||
                Poco::Data::Keywords::use(Value);
 | 
					                    Poco::Data::Keywords::use(tValue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if(Select.execute()==1) {
 | 
					                if(Select.execute()==1) {
 | 
				
			||||||
                    Convert(RT,R);
 | 
					                    Convert(RT,R);
 | 
				
			||||||
                    Name = R.info.name;
 | 
					                    Name = R.info.name;
 | 
				
			||||||
@@ -480,17 +563,21 @@ namespace ORM {
 | 
				
			|||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        template <typename T> bool DeleteRecord( const char *FieldName, T Value) {
 | 
					        template <typename T> bool DeleteRecord(field_name_t FieldName, const T & Value) {
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
                assert( FieldNames_.find(FieldName) != FieldNames_.end() );
 | 
					                assert( FieldNames_.find(FieldName) != FieldNames_.end() );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                Poco::Data::Session     Session = Pool_.get();
 | 
					                Poco::Data::Session     Session = Pool_.get();
 | 
				
			||||||
                Poco::Data::Statement   Delete(Session);
 | 
					                Poco::Data::Statement   Delete(Session);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                std::string St = "delete from " + DBName + " where " + FieldName + "=?" ;
 | 
					                std::string St = "delete from " + TableName_ + " where " + FieldName + "=?" ;
 | 
				
			||||||
 | 
					                auto tValue{Value};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                Delete  << ConvertParams(St) ,
 | 
					                Delete  << ConvertParams(St) ,
 | 
				
			||||||
                    Poco::Data::Keywords::use(Value);
 | 
					                    Poco::Data::Keywords::use(tValue);
 | 
				
			||||||
                Delete.execute();
 | 
					                Delete.execute();
 | 
				
			||||||
 | 
					                if(Cache_)
 | 
				
			||||||
 | 
					                    Cache_->Delete(FieldName, Value);
 | 
				
			||||||
                return true;
 | 
					                return true;
 | 
				
			||||||
            } catch (const Poco::Exception &E) {
 | 
					            } catch (const Poco::Exception &E) {
 | 
				
			||||||
                Logger_.log(E);
 | 
					                Logger_.log(E);
 | 
				
			||||||
@@ -504,7 +591,7 @@ namespace ORM {
 | 
				
			|||||||
                Poco::Data::Session     Session = Pool_.get();
 | 
					                Poco::Data::Session     Session = Pool_.get();
 | 
				
			||||||
                Poco::Data::Statement   Delete(Session);
 | 
					                Poco::Data::Statement   Delete(Session);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                std::string St = "delete from " + DBName + " where " + WhereClause;
 | 
					                std::string St = "delete from " + TableName_ + " where " + WhereClause;
 | 
				
			||||||
                Delete  << St;
 | 
					                Delete  << St;
 | 
				
			||||||
                Delete.execute();
 | 
					                Delete.execute();
 | 
				
			||||||
                return true;
 | 
					                return true;
 | 
				
			||||||
@@ -514,7 +601,7 @@ namespace ORM {
 | 
				
			|||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        bool Exists(const char *FieldName, std::string & Value) {
 | 
					        bool Exists(field_name_t FieldName, const std::string & Value) {
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
                assert( FieldNames_.find(FieldName) != FieldNames_.end() );
 | 
					                assert( FieldNames_.find(FieldName) != FieldNames_.end() );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -528,15 +615,15 @@ namespace ORM {
 | 
				
			|||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        bool Iterate( std::function<bool(const RecordType &R)> F) {
 | 
					        bool Iterate( std::function<bool(const RecordType &R)> F, const std::string & WhereClause = "" ) {
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                uint64_t    Offset=1;
 | 
					                uint64_t    Offset=0;
 | 
				
			||||||
                uint64_t    Batch=50;
 | 
					                uint64_t    Batch=50;
 | 
				
			||||||
                bool Done=false;
 | 
					                bool Done=false;
 | 
				
			||||||
                while(!Done) {
 | 
					                while(!Done) {
 | 
				
			||||||
                    std::vector<RecordType> Records;
 | 
					                    std::vector<RecordType> Records;
 | 
				
			||||||
                    if(GetRecords(Offset,Batch,Records)) {
 | 
					                    if(GetRecords(Offset,Batch,Records, WhereClause)) {
 | 
				
			||||||
                        for(const auto &i:Records) {
 | 
					                        for(const auto &i:Records) {
 | 
				
			||||||
                            if(!F(i))
 | 
					                            if(!F(i))
 | 
				
			||||||
                                return true;
 | 
					                                return true;
 | 
				
			||||||
@@ -592,7 +679,7 @@ namespace ORM {
 | 
				
			|||||||
                Poco::Data::Session     Session = Pool_.get();
 | 
					                Poco::Data::Session     Session = Pool_.get();
 | 
				
			||||||
                Poco::Data::Statement   Select(Session);
 | 
					                Poco::Data::Statement   Select(Session);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                std::string st{"SELECT COUNT(*) FROM " + DBName + " " + (Where.empty() ? "" : (" where " + Where)) };
 | 
					                std::string st{"SELECT COUNT(*) FROM " + TableName_ + " " + (Where.empty() ? "" : (" where " + Where)) };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                Select << st ,
 | 
					                Select << st ,
 | 
				
			||||||
                    Poco::Data::Keywords::into(Cnt);
 | 
					                    Poco::Data::Keywords::into(Cnt);
 | 
				
			||||||
@@ -606,7 +693,7 @@ namespace ORM {
 | 
				
			|||||||
            return 0;
 | 
					            return 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        template <typename X> bool ManipulateVectorMember( X T, const char *FieldName, std::string & ParentUUID, std::string & ChildUUID, bool Add) {
 | 
					        template <typename X> bool ManipulateVectorMember( X T, field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID, bool Add) {
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
                assert( FieldNames_.find(FieldName) != FieldNames_.end() );
 | 
					                assert( FieldNames_.find(FieldName) != FieldNames_.end() );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -633,89 +720,122 @@ namespace ORM {
 | 
				
			|||||||
            return false;
 | 
					            return false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inline bool AddChild( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) {
 | 
					        bool RunScript(const std::vector<std::string> & Statements, bool IgnoreExceptions=true) {
 | 
				
			||||||
 | 
					            try {
 | 
				
			||||||
 | 
					                Poco::Data::Session     Session = Pool_.get();
 | 
				
			||||||
 | 
					                Poco::Data::Statement   Command(Session);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                for(const auto &i:Statements) {
 | 
				
			||||||
 | 
					                    try {
 | 
				
			||||||
 | 
					                        Command << i, Poco::Data::Keywords::now;
 | 
				
			||||||
 | 
					                    } catch (const Poco::Exception &E) {
 | 
				
			||||||
 | 
					                        Logger_.log(E);
 | 
				
			||||||
 | 
					                        Logger_.error(Poco::format("The following statement '%s' generated an exception during a table upgrade. This maya or may not be a problem.", i));
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    if(!IgnoreExceptions) {
 | 
				
			||||||
 | 
					                        return false;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    Command.reset(Session);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                return true;
 | 
				
			||||||
 | 
					            } catch (const Poco::Exception &E) {
 | 
				
			||||||
 | 
					                Logger_.log(E);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        virtual uint32_t Version() {
 | 
				
			||||||
 | 
					            return 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        virtual bool Upgrade(uint32_t from, uint32_t &to) {
 | 
				
			||||||
 | 
					            to = from;
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        inline bool AddChild(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
 | 
				
			||||||
            return ManipulateVectorMember(&RecordType::children, FieldName, ParentUUID, ChildUUID, true);
 | 
					            return ManipulateVectorMember(&RecordType::children, FieldName, ParentUUID, ChildUUID, true);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inline bool DeleteChild( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) {
 | 
					        inline bool DeleteChild(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
 | 
				
			||||||
            return ManipulateVectorMember(&RecordType::children, FieldName, ParentUUID, ChildUUID, false);
 | 
					            return ManipulateVectorMember(&RecordType::children, FieldName, ParentUUID, ChildUUID, false);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inline bool AddLocation( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) {
 | 
					        inline bool AddLocation(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
 | 
				
			||||||
            return ManipulateVectorMember(&RecordType::locations, FieldName, ParentUUID, ChildUUID, true);
 | 
					            return ManipulateVectorMember(&RecordType::locations, FieldName, ParentUUID, ChildUUID, true);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inline bool DeleteLocation( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) {
 | 
					        inline bool DeleteLocation(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
 | 
				
			||||||
            return ManipulateVectorMember(&RecordType::locations, FieldName, ParentUUID, ChildUUID, false);
 | 
					            return ManipulateVectorMember(&RecordType::locations, FieldName, ParentUUID, ChildUUID, false);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inline bool AddContact( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) {
 | 
					        inline bool AddContact(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
 | 
				
			||||||
            return ManipulateVectorMember(&RecordType::contacts, FieldName, ParentUUID, ChildUUID, true);
 | 
					            return ManipulateVectorMember(&RecordType::contacts, FieldName, ParentUUID, ChildUUID, true);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inline bool DeleteContact( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) {
 | 
					        inline bool DeleteContact(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
 | 
				
			||||||
            return ManipulateVectorMember(&RecordType::contacts, FieldName, ParentUUID, ChildUUID, false);
 | 
					            return ManipulateVectorMember(&RecordType::contacts, FieldName, ParentUUID, ChildUUID, false);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inline bool AddVenue( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) {
 | 
					        inline bool AddVenue(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
 | 
				
			||||||
            return ManipulateVectorMember(&RecordType::venues, FieldName, ParentUUID, ChildUUID, true);
 | 
					            return ManipulateVectorMember(&RecordType::venues, FieldName, ParentUUID, ChildUUID, true);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inline bool DeleteVenue( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) {
 | 
					        inline bool DeleteVenue(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
 | 
				
			||||||
            return ManipulateVectorMember(&RecordType::venues, FieldName, ParentUUID, ChildUUID, false);
 | 
					            return ManipulateVectorMember(&RecordType::venues, FieldName, ParentUUID, ChildUUID, false);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inline bool AddDevice( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) {
 | 
					        inline bool AddDevice(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
 | 
				
			||||||
            return ManipulateVectorMember(&RecordType::devices, FieldName, ParentUUID, ChildUUID, true);
 | 
					            return ManipulateVectorMember(&RecordType::devices, FieldName, ParentUUID, ChildUUID, true);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inline bool DeleteDevice( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) {
 | 
					        inline bool DeleteDevice(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
 | 
				
			||||||
            return ManipulateVectorMember(&RecordType::devices, FieldName, ParentUUID, ChildUUID, false);
 | 
					            return ManipulateVectorMember(&RecordType::devices, FieldName, ParentUUID, ChildUUID, false);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inline bool AddEntity( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) {
 | 
					        inline bool AddEntity(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
 | 
				
			||||||
            return ManipulateVectorMember(&RecordType::entities, FieldName, ParentUUID, ChildUUID, true);
 | 
					            return ManipulateVectorMember(&RecordType::entities, FieldName, ParentUUID, ChildUUID, true);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inline bool DeleteEntity( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) {
 | 
					        inline bool DeleteEntity(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
 | 
				
			||||||
            return ManipulateVectorMember(&RecordType::entities, FieldName, ParentUUID, ChildUUID, false);
 | 
					            return ManipulateVectorMember(&RecordType::entities, FieldName, ParentUUID, ChildUUID, false);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inline bool AddUser( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) {
 | 
					        inline bool AddUser(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
 | 
				
			||||||
            return ManipulateVectorMember(&RecordType::users, FieldName, ParentUUID, ChildUUID, true);
 | 
					            return ManipulateVectorMember(&RecordType::users, FieldName, ParentUUID, ChildUUID, true);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inline bool DelUser( const char *FieldName, std::string & ParentUUID, std::string & ChildUUID) {
 | 
					        inline bool DelUser(field_name_t FieldName, const std::string & ParentUUID, const std::string & ChildUUID) {
 | 
				
			||||||
            return ManipulateVectorMember(&RecordType::users, FieldName, ParentUUID, ChildUUID, false);
 | 
					            return ManipulateVectorMember(&RecordType::users, FieldName, ParentUUID, ChildUUID, false);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inline bool AddInUse(const char *FieldName, std::string & ParentUUID, const std::string & Prefix, const std::string & ChildUUID) {
 | 
					        inline bool AddInUse(field_name_t FieldName, std::string & ParentUUID, const std::string & Prefix, const std::string & ChildUUID) {
 | 
				
			||||||
            std::string FakeUUID{ Prefix + ":" + ChildUUID};
 | 
					            std::string FakeUUID{ Prefix + ":" + ChildUUID};
 | 
				
			||||||
            return ManipulateVectorMember(&RecordType::inUse,FieldName, ParentUUID, FakeUUID, true);
 | 
					            return ManipulateVectorMember(&RecordType::inUse,FieldName, ParentUUID, FakeUUID, true);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inline bool DeleteInUse(const char *FieldName, std::string & ParentUUID, const std::string & Prefix, const std::string & ChildUUID) {
 | 
					        inline bool DeleteInUse(field_name_t FieldName, std::string & ParentUUID, const std::string & Prefix, const std::string & ChildUUID) {
 | 
				
			||||||
            std::string FakeUUID{ Prefix + ":" + ChildUUID};
 | 
					            std::string FakeUUID{ Prefix + ":" + ChildUUID};
 | 
				
			||||||
            return ManipulateVectorMember(&RecordType::inUse,FieldName, ParentUUID, FakeUUID, false);
 | 
					            return ManipulateVectorMember(&RecordType::inUse,FieldName, ParentUUID, FakeUUID, false);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inline bool DeleteContact(const char *FieldName, std::string & ParentUUID, const std::string & ChildUUID) {
 | 
					        inline bool DeleteContact(field_name_t FieldName, std::string & ParentUUID, const std::string & ChildUUID) {
 | 
				
			||||||
            return ManipulateVectorMember(&RecordType::contacts,FieldName, ParentUUID, ChildUUID, false);
 | 
					            return ManipulateVectorMember(&RecordType::contacts,FieldName, ParentUUID, ChildUUID, false);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inline bool AddContact(const char *FieldName, std::string & ParentUUID, const std::string & ChildUUID) {
 | 
					        inline bool AddContact(field_name_t FieldName, std::string & ParentUUID, const std::string & ChildUUID) {
 | 
				
			||||||
            return ManipulateVectorMember(&RecordType::contacts,FieldName, ParentUUID, ChildUUID, true);
 | 
					            return ManipulateVectorMember(&RecordType::contacts,FieldName, ParentUUID, ChildUUID, true);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inline bool DeleteLocation(const char *FieldName, std::string & ParentUUID, const std::string & ChildUUID) {
 | 
					        inline bool DeleteLocation(field_name_t FieldName, std::string & ParentUUID, const std::string & ChildUUID) {
 | 
				
			||||||
            return ManipulateVectorMember(&RecordType::locations,FieldName, ParentUUID, ChildUUID, false);
 | 
					            return ManipulateVectorMember(&RecordType::locations,FieldName, ParentUUID, ChildUUID, false);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inline bool AddLocation(const char *FieldName, std::string & ParentUUID, const std::string & ChildUUID) {
 | 
					        inline bool AddLocation(field_name_t FieldName, std::string & ParentUUID, const std::string & ChildUUID) {
 | 
				
			||||||
            return ManipulateVectorMember(&RecordType::locations,FieldName, ParentUUID, ChildUUID, true);
 | 
					            return ManipulateVectorMember(&RecordType::locations,FieldName, ParentUUID, ChildUUID, true);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inline bool GetInUse(const char *FieldName, std::string & UUID, std::vector<std::string> & UUIDs ) {
 | 
					        inline bool GetInUse(field_name_t FieldName, const std::string & UUID, std::vector<std::string> & UUIDs ) {
 | 
				
			||||||
            RecordType  R;
 | 
					            RecordType  R;
 | 
				
			||||||
            if(GetRecord(FieldName,UUID,R)) {
 | 
					            if(GetRecord(FieldName,UUID,R)) {
 | 
				
			||||||
                UUIDs = R.inUse;
 | 
					                UUIDs = R.inUse;
 | 
				
			||||||
@@ -725,34 +845,41 @@ namespace ORM {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        [[nodiscard]] inline std::string ComputeRange(uint64_t From, uint64_t HowMany) {
 | 
					        [[nodiscard]] inline std::string ComputeRange(uint64_t From, uint64_t HowMany) {
 | 
				
			||||||
            if(From<1) From=1;
 | 
					            if(From<1) From=0;
 | 
				
			||||||
            switch(Type) {
 | 
					            switch(Type_) {
 | 
				
			||||||
                case OpenWifi::DBType::sqlite:
 | 
					                case OpenWifi::DBType::sqlite:
 | 
				
			||||||
                    return " LIMIT " + std::to_string(From-1) + ", " + std::to_string(HowMany) +  " ";
 | 
					                    return " LIMIT " + std::to_string(From) + ", " + std::to_string(HowMany) +  " ";
 | 
				
			||||||
                case OpenWifi::DBType::pgsql:
 | 
					                case OpenWifi::DBType::pgsql:
 | 
				
			||||||
                    return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From-1) + " ";
 | 
					                    return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From) + " ";
 | 
				
			||||||
                case OpenWifi::DBType::mysql:
 | 
					                case OpenWifi::DBType::mysql:
 | 
				
			||||||
                    return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From-1) + " ";
 | 
					                    return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From) + " ";
 | 
				
			||||||
                default:
 | 
					                default:
 | 
				
			||||||
                    return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From-1) + " ";
 | 
					                    return " LIMIT " + std::to_string(HowMany) + " OFFSET " + std::to_string(From) + " ";
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Poco::Logger & Logger() { return Logger_; }
 | 
					        Poco::Logger & Logger() { return Logger_; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        bool DeleteRecordsFromCache(const char *FieldName, const std::string &Value ) {
 | 
				
			||||||
 | 
					            if(Cache_)
 | 
				
			||||||
 | 
					                Cache_->Delete(FieldName, Value);
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected:
 | 
				
			||||||
 | 
					        Poco::Data::SessionPool     &Pool_;
 | 
				
			||||||
 | 
					        Poco::Logger                &Logger_;
 | 
				
			||||||
 | 
					        std::string                 TableName_;
 | 
				
			||||||
 | 
					        DBCache<RecordType>         *Cache_= nullptr;
 | 
				
			||||||
    private:
 | 
					    private:
 | 
				
			||||||
        OpenWifi::DBType            Type;
 | 
					        OpenWifi::DBType            Type_;
 | 
				
			||||||
        std::string                 DBName;
 | 
					 | 
				
			||||||
        std::string                 CreateFields_;
 | 
					        std::string                 CreateFields_;
 | 
				
			||||||
        std::string                 SelectFields_;
 | 
					        std::string                 SelectFields_;
 | 
				
			||||||
        std::string                 SelectList_;
 | 
					        std::string                 SelectList_;
 | 
				
			||||||
        std::string                 UpdateFields_;
 | 
					        std::string                 UpdateFields_;
 | 
				
			||||||
        std::string                 IndexCreation;
 | 
					        std::vector<std::string>    IndexCreation_;
 | 
				
			||||||
        std::map<std::string,int>   FieldNames_;
 | 
					        std::map<std::string,int>   FieldNames_;
 | 
				
			||||||
        Poco::Data::SessionPool     &Pool_;
 | 
					 | 
				
			||||||
        Poco::Logger                &Logger_;
 | 
					 | 
				
			||||||
        std::string                 Prefix_;
 | 
					        std::string                 Prefix_;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
@@ -5,9 +5,7 @@
 | 
				
			|||||||
//	Created by Stephane Bourque on 2021-03-04.
 | 
					//	Created by Stephane Bourque on 2021-03-04.
 | 
				
			||||||
//	Arilia Wireless Inc.
 | 
					//	Arilia Wireless Inc.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
#ifndef UCENTRALGW_UCENTRALPROTOCOL_H
 | 
					 | 
				
			||||||
#define UCENTRALGW_UCENTRALPROTOCOL_H
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "Poco/String.h"
 | 
					#include "Poco/String.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -40,6 +38,7 @@ namespace OpenWifi::uCentralProtocol {
 | 
				
			|||||||
	static const char * LOGLINES = "loglines";
 | 
						static const char * LOGLINES = "loglines";
 | 
				
			||||||
	static const char * SEVERITY = "severity";
 | 
						static const char * SEVERITY = "severity";
 | 
				
			||||||
	static const char * ACTIVE = "active";
 | 
						static const char * ACTIVE = "active";
 | 
				
			||||||
 | 
						static const char * OVERRIDEDFS = "override_dfs";
 | 
				
			||||||
	static const char * REBOOT = "reboot";
 | 
						static const char * REBOOT = "reboot";
 | 
				
			||||||
	static const char * WHEN = "when";
 | 
						static const char * WHEN = "when";
 | 
				
			||||||
	static const char * CONFIG = "config";
 | 
						static const char * CONFIG = "config";
 | 
				
			||||||
@@ -130,5 +129,3 @@ namespace OpenWifi::uCentralProtocol {
 | 
				
			|||||||
			return ET_UNKNOWN;
 | 
								return ET_UNKNOWN;
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif // UCENTRALGW_UCENTRALPROTOCOL_H
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										13
									
								
								src/ow_version.h.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/ow_version.h.in
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					//
 | 
				
			||||||
 | 
					// Created by stephane bourque on 2021-12-06.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace OW_VERSION {
 | 
				
			||||||
 | 
					    inline static const std::string VERSION{"@CMAKE_PROJECT_VERSION@"};
 | 
				
			||||||
 | 
					    inline static const std::string BUILD{"@BUILD_NUM@"};
 | 
				
			||||||
 | 
					    inline static const std::string HASH{"@GIT_HASH@"};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										341
									
								
								src/seclibs/cpptotp/bytes.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										341
									
								
								src/seclibs/cpptotp/bytes.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,341 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @file bytes.cpp
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @brief Byte-related operations.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @copyright The contents of this file have been placed into the public domain;
 | 
				
			||||||
 | 
					 * see the file COPYING for more details.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "bytes.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					#include <stdexcept>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <cassert>
 | 
				
			||||||
 | 
					#include <cstdlib>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace CppTotp
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					namespace Bytes
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void clearByteString(ByteString * bstr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						volatile Byte * bs = const_cast<volatile Byte *>(bstr->data());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (size_t i = 0; i < bstr->size(); ++i)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							bs[i] = Byte(0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void swizzleByteStrings(ByteString * target, ByteString * source)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						clearByteString(target);
 | 
				
			||||||
 | 
						target->assign(*source);
 | 
				
			||||||
 | 
						clearByteString(source);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static char nibbleToLCHex(uint8_t nib)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (nib < 0xa)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return static_cast<char>(nib + '0');
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if (nib < 0x10)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return static_cast<char>((nib - 10) + 'a');
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							assert(0 && "not actually a nibble");
 | 
				
			||||||
 | 
							return '\0';
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint8_t hexToNibble(char c)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (c >= '0' && c <= '9')
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return static_cast<uint8_t>(c - '0');
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if (c >= 'A' && c <= 'F')
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return static_cast<uint8_t>(c - 'A' + 10);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else if (c >= 'a' && c <= 'f')
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return static_cast<uint8_t>(c - 'a' + 10);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							assert(0 && "not actually a hex digit");
 | 
				
			||||||
 | 
							return 0xff;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::string toHexString(const ByteString & bstr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						std::string ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (Byte b : bstr)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							ret.push_back(nibbleToLCHex((b >> 4) & 0x0F));
 | 
				
			||||||
 | 
							ret.push_back(nibbleToLCHex((b >> 0) & 0x0F));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ByteString fromHexStringSkipUnknown(const std::string & str)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						std::string hstr;
 | 
				
			||||||
 | 
						for (char c : str)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (
 | 
				
			||||||
 | 
								(c >= '0' && c <= '9') ||
 | 
				
			||||||
 | 
								(c >= 'A' && c <= 'F') ||
 | 
				
			||||||
 | 
								(c >= 'a' && c <= 'f')
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								hstr.push_back(c);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							// ignore otherwise
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (hstr.size() % 2 != 0)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							throw std::invalid_argument("hex string (unknown characters ignored) length not divisible by 2");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ByteString ret;
 | 
				
			||||||
 | 
						for (size_t i = 0; i < hstr.size(); i += 2)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							uint8_t top = hexToNibble(hstr[i+0]);
 | 
				
			||||||
 | 
							uint8_t btm = hexToNibble(hstr[i+1]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							ret.push_back((top << 4) | btm);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Bytes::ByteString u32beToByteString(uint32_t num)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						Bytes::ByteString ret;
 | 
				
			||||||
 | 
						ret.push_back((num >> 24) & 0xFF);
 | 
				
			||||||
 | 
						ret.push_back((num >> 16) & 0xFF);
 | 
				
			||||||
 | 
						ret.push_back((num >>  8) & 0xFF);
 | 
				
			||||||
 | 
						ret.push_back((num >>  0) & 0xFF);
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Bytes::ByteString u64beToByteString(uint64_t num)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						Bytes::ByteString left  = u32beToByteString((num >> 32) & 0xFFFFFFFF);
 | 
				
			||||||
 | 
						Bytes::ByteString right = u32beToByteString((num >>  0) & 0xFFFFFFFF);
 | 
				
			||||||
 | 
						return left + right;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static ByteString b32ChunkToBytes(const std::string & str)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						ByteString ret;
 | 
				
			||||||
 | 
						uint64_t whole = 0x00;
 | 
				
			||||||
 | 
						size_t padcount = 0;
 | 
				
			||||||
 | 
						size_t finalcount;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (str.length() != 8)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							throw std::invalid_argument("incorrect length of base32 chunk");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						size_t i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < 8; ++i)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							char c = str[i];
 | 
				
			||||||
 | 
							uint64_t bits;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (c == '=')
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								bits = 0;
 | 
				
			||||||
 | 
								++padcount;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if (padcount > 0)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								throw std::invalid_argument("padding character followed by non-padding character");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if (c >= 'A' && c <= 'Z')
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								bits = static_cast<Byte>(c - 'A');
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if (c >= '2' && c <= '7')
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								bits = static_cast<Byte>(c - '2' + 26);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								throw std::invalid_argument("not a base32 character: " + std::string(1, c));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// shift into the chunk
 | 
				
			||||||
 | 
							whole |= (bits << ((7-i)*5));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (padcount)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						case 0:
 | 
				
			||||||
 | 
							finalcount = 5;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case 1:
 | 
				
			||||||
 | 
							finalcount = 4;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case 3:
 | 
				
			||||||
 | 
							finalcount = 3;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case 4:
 | 
				
			||||||
 | 
							finalcount = 2;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case 6:
 | 
				
			||||||
 | 
							finalcount = 1;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							throw std::invalid_argument("invalid number of padding characters");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < finalcount; ++i)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							// shift out of the chunk
 | 
				
			||||||
 | 
							ret.push_back(static_cast<Byte>((whole >> ((4-i)*8)) & 0xFF));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline uint64_t u64(uint8_t n)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return static_cast<uint64_t>(n);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static std::string bytesToB32Chunk(const ByteString & bs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (bs.size() < 1 || bs.size() > 5)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							throw std::invalid_argument("need a chunk of at least 1 and at most 5 bytes");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						uint64_t whole = 0x00;
 | 
				
			||||||
 | 
						size_t putchars = 2;
 | 
				
			||||||
 | 
						std::string ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// shift into the chunk
 | 
				
			||||||
 | 
						whole |= (u64(bs[0]) << 32);
 | 
				
			||||||
 | 
						if (bs.size() > 1)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							whole |= (u64(bs[1]) << 24);
 | 
				
			||||||
 | 
							putchars += 2;  // at least 4
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (bs.size() > 2)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							whole |= (u64(bs[2]) << 16);
 | 
				
			||||||
 | 
							++putchars;  // at least 5
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (bs.size() > 3)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							whole |= (u64(bs[3]) <<  8);
 | 
				
			||||||
 | 
							putchars += 2;  // at least 7
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (bs.size() > 4)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							whole |= u64(bs[4]);
 | 
				
			||||||
 | 
							++putchars;  // at least 8
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						size_t i;
 | 
				
			||||||
 | 
						for (i = 0; i < putchars; ++i)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							// shift out of the chunk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Byte val = (whole >> ((7-i)*5)) & 0x1F;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// map bits to base32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (val < 26)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								ret.push_back(static_cast<char>(val + 'A'));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								ret.push_back(static_cast<char>(val - 26 + '2'));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// pad
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = putchars; i < 8; ++i)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							ret.push_back('=');
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ByteString fromBase32(const std::string & b32str)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (b32str.size() % 8 != 0)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							throw std::invalid_argument("base32 string length not divisible by 8");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ByteString ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (size_t i = 0; i < b32str.size(); i += 8)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							std::string sub(b32str, i, 8);
 | 
				
			||||||
 | 
							ByteString chk = b32ChunkToBytes(sub);
 | 
				
			||||||
 | 
							ret.append(chk);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ByteString fromUnpaddedBase32(const std::string & b32str)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						std::string newstr = b32str;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (newstr.size() % 8 != 0)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							newstr.push_back('=');
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return fromBase32(newstr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::string toBase32(const ByteString & bs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						std::string ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						size_t i, j, len;
 | 
				
			||||||
 | 
						for (j = 0; j < bs.size() / 5; ++j)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							i = j * 5;
 | 
				
			||||||
 | 
							ByteString sub(bs, i, 5);
 | 
				
			||||||
 | 
							std::string chk = bytesToB32Chunk(sub);
 | 
				
			||||||
 | 
							ret.append(chk);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						i = j * 5;
 | 
				
			||||||
 | 
						len = bs.size() - i;
 | 
				
			||||||
 | 
						if (len > 0)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							// block of size < 5 remains
 | 
				
			||||||
 | 
							ByteString sub(bs, i, std::string::npos);
 | 
				
			||||||
 | 
							std::string chk = bytesToB32Chunk(sub);
 | 
				
			||||||
 | 
							ret.append(chk);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user