mirror of
				https://github.com/Telecominfraproject/wlan-cloud-owprov.git
				synced 2025-10-31 02:27:52 +00:00 
			
		
		
		
	Compare commits
	
		
			450 Commits
		
	
	
		
			v2.5.0
			...
			release/v2
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 16f429b056 | ||
|   | af7cbf0ce1 | ||
|   | d50e8c0c44 | ||
|   | c5e44f2a98 | ||
|   | 5c2937c7ec | ||
|   | 698b467d3f | ||
|   | a8f1483362 | ||
|   | 693814de1c | ||
|   | 0394369410 | ||
|   | 5abe7a9909 | ||
|   | 0a3a9a4b20 | ||
|   | 9d4eb1e502 | ||
|   | 0b6d68def5 | ||
|   | 51ba962338 | ||
|   | fef07e3150 | ||
|   | 03a6675359 | ||
|   | 19686da4d8 | ||
|   | c5997a3511 | ||
|   | 3feb5fd666 | ||
|   | d3cd3a1a21 | ||
|   | 5e6228b9d6 | ||
|   | ad526ebf1d | ||
|   | 8de53277e6 | ||
|   | 93fbb3017a | ||
|   | 2e4d1ad3e8 | ||
|   | 109a9affc5 | ||
|   | 9c65813735 | ||
|   | 7d0bdf059d | ||
|   | 93e4b069c4 | ||
|   | 4fe1367651 | ||
|   | 5f5f2fd699 | ||
|   | c2e0d32e0d | ||
|   | cab81a3930 | ||
|   | 01395f11a3 | ||
|   | 250c12acf1 | ||
|   | e23d04c1d0 | ||
|   | b48955e791 | ||
|   | e58eb38d53 | ||
|   | 791af9aeba | ||
|   | 67081917a9 | ||
|   | 3a33815096 | ||
|   | f515bb8e30 | ||
|   | 02fd6d726a | ||
|   | 27ffb31a7c | ||
|   | 5fd9831d6b | ||
|   | fed085cc4a | ||
|   | 121fee841e | ||
|   | 4c6f03ba14 | ||
|   | 0fb9478675 | ||
|   | 97c2af83fd | ||
|   | 599ba0793c | ||
|   | 6df780dba3 | ||
|   | a00287ae85 | ||
|   | c7a300b81e | ||
|   | 5dc507a82e | ||
|   | 8b3e1326b7 | ||
|   | 667f8bc4bd | ||
|   | 6cacebad28 | ||
|   | e487b68945 | ||
|   | ffddfa87d2 | ||
|   | 0168301d6b | ||
|   | 1a0b00e989 | ||
|   | 7c2229f3d6 | ||
|   | 541df429ec | ||
|   | 6f9fe6cd5d | ||
|   | 2594a2c5f2 | ||
|   | 2e02d96523 | ||
|   | a1375f9468 | ||
|   | 777bc0f2aa | ||
|   | bd0e99309c | ||
|   | 6cb6a60142 | ||
|   | fc7947394d | ||
|   | 1341e15874 | ||
|   | f065815df3 | ||
|   | 03ba51e869 | ||
|   | efd7ef2a9b | ||
|   | 4b90a6e893 | ||
|   | f5cb4a5a87 | ||
|   | e3e4aac202 | ||
|   | 5945d02b3d | ||
|   | 0ac192cdc0 | ||
|   | 1b5eb87eef | ||
|   | 46db18d7cd | ||
|   | 30b8665d7d | ||
|   | c8b3a3b060 | ||
|   | 096da35ff4 | ||
|   | bd7f3af11c | ||
|   | 2a06021c4a | ||
|   | bf18bb25ba | ||
|   | e93f899b76 | ||
|   | eda73038f6 | ||
|   | 953ca155a4 | ||
|   | 898806f232 | ||
|   | 7d97b19b85 | ||
|   | d6c587fde6 | ||
|   | 58c9a7805b | ||
|   | 94dd4c84e9 | ||
|   | 2636715f6f | ||
|   | f9f4624add | ||
|   | cf441de197 | ||
|   | 158455a528 | ||
|   | 4d2ccec1a8 | ||
|   | 7dad5a9bdb | ||
|   | cd2ac84c5b | ||
|   | 9735f709e9 | ||
|   | ae5fd31818 | ||
|   | 2b46ad4a66 | ||
|   | 43d7078cb7 | ||
|   | 18f5d42f00 | ||
|   | 70622b2bb8 | ||
|   | 5b24aea47c | ||
|   | e97617a0db | ||
|   | ba63a7033f | ||
|   | e9db2e1a0d | ||
|   | d85fef7725 | ||
|   | 543c46bf68 | ||
|   | 73eec53fe4 | ||
|   | 8ad2d67c2c | ||
|   | 442f810688 | ||
|   | 2dca5204ea | ||
|   | dc2abe2154 | ||
|   | 8c14bb5b3a | ||
|   | 6ec4bc7115 | ||
|   | 9883a40ec6 | ||
|   | cc647b8108 | ||
|   | 3b0f2a0977 | ||
|   | dfefe39188 | ||
|   | 7d65e19d29 | ||
|   | 1e16c59743 | ||
|   | 4582cbd133 | ||
|   | 18e4b68c1f | ||
|   | 46a11ebda2 | ||
|   | a2fc2a939a | ||
|   | 8fe1b08859 | ||
|   | 7091bfe75b | ||
|   | b9a3643e11 | ||
|   | fb065dd0e4 | ||
|   | 744b6c4b2a | ||
|   | 4abec884bf | ||
|   | 428639c879 | ||
|   | fd16ed8b38 | ||
|   | cfe4fefd0e | ||
|   | 9e1e5381ef | ||
|   | ce366dc18c | ||
|   | 047b9493ed | ||
|   | 69ae06dc0c | ||
|   | 74aa7f7f41 | ||
|   | 651654c0b5 | ||
|   | a573e1df83 | ||
|   | 88ce933a81 | ||
|   | c4a9867730 | ||
|   | 1bf078c2f1 | ||
|   | 81d6c9611f | ||
|   | 5228066b65 | ||
|   | 8f78aec565 | ||
|   | 409fc756cd | ||
|   | 1b6e8f37de | ||
|   | b30b6c00f3 | ||
|   | b043dcc867 | ||
|   | 6404430af8 | ||
|   | e109d71ea3 | ||
|   | d5a60e9066 | ||
|   | 497ce6cd78 | ||
|   | b72254dd7a | ||
|   | 3cb908c9ed | ||
|   | 61f00f2036 | ||
|   | 75a3e57e9d | ||
|   | 84cf98d6a8 | ||
|   | 973823004a | ||
|   | 9686675090 | ||
|   | bf416f0470 | ||
|   | 6d29c8e5ce | ||
|   | 518f950078 | ||
|   | a149f167ec | ||
|   | e0d45d50d6 | ||
|   | 35890f3be4 | ||
|   | a333e49c5f | ||
|   | 25b156a586 | ||
|   | 3d4b7356a3 | ||
|   | 45b251f100 | ||
|   | 536802f43e | ||
|   | d2262fc975 | ||
|   | cd91c8db37 | ||
|   | e68a132c64 | ||
|   | 1fd917d8e7 | ||
|   | c5ba57643d | ||
|   | 8de57f525c | ||
|   | 59c1f3afbb | ||
|   | 8ff889e06e | ||
|   | de21bb5927 | ||
|   | cbaf3fcb5f | ||
|   | e342b419c7 | ||
|   | 3952403f1e | ||
|   | 642dd63fa9 | ||
|   | 6fd6aea01e | ||
|   | 77585630c0 | ||
|   | 4df53868f1 | ||
|   | b7b4fa5cbd | ||
|   | 4e1be7cc13 | ||
|   | 38b5c9ef24 | ||
|   | fdf9b90d39 | ||
|   | d8968b9123 | ||
|   | e87c2c1826 | ||
|   | cacb3e2887 | ||
|   | fc442a22b2 | ||
|   | 2d19d1cda7 | ||
|   | 0e35ebf49f | ||
|   | f97185e0d9 | ||
|   | 667a43f87f | ||
|   | 2cbcdb20c8 | ||
|   | 078da53234 | ||
|   | be8281a2f5 | ||
|   | eb48f9841b | ||
|   | 8f0763f812 | ||
|   | 15a274d416 | ||
|   | 0d06634a4d | ||
|   | 811f13627f | ||
|   | ee260416a5 | ||
|   | d0f986a7f9 | ||
|   | c816c0754a | ||
|   | d93f1348c8 | ||
|   | 138f7654e1 | ||
|   | e28a0634e0 | ||
|   | 6a6ed64505 | ||
|   | 6c28f4ad7d | ||
|   | a04d581a84 | ||
|   | 40baf47011 | ||
|   | 981e845460 | ||
|   | 998ca93895 | ||
|   | 165b0eea9e | ||
|   | b8e2698780 | ||
|   | d8106d5d19 | ||
|   | a76a98c3f1 | ||
|   | d9cf529a40 | ||
|   | 35e1d94718 | ||
|   | 2f7c145908 | ||
|   | 4858b857c6 | ||
|   | 407ab7d598 | ||
|   | 59c7004342 | ||
|   | b61ada1552 | ||
|   | 9452a49f9c | ||
|   | 3a758b6fbd | ||
|   | 25a7b546ae | ||
|   | 420f9a3bb5 | ||
|   | c2e34b228d | ||
|   | dfa62fc33d | ||
|   | 768af0cad6 | ||
|   | 19583fe6b7 | ||
|   | c600d3fc21 | ||
|   | b8727bf4a0 | ||
|   | 8952937a1f | ||
|   | 5e6438ffe0 | ||
|   | 9712c41c64 | ||
|   | df390466d5 | ||
|   | 1b853b385d | ||
|   | 4c7d2bff28 | ||
|   | a113cd0996 | ||
|   | 3f6108bfd9 | ||
|   | ce5250598c | ||
|   | 53b1434900 | ||
|   | 0510c8e51f | ||
|   | c7f71e165b | ||
|   | c1f0817631 | ||
|   | cebf674a4d | ||
|   | 15c0220f73 | ||
|   | 9d6ffbe25c | ||
|   | f36a9f5dba | ||
|   | 65d7b28d77 | ||
|   | 6dbf33d764 | ||
|   | 65467b7320 | ||
|   | 59b752aa92 | ||
|   | 7e06a2b84d | ||
|   | ae9c293b69 | ||
|   | b0775f19f9 | ||
|   | 266266481e | ||
|   | c1454462c8 | ||
|   | 0e837049bf | ||
|   | b68c4096df | ||
|   | b51c2b76e0 | ||
|   | 3090e9b9b5 | ||
|   | 84e3229bec | ||
|   | 3d1a1a20d3 | ||
|   | 09b18f6e43 | ||
|   | b1d519a178 | ||
|   | 2a925646e9 | ||
|   | 556bef4227 | ||
|   | 78e36ba24e | ||
|   | 9e5c923d3b | ||
|   | 6a05e01a01 | ||
|   | 97a56f782e | ||
|   | bc0f08c2cb | ||
|   | 9cc315d700 | ||
|   | a5d743bf2f | ||
|   | 800ec1c607 | ||
|   | 352343d10c | ||
|   | b32ddeb283 | ||
|   | 8cd25ebe3a | ||
|   | 43a095831b | ||
|   | 1282d8dfb0 | ||
|   | 9f76803c30 | ||
|   | 0a7d5d8a1d | ||
|   | c6efb7a80b | ||
|   | 84376a07c9 | ||
|   | 20d09b8f31 | ||
|   | 453f1c267c | ||
|   | becec36a03 | ||
|   | b7c74128a2 | ||
|   | 9d7b3c8f98 | ||
|   | 3e3dee0515 | ||
|   | 3f2989fd4e | ||
|   | b017e474de | ||
|   | ab7e5ed87a | ||
|   | f9a83258a9 | ||
|   | c4516d30a8 | ||
|   | fa73ad35ea | ||
|   | 4186b5491e | ||
|   | f758722685 | ||
|   | 4d3c17977a | ||
|   | 916229e47d | ||
|   | a8773bdf30 | ||
|   | cf072e921d | ||
|   | b483d16a4a | ||
|   | 13b0daa240 | ||
|   | 4f3b80340e | ||
|   | a9d031b56c | ||
|   | 8891e56311 | ||
|   | 697f85c195 | ||
|   | 144e5a3480 | ||
|   | f47447d931 | ||
|   | b9b2bf5524 | ||
|   | e04988fcac | ||
|   | 2aba988dba | ||
|   | e614144de9 | ||
|   | 078107d93d | ||
|   | 8134dfcd61 | ||
|   | 6739cfbd64 | ||
|   | 7bc4766c35 | ||
|   | 20070a060f | ||
|   | b68eddcd26 | ||
|   | a0491820f5 | ||
|   | 503d3afc76 | ||
|   | 8763405a05 | ||
|   | a75e5fe79e | ||
|   | 1118fa8b0e | ||
|   | 5416db9037 | ||
|   | a53b906f9e | ||
|   | 8c3876630e | ||
|   | 5ef5f2aaaf | ||
|   | 40db30839f | ||
|   | 1eff3ba5b6 | ||
|   | c415fe5805 | ||
|   | 6ec7f78caa | ||
|   | fcfc2183a2 | ||
|   | 829f27682a | ||
|   | e3b9d0ea1d | ||
|   | 5e3280401c | ||
|   | 87cdc894e4 | ||
|   | 244cc423b8 | ||
|   | 1035f94f1c | ||
|   | 6a637a737a | ||
|   | edb858e832 | ||
|   | ae1e31a358 | ||
|   | 52c9184bde | ||
|   | 1483b1fdd1 | ||
|   | 4995926afc | ||
|   | b7cb7a295d | ||
|   | 2080d18099 | ||
|   | db31297686 | ||
|   | d8b459e744 | ||
|   | b2bd7adfcc | ||
|   | 1c33a4640f | ||
|   | 03fee2646a | ||
|   | 80fde2f0f4 | ||
|   | 23b2668378 | ||
|   | 83f9f2b42b | ||
|   | 705a183f06 | ||
|   | c13643a0bd | ||
|   | 7c7fbbcc4f | ||
|   | d6d2d3b277 | ||
|   | deaba74855 | ||
|   | a870c5130b | ||
|   | fca6ca235a | ||
|   | d886876cf8 | ||
|   | 72d7f16337 | ||
|   | 0221b79816 | ||
|   | 9b7bb31be8 | ||
|   | 87277d08f3 | ||
|   | 261fa5759c | ||
|   | 68a4f44cc7 | ||
|   | 10dbfbae27 | ||
|   | 3f83a7c937 | ||
|   | 6e734885c2 | ||
|   | adbd13663e | ||
|   | f66522ca51 | ||
|   | 66974e96a4 | ||
|   | bea59b7bd7 | ||
|   | 9760144965 | ||
|   | ac905c92b5 | ||
|   | 6a9d0cee55 | ||
|   | 63484acb63 | ||
|   | 728db00477 | ||
|   | dd5448c10e | ||
|   | 0a846f0aa3 | ||
|   | d1ab83d3d0 | ||
|   | 85be844bd5 | ||
|   | 347fa7825f | ||
|   | caebebdb64 | ||
|   | faaccb5595 | ||
|   | d1cc3a8001 | ||
|   | 7ea4b8b6c2 | ||
|   | a2d9e2a8a5 | ||
|   | e817a54769 | ||
|   | 89206bd104 | ||
|   | 17596b89f9 | ||
|   | 7b27a9d41d | ||
|   | 09e4f15f20 | ||
|   | dc74b2e23d | ||
|   | 5141ac9914 | ||
|   | c52808e3ce | ||
|   | fa069825fb | ||
|   | 51c748e5b3 | ||
|   | 231cf3289b | ||
|   | 55b3e96ff0 | ||
|   | 72dd336b08 | ||
|   | 73a096b0ad | ||
|   | df70ec8f40 | ||
|   | 89d81c0dcb | ||
|   | 1cd2c5f6ba | ||
|   | 6bf952cba0 | ||
|   | 5d190483e2 | ||
|   | 874e8d81d9 | ||
|   | ef778897bd | ||
|   | 05426fdd98 | ||
|   | 8f78573127 | ||
|   | 281d2131b9 | ||
|   | ed82d7625d | ||
|   | 19141ae17c | ||
|   | 3a1c51c252 | ||
|   | 8f7f381ae0 | ||
|   | ec1439bed1 | ||
|   | eac5213277 | ||
|   | b3ab9b5e1f | ||
|   | d9e9afef62 | ||
|   | d4a13d56bc | ||
|   | fb01f895d4 | ||
|   | b63a886d86 | ||
|   | 90a13341cc | ||
|   | c5aaa5d90c | ||
|   | 2212dc8e71 | ||
|   | b76b73c0e2 | 
							
								
								
									
										35
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										35
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							| @@ -13,6 +13,7 @@ on: | |||||||
|   pull_request: |   pull_request: | ||||||
|     branches: |     branches: | ||||||
|       - main |       - main | ||||||
|  |       - 'release/*' | ||||||
|  |  | ||||||
| defaults: | defaults: | ||||||
|   run: |   run: | ||||||
| @@ -39,6 +40,16 @@ jobs: | |||||||
|         registry_user: ucentral |         registry_user: ucentral | ||||||
|         registry_password: ${{ secrets.DOCKER_REGISTRY_PASSWORD }} |         registry_password: ${{ secrets.DOCKER_REGISTRY_PASSWORD }} | ||||||
|  |  | ||||||
|  |     - name: Notify on failure via Slack | ||||||
|  |       if: failure() && github.ref == 'refs/heads/main' | ||||||
|  |       uses: rtCamp/action-slack-notify@v2 | ||||||
|  |       env: | ||||||
|  |         SLACK_USERNAME: GitHub Actions failure notifier | ||||||
|  |         SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} | ||||||
|  |         SLACK_COLOR: "${{ job.status }}" | ||||||
|  |         SLACK_ICON: https://raw.githubusercontent.com/quintessence/slack-icons/master/images/github-logo-slack-icon.png | ||||||
|  |         SLACK_TITLE: Docker build failed for OWProv service | ||||||
|  |  | ||||||
|   trigger-testing: |   trigger-testing: | ||||||
|     if: startsWith(github.ref, 'refs/pull/') |     if: startsWith(github.ref, 'refs/pull/') | ||||||
|     runs-on: ubuntu-latest |     runs-on: ubuntu-latest | ||||||
| @@ -67,4 +78,26 @@ jobs: | |||||||
|         workflow: ow_docker-compose.yml |         workflow: ow_docker-compose.yml | ||||||
|         token: ${{ secrets.WLAN_TESTING_PAT }} |         token: ${{ secrets.WLAN_TESTING_PAT }} | ||||||
|         ref: master |         ref: master | ||||||
|         inputs: '{"owgw_version": "${{ env.OWGW_BASE_BRANCH }}", "owgwui_version": "${{ env.BASE_BRANCH }}", "owsec_version": "${{ env.BASE_BRANCH }}", "owfms_version": "${{ env.BASE_BRANCH }}", "owprov_version": "${{ github.sha }}", "owprovui_version": "${{ env.BASE_BRANCH }}"}' |         inputs: '{"deployment_version": "${{ env.BASE_BRANCH }}", "owgw_version": "${{ env.OWGW_BASE_BRANCH }}", "owsec_version": "${{ env.BASE_BRANCH }}", "owfms_version": "${{ env.BASE_BRANCH }}", "owprov_version": "${{ github.sha }}", "owanalytics_version": "${{ env.BASE_BRANCH }}", "owsub_version": "${{ env.BASE_BRANCH }}", "microservice": "all"}' | ||||||
|  |  | ||||||
|  |   trigger-deploy-to-dev: | ||||||
|  |     runs-on: ubuntu-latest | ||||||
|  |     if: github.ref == 'refs/heads/main' | ||||||
|  |     needs: | ||||||
|  |       - docker | ||||||
|  |     steps: | ||||||
|  |     - name: Checkout actions repo | ||||||
|  |       uses: actions/checkout@v2 | ||||||
|  |       with: | ||||||
|  |         repository: Telecominfraproject/.github | ||||||
|  |         path: github | ||||||
|  |  | ||||||
|  |     - name: Trigger deployment of the latest version to dev instance and wait for result | ||||||
|  |       uses: ./github/composite-actions/trigger-workflow-and-wait | ||||||
|  |       with: | ||||||
|  |         owner: Telecominfraproject | ||||||
|  |         repo: wlan-testing | ||||||
|  |         workflow: ucentralgw-dev-deployment.yaml | ||||||
|  |         token: ${{ secrets.WLAN_TESTING_PAT }} | ||||||
|  |         ref: master | ||||||
|  |         inputs: '{"force_latest": "true"}' | ||||||
|   | |||||||
							
								
								
									
										9
									
								
								.github/workflows/cleanup.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								.github/workflows/cleanup.yml
									
									
									
									
										vendored
									
									
								
							| @@ -4,6 +4,7 @@ on: | |||||||
|   pull_request: |   pull_request: | ||||||
|     branches: |     branches: | ||||||
|       - main |       - main | ||||||
|  |       - 'release/*' | ||||||
|     types: [ closed ] |     types: [ closed ] | ||||||
|  |  | ||||||
| defaults: | defaults: | ||||||
| @@ -16,4 +17,10 @@ jobs: | |||||||
|     steps: |     steps: | ||||||
|       - run: | |       - run: | | ||||||
|           export PR_BRANCH_TAG=$(echo ${GITHUB_HEAD_REF#refs/heads/} | tr '/' '-') |           export PR_BRANCH_TAG=$(echo ${GITHUB_HEAD_REF#refs/heads/} | tr '/' '-') | ||||||
|           curl -uucentral:${{ secrets.DOCKER_REGISTRY_PASSWORD }} -X DELETE "https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral/owprov/$PR_BRANCH_TAG" |  | ||||||
|  |           if [[ ! $PR_BRANCH_TAG =~ (main|master|release-*) ]]; then | ||||||
|  |             echo "PR branch is $PR_BRANCH_TAG, deleting Docker image" | ||||||
|  |             curl -s -uucentral:${{ secrets.DOCKER_REGISTRY_PASSWORD }} -X DELETE "https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral/owprov/$PR_BRANCH_TAG" | ||||||
|  |           else | ||||||
|  |             echo "PR branch is $PR_BRANCH_TAG, not deleting Docker image" | ||||||
|  |           fi | ||||||
|   | |||||||
							
								
								
									
										46
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | |||||||
|  | name: Release chart package | ||||||
|  |  | ||||||
|  | on: | ||||||
|  |   push: | ||||||
|  |     tags: | ||||||
|  |       - 'v*' | ||||||
|  |  | ||||||
|  | defaults: | ||||||
|  |   run: | ||||||
|  |     shell: bash | ||||||
|  |  | ||||||
|  | jobs: | ||||||
|  |   helm-package: | ||||||
|  |     runs-on: ubuntu-20.04 | ||||||
|  |     env: | ||||||
|  |       HELM_REPO_URL: https://tip.jfrog.io/artifactory/tip-wlan-cloud-ucentral-helm/ | ||||||
|  |       HELM_REPO_USERNAME: ucentral | ||||||
|  |     steps: | ||||||
|  |       - name: Checkout uCentral assembly chart repo | ||||||
|  |         uses: actions/checkout@v2 | ||||||
|  |         with: | ||||||
|  |           path: wlan-cloud-owprov | ||||||
|  |  | ||||||
|  |       - name: Build package | ||||||
|  |         working-directory: wlan-cloud-owprov/helm | ||||||
|  |         run: | | ||||||
|  |           helm plugin install https://github.com/aslafy-z/helm-git --version 0.10.0 | ||||||
|  |           helm repo add bitnami https://charts.bitnami.com/bitnami | ||||||
|  |           helm repo update | ||||||
|  |           helm dependency update | ||||||
|  |           mkdir dist | ||||||
|  |           helm package . -d dist | ||||||
|  |  | ||||||
|  |       - name: Generate GitHub release body | ||||||
|  |         working-directory: wlan-cloud-owprov/helm | ||||||
|  |         run: | | ||||||
|  |           pip3 install yq -q | ||||||
|  |           echo "Docker image - tip-tip-wlan-cloud-ucentral.jfrog.io/owprov:$GITHUB_REF_NAME" > release.txt | ||||||
|  |           echo "Helm charted may be attached to this release" >> release.txt | ||||||
|  |           echo "Deployment artifacts may be found in https://github.com/Telecominfraproject/wlan-cloud-ucentral-deploy/tree/$GITHUB_REF_NAME" >> release.txt | ||||||
|  |  | ||||||
|  |       - name: Create GitHub release | ||||||
|  |         uses: softprops/action-gh-release@v1 | ||||||
|  |         with: | ||||||
|  |           body_path: wlan-cloud-owprov/helm/release.txt | ||||||
|  |           files: wlan-cloud-owprov/helm/dist/* | ||||||
| @@ -1,5 +1,5 @@ | |||||||
| cmake_minimum_required(VERSION 3.13) | cmake_minimum_required(VERSION 3.13) | ||||||
| project(owprov VERSION 2.5.0) | project(owprov VERSION 2.7.0) | ||||||
|  |  | ||||||
| set(CMAKE_CXX_STANDARD 17) | set(CMAKE_CXX_STANDARD 17) | ||||||
|  |  | ||||||
| @@ -39,17 +39,11 @@ endif() | |||||||
|  |  | ||||||
| add_definitions(-DAWS_CUSTOM_MEMORY_MANAGEMENT) | add_definitions(-DAWS_CUSTOM_MEMORY_MANAGEMENT) | ||||||
|  |  | ||||||
| set(BUILD_SHARED_LIBS 1) |  | ||||||
| set(Boost_USE_STATIC_LIBS OFF) |  | ||||||
| set(Boost_USE_MULTITHREADED ON) |  | ||||||
| set(Boost_USE_STATIC_RUNTIME OFF) |  | ||||||
|  |  | ||||||
| find_package(Boost      REQUIRED system) |  | ||||||
| find_package(OpenSSL    REQUIRED) | find_package(OpenSSL    REQUIRED) | ||||||
| find_package(AWSSDK     REQUIRED COMPONENTS s3) |  | ||||||
| find_package(Poco       REQUIRED COMPONENTS Crypto JWT Net Util NetSSL Data DataSQLite) | find_package(Poco       REQUIRED COMPONENTS Crypto JWT Net Util NetSSL Data DataSQLite) | ||||||
| find_package(nlohmann_json  REQUIRED) | find_package(nlohmann_json  REQUIRED) | ||||||
| find_package(nlohmann_json_schema_validator REQUIRED) | find_package(nlohmann_json_schema_validator REQUIRED) | ||||||
|  | find_package(fmt        REQUIRED) | ||||||
|  |  | ||||||
| if(SMALL_BUILD) | if(SMALL_BUILD) | ||||||
|     find_package(Poco REQUIRED COMPONENTS Crypto JWT Net Util NetSSL Data DataSQLite) |     find_package(Poco REQUIRED COMPONENTS Crypto JWT Net Util NetSSL Data DataSQLite) | ||||||
| @@ -64,6 +58,14 @@ include_directories(/usr/local/include  /usr/local/opt/openssl/include src inclu | |||||||
|  |  | ||||||
| configure_file(src/ow_version.h.in ${PROJECT_SOURCE_DIR}/src/ow_version.h @ONLY) | configure_file(src/ow_version.h.in ${PROJECT_SOURCE_DIR}/src/ow_version.h @ONLY) | ||||||
|  |  | ||||||
|  | add_definitions(-DPOCO_LOG_DEBUG="1") | ||||||
|  |  | ||||||
|  | add_compile_options(-Wall -Wextra) | ||||||
|  | if(ASAN) | ||||||
|  |     add_compile_options(-fsanitize=address) | ||||||
|  |     add_link_options(-fsanitize=address) | ||||||
|  | endif() | ||||||
|  |  | ||||||
| add_executable(owprov | add_executable(owprov | ||||||
|         build |         build | ||||||
|         src/ow_version.h.in |         src/ow_version.h.in | ||||||
| @@ -72,12 +74,13 @@ add_executable(owprov | |||||||
|         src/framework/MicroService.h |         src/framework/MicroService.h | ||||||
|         src/framework/OpenWifiTypes.h |         src/framework/OpenWifiTypes.h | ||||||
|         src/framework/orm.h |         src/framework/orm.h | ||||||
|         src/framework/RESTAPI_errors.h |  | ||||||
|         src/framework/RESTAPI_protocol.h |  | ||||||
|         src/framework/StorageClass.h |         src/framework/StorageClass.h | ||||||
|         src/framework/uCentral_Protocol.h |  | ||||||
|         src/framework/ConfigurationValidator.cpp |         src/framework/ConfigurationValidator.cpp | ||||||
|         src/framework/ConfigurationValidator.h |         src/framework/ConfigurationValidator.h | ||||||
|  |         src/framework/ow_constants.h | ||||||
|  |         src/framework/MicroServiceErrorHandler.h | ||||||
|  |         src/framework/WebSocketClientNotifications.h | ||||||
|  |         src/framework/MicroServiceErrorHandler.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 | ||||||
| @@ -104,7 +107,6 @@ add_executable(owprov | |||||||
|         src/RESTAPI/RESTAPI_inventory_list_handler.cpp src/RESTAPI/RESTAPI_inventory_list_handler.h |         src/RESTAPI/RESTAPI_inventory_list_handler.cpp src/RESTAPI/RESTAPI_inventory_list_handler.h | ||||||
|         src/RESTAPI/RESTAPI_entity_list_handler.cpp src/RESTAPI/RESTAPI_entity_list_handler.h |         src/RESTAPI/RESTAPI_entity_list_handler.cpp src/RESTAPI/RESTAPI_entity_list_handler.h | ||||||
|         src/RESTAPI/RESTAPI_configurations_handler.cpp src/RESTAPI/RESTAPI_configurations_handler.h |         src/RESTAPI/RESTAPI_configurations_handler.cpp src/RESTAPI/RESTAPI_configurations_handler.h | ||||||
|         src/RESTAPI/RESTAPI_webSocketServer.h src/RESTAPI/RESTAPI_webSocketServer.cpp |  | ||||||
|         src/RESTAPI/RESTAPI_contact_list_handler.cpp src/RESTAPI/RESTAPI_contact_list_handler.h |         src/RESTAPI/RESTAPI_contact_list_handler.cpp src/RESTAPI/RESTAPI_contact_list_handler.h | ||||||
|         src/RESTAPI/RESTAPI_location_list_handler.cpp src/RESTAPI/RESTAPI_location_list_handler.h |         src/RESTAPI/RESTAPI_location_list_handler.cpp src/RESTAPI/RESTAPI_location_list_handler.h | ||||||
|         src/RESTAPI/RESTAPI_venue_list_handler.cpp src/RESTAPI/RESTAPI_venue_list_handler.h |         src/RESTAPI/RESTAPI_venue_list_handler.cpp src/RESTAPI/RESTAPI_venue_list_handler.h | ||||||
| @@ -113,6 +115,8 @@ add_executable(owprov | |||||||
|         src/RESTAPI/RESTAPI_managementRole_list_handler.cpp src/RESTAPI/RESTAPI_managementRole_list_handler.h |         src/RESTAPI/RESTAPI_managementRole_list_handler.cpp src/RESTAPI/RESTAPI_managementRole_list_handler.h | ||||||
|         src/RESTAPI/RESTAPI_configurations_list_handler.cpp src/RESTAPI/RESTAPI_configurations_list_handler.h |         src/RESTAPI/RESTAPI_configurations_list_handler.cpp src/RESTAPI/RESTAPI_configurations_list_handler.h | ||||||
|         src/RESTAPI/RESTAPI_iptocountry_handler.cpp src/RESTAPI/RESTAPI_iptocountry_handler.h |         src/RESTAPI/RESTAPI_iptocountry_handler.cpp src/RESTAPI/RESTAPI_iptocountry_handler.h | ||||||
|  |         src/RESTAPI/RESTAPI_signup_handler.h src/RESTAPI/RESTAPI_signup_handler.cpp | ||||||
|  |         src/RESTAPI/RESTAPI_asset_server.cpp src/RESTAPI/RESTAPI_asset_server.h | ||||||
|         src/FindCountry.h |         src/FindCountry.h | ||||||
|         src/sdks/SDK_gw.cpp src/sdks/SDK_gw.h |         src/sdks/SDK_gw.cpp src/sdks/SDK_gw.h | ||||||
|         src/sdks/SDK_prov.cpp src/sdks/SDK_prov.h |         src/sdks/SDK_prov.cpp src/sdks/SDK_prov.h | ||||||
| @@ -125,15 +129,29 @@ add_executable(owprov | |||||||
|         src/RESTAPI/RESTAPI_db_helpers.h |         src/RESTAPI/RESTAPI_db_helpers.h | ||||||
|         src/JobController.cpp src/JobController.h |         src/JobController.cpp src/JobController.h | ||||||
|         src/JobRegistrations.cpp |         src/JobRegistrations.cpp | ||||||
|         src/storage/storage_jobs.cpp src/storage/storage_jobs.h |  | ||||||
|         src/WebSocketClientServer.cpp src/WebSocketClientServer.h |  | ||||||
|         src/storage/storage_maps.cpp src/storage/storage_maps.h |         src/storage/storage_maps.cpp src/storage/storage_maps.h | ||||||
|         src/RESTAPI/RESTAPI_map_handler.cpp src/RESTAPI/RESTAPI_map_handler.h |         src/RESTAPI/RESTAPI_map_handler.cpp src/RESTAPI/RESTAPI_map_handler.h | ||||||
|         src/RESTAPI/RESTAPI_map_list_handler.cpp src/RESTAPI/RESTAPI_map_list_handler.h) |         src/RESTAPI/RESTAPI_map_list_handler.cpp src/RESTAPI/RESTAPI_map_list_handler.h | ||||||
|  |         src/storage/storage_signup.cpp src/storage/storage_signup.h | ||||||
|  |         src/Signup.cpp src/Signup.h | ||||||
|  |         src/DeviceTypeCache.h | ||||||
|  |         src/storage/storage_variables.cpp src/storage/storage_variables.h | ||||||
|  |         src/RESTAPI/RESTAPI_variables_handler.cpp src/RESTAPI/RESTAPI_variables_handler.h | ||||||
|  |         src/RESTAPI/RESTAPI_variables_list_handler.cpp src/RESTAPI/RESTAPI_variables_list_handler.h | ||||||
|  |         src/FileDownloader.cpp src/FileDownloader.h | ||||||
|  |         src/Tasks/VenueConfigUpdater.h | ||||||
|  |         src/libs/croncpp.h | ||||||
|  |         src/Kafka_ProvUpdater.cpp src/Kafka_ProvUpdater.h | ||||||
|  |         src/storage/storage_operataor.cpp src/storage/storage_operataor.h | ||||||
|  |         src/storage/storage_sub_devices.cpp src/storage/storage_sub_devices.h | ||||||
|  |         src/storage/storage_service_class.cpp src/storage/storage_service_class.h | ||||||
|  |         src/RESTAPI/RESTAPI_sub_devices_list_handler.cpp src/RESTAPI/RESTAPI_sub_devices_list_handler.h src/RESTAPI/RESTAPI_sub_devices_handler.cpp src/RESTAPI/RESTAPI_sub_devices_handler.h src/RESTAPI/RESTAPI_service_class_list_handler.cpp src/RESTAPI/RESTAPI_service_class_list_handler.h src/RESTAPI/RESTAPI_service_class_handler.cpp src/RESTAPI/RESTAPI_service_class_handler.h src/RESTAPI/RESTAPI_operators_list_handler.cpp src/RESTAPI/RESTAPI_operators_list_handler.h src/RESTAPI/RESTAPI_operators_handler.cpp src/RESTAPI/RESTAPI_operators_handler.h src/storage/storage_op_contacts.cpp src/storage/storage_op_contacts.h src/storage/storage_op_locations.cpp src/storage/storage_op_locations.h src/RESTAPI/RESTAPI_op_contact_list_handler.cpp src/RESTAPI/RESTAPI_op_contact_list_handler.h src/RESTAPI/RESTAPI_op_contact_handler.cpp src/RESTAPI/RESTAPI_op_contact_handler.h src/RESTAPI/RESTAPI_op_location_list_handler.cpp src/RESTAPI/RESTAPI_op_location_list_handler.h src/RESTAPI/RESTAPI_op_location_handler.cpp src/RESTAPI/RESTAPI_op_location_handler.h src/ProvWebSocketClient.cpp src/ProvWebSocketClient.h src/Tasks/VenueRebooter.h src/Tasks/VenueUpgrade.h src/sdks/SDK_fms.cpp src/sdks/SDK_fms.h) | ||||||
|  |  | ||||||
| target_link_libraries(owprov PUBLIC | target_link_libraries(owprov PUBLIC | ||||||
|         ${Poco_LIBRARIES} ${MySQL_LIBRARIES} |         ${Poco_LIBRARIES} | ||||||
|         ${Boost_LIBRARIES} |         ${MySQL_LIBRARIES} | ||||||
|         ${ZLIB_LIBRARIES} ${AWSSDK_LINK_LIBRARIES} |         ${ZLIB_LIBRARIES} | ||||||
|         CppKafka::cppkafka nlohmann_json_schema_validator) |         CppKafka::cppkafka | ||||||
|  |         fmt::fmt | ||||||
|  |         nlohmann_json_schema_validator) | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										85
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										85
									
								
								Dockerfile
									
									
									
									
									
								
							| @@ -1,16 +1,23 @@ | |||||||
| FROM alpine:3.15 AS build-base | ARG DEBIAN_VERSION=11.4-slim | ||||||
|  | ARG POCO_VERSION=poco-tip-v1 | ||||||
|  | ARG FMTLIB_VERSION=9.0.0 | ||||||
|  | ARG CPPKAFKA_VERSION=tip-v1 | ||||||
|  | ARG JSON_VALIDATOR_VERSION=2.1.0 | ||||||
|  |  | ||||||
| RUN apk add --update --no-cache \ | FROM debian:$DEBIAN_VERSION AS build-base | ||||||
|  |  | ||||||
|  | RUN apt-get update && apt-get install --no-install-recommends -y \ | ||||||
|     make cmake g++ git \ |     make cmake g++ git \ | ||||||
|     unixodbc-dev postgresql-dev mariadb-dev \ |     libpq-dev libmariadb-dev libmariadbclient-dev-compat \ | ||||||
|     librdkafka-dev boost-dev openssl-dev \ |     librdkafka-dev libboost-all-dev libssl-dev \ | ||||||
|     zlib-dev nlohmann-json \ |     zlib1g-dev nlohmann-json3-dev ca-certificates libcurl4-openssl-dev | ||||||
|     curl-dev |  | ||||||
|  |  | ||||||
| FROM build-base AS poco-build | FROM build-base AS poco-build | ||||||
|  |  | ||||||
| ADD https://api.github.com/repos/stephb9959/poco/git/refs/heads/master version.json | ARG POCO_VERSION | ||||||
| RUN git clone https://github.com/stephb9959/poco /poco |  | ||||||
|  | ADD https://api.github.com/repos/AriliaWireless/poco/git/refs/tags/${POCO_VERSION} version.json | ||||||
|  | RUN git clone https://github.com/AriliaWireless/poco --branch ${POCO_VERSION} /poco | ||||||
|  |  | ||||||
| WORKDIR /poco | WORKDIR /poco | ||||||
| RUN mkdir cmake-build | RUN mkdir cmake-build | ||||||
| @@ -19,10 +26,26 @@ RUN cmake .. | |||||||
| RUN cmake --build . --config Release -j8 | RUN cmake --build . --config Release -j8 | ||||||
| RUN cmake --build . --target install | RUN cmake --build . --target install | ||||||
|  |  | ||||||
|  | FROM build-base AS fmtlib-build | ||||||
|  |  | ||||||
|  | ARG FMTLIB_VERSION | ||||||
|  |  | ||||||
|  | ADD https://api.github.com/repos/fmtlib/fmt/git/refs/tags/${FMTLIB_VERSION} version.json | ||||||
|  | RUN git clone https://github.com/fmtlib/fmt --branch ${FMTLIB_VERSION} /fmtlib | ||||||
|  |  | ||||||
|  | WORKDIR /fmtlib | ||||||
|  | RUN mkdir cmake-build | ||||||
|  | WORKDIR cmake-build | ||||||
|  | RUN cmake .. | ||||||
|  | RUN make | ||||||
|  | RUN make install | ||||||
|  |  | ||||||
| FROM build-base AS cppkafka-build | FROM build-base AS cppkafka-build | ||||||
|  |  | ||||||
| ADD https://api.github.com/repos/stephb9959/cppkafka/git/refs/heads/master version.json | ARG CPPKAFKA_VERSION | ||||||
| RUN git clone https://github.com/stephb9959/cppkafka /cppkafka |  | ||||||
|  | ADD https://api.github.com/repos/AriliaWireless/cppkafka/git/refs/tags/${CPPKAFKA_VERSION} version.json | ||||||
|  | RUN git clone https://github.com/AriliaWireless/cppkafka --branch ${CPPKAFKA_VERSION} /cppkafka | ||||||
|  |  | ||||||
| WORKDIR /cppkafka | WORKDIR /cppkafka | ||||||
| RUN mkdir cmake-build | RUN mkdir cmake-build | ||||||
| @@ -33,8 +56,10 @@ RUN cmake --build . --target install | |||||||
|  |  | ||||||
| FROM build-base AS json-schema-validator-build | FROM build-base AS json-schema-validator-build | ||||||
|  |  | ||||||
| ADD https://api.github.com/repos/pboettch/json-schema-validator/git/refs/heads/master version.json | ARG JSON_VALIDATOR_VERSION | ||||||
| RUN git clone https://github.com/pboettch/json-schema-validator /json-schema-validator |  | ||||||
|  | ADD https://api.github.com/repos/pboettch/json-schema-validator/git/refs/tags/${JSON_VALIDATOR_VERSION} version.json | ||||||
|  | RUN git clone https://github.com/pboettch/json-schema-validator --branch ${JSON_VALIDATOR_VERSION} /json-schema-validator | ||||||
|  |  | ||||||
| WORKDIR /json-schema-validator | WORKDIR /json-schema-validator | ||||||
| RUN mkdir cmake-build | RUN mkdir cmake-build | ||||||
| @@ -43,21 +68,6 @@ RUN cmake .. | |||||||
| RUN make | RUN make | ||||||
| RUN make install | RUN make install | ||||||
|  |  | ||||||
| FROM build-base AS aws-sdk-cpp-build |  | ||||||
|  |  | ||||||
| ADD https://api.github.com/repos/aws/aws-sdk-cpp/git/refs/heads/main version.json |  | ||||||
| RUN git clone --recurse-submodules https://github.com/aws/aws-sdk-cpp /aws-sdk-cpp |  | ||||||
|  |  | ||||||
| WORKDIR /aws-sdk-cpp |  | ||||||
| RUN mkdir cmake-build |  | ||||||
| WORKDIR cmake-build |  | ||||||
| RUN cmake .. -DBUILD_ONLY="sns;s3" \ |  | ||||||
|              -DCMAKE_BUILD_TYPE=Release \ |  | ||||||
|              -DCMAKE_CXX_FLAGS="-Wno-error=stringop-overflow -Wno-error=uninitialized" \ |  | ||||||
|              -DAUTORUN_UNIT_TESTS=OFF |  | ||||||
| RUN cmake --build . --config Release -j8 |  | ||||||
| RUN cmake --build . --target install |  | ||||||
|  |  | ||||||
| FROM build-base AS owprov-build | FROM build-base AS owprov-build | ||||||
|  |  | ||||||
| ADD CMakeLists.txt build /owprov/ | ADD CMakeLists.txt build /owprov/ | ||||||
| @@ -71,8 +81,8 @@ COPY --from=cppkafka-build /usr/local/include /usr/local/include | |||||||
| COPY --from=cppkafka-build /usr/local/lib /usr/local/lib | 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/include /usr/local/include | ||||||
| COPY --from=json-schema-validator-build /usr/local/lib /usr/local/lib | 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=fmtlib-build /usr/local/include /usr/local/include | ||||||
| COPY --from=aws-sdk-cpp-build /usr/local/lib /usr/local/lib | COPY --from=fmtlib-build /usr/local/lib /usr/local/lib | ||||||
|  |  | ||||||
| WORKDIR /owprov | WORKDIR /owprov | ||||||
| RUN mkdir cmake-build | RUN mkdir cmake-build | ||||||
| @@ -80,21 +90,21 @@ WORKDIR /owprov/cmake-build | |||||||
| RUN cmake .. | RUN cmake .. | ||||||
| RUN cmake --build . --config Release -j8 | RUN cmake --build . --config Release -j8 | ||||||
|  |  | ||||||
| FROM alpine:3.15 | FROM debian:$DEBIAN_VERSION | ||||||
|  |  | ||||||
| ENV OWPROV_USER=owprov \ | ENV OWPROV_USER=owprov \ | ||||||
|     OWPROV_ROOT=/owprov-data \ |     OWPROV_ROOT=/owprov-data \ | ||||||
|     OWPROV_CONFIG=/owprov-data |     OWPROV_CONFIG=/owprov-data | ||||||
|  |  | ||||||
| RUN addgroup -S "$OWPROV_USER" && \ | RUN useradd "$OWPROV_USER" | ||||||
|     adduser -S -G "$OWPROV_USER" "$OWPROV_USER" |  | ||||||
|  |  | ||||||
| RUN mkdir /openwifi | RUN mkdir /openwifi | ||||||
| RUN mkdir -p "$OWPROV_ROOT" "$OWPROV_CONFIG" && \ | RUN mkdir -p "$OWPROV_ROOT" "$OWPROV_CONFIG" && \ | ||||||
|     chown "$OWPROV_USER": "$OWPROV_ROOT" "$OWPROV_CONFIG" |     chown "$OWPROV_USER": "$OWPROV_ROOT" "$OWPROV_CONFIG" | ||||||
|  |  | ||||||
| RUN apk add --update --no-cache librdkafka su-exec gettext ca-certificates bash jq curl \ | RUN apt-get update && apt-get install --no-install-recommends -y \ | ||||||
|     mariadb-connector-c libpq unixodbc postgresql-client |     librdkafka++1 gosu gettext ca-certificates bash jq curl wget \ | ||||||
|  |     libmariadb-dev-compat libpq5 unixodbc postgresql-client | ||||||
|  |  | ||||||
| COPY readiness_check /readiness_check | COPY readiness_check /readiness_check | ||||||
| COPY test_scripts/curl/cli /cli | COPY test_scripts/curl/cli /cli | ||||||
| @@ -103,14 +113,13 @@ COPY owprov.properties.tmpl / | |||||||
| COPY docker-entrypoint.sh / | COPY docker-entrypoint.sh / | ||||||
| COPY wait-for-postgres.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.crt | ||||||
|  |  | ||||||
| COPY --from=owprov-build /owprov/cmake-build/owprov /openwifi/owprov | COPY --from=owprov-build /owprov/cmake-build/owprov /openwifi/owprov | ||||||
| COPY --from=cppkafka-build /cppkafka/cmake-build/src/lib/* /usr/local/lib | 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=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 | RUN ldconfig | ||||||
| COPY --from=aws-sdk-cpp-build /aws-sdk-cpp/cmake-build/aws-cpp-sdk-sns/libaws-cpp-sdk-sns.so /usr/local/lib |  | ||||||
|  |  | ||||||
| EXPOSE 16005 17005 16105 | EXPOSE 16005 17005 16105 | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										6
									
								
								SUBSCRIBERS.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								SUBSCRIBERS.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | |||||||
|  | # Subscribers Architecture | ||||||
|  |  | ||||||
|  | ## Overview | ||||||
|  | The goal is to provide multiple WISPs with access to a set of subscribers. All subscribers will fall in the default WISP and can be moved to any other WISP later. You can use the source IP to detect which WISP to select. | ||||||
|  | Entities can be generic entities when created OR WISP entities.  | ||||||
|  |  | ||||||
| @@ -1,11 +1,11 @@ | |||||||
| #!/bin/sh | #!/bin/bash | ||||||
| set -e | set -e | ||||||
|  |  | ||||||
| if [ "$SELFSIGNED_CERTS" = 'true' ]; then | if [ "$SELFSIGNED_CERTS" = 'true' ]; then | ||||||
|     update-ca-certificates |     update-ca-certificates | ||||||
| fi | fi | ||||||
|  |  | ||||||
| if [[ "$TEMPLATE_CONFIG" = 'true' && ! -f "$OWPROV_CONFIG"/owprov.properties ]]; then | if [[ "$TEMPLATE_CONFIG" = 'true' ]]; then | ||||||
|   RESTAPI_HOST_ROOTCA=${RESTAPI_HOST_ROOTCA:-"\$OWPROV_ROOT/certs/restapi-ca.pem"} \ |   RESTAPI_HOST_ROOTCA=${RESTAPI_HOST_ROOTCA:-"\$OWPROV_ROOT/certs/restapi-ca.pem"} \ | ||||||
|   RESTAPI_HOST_PORT=${RESTAPI_HOST_PORT:-"16005"} \ |   RESTAPI_HOST_PORT=${RESTAPI_HOST_PORT:-"16005"} \ | ||||||
|   RESTAPI_HOST_CERT=${RESTAPI_HOST_CERT:-"\$OWPROV_ROOT/certs/restapi-cert.pem"} \ |   RESTAPI_HOST_CERT=${RESTAPI_HOST_CERT:-"\$OWPROV_ROOT/certs/restapi-cert.pem"} \ | ||||||
| @@ -24,8 +24,13 @@ if [[ "$TEMPLATE_CONFIG" = 'true' && ! -f "$OWPROV_CONFIG"/owprov.properties ]]; | |||||||
|   SYSTEM_URI_PRIVATE=${SYSTEM_URI_PRIVATE:-"https://localhost:17005"} \ |   SYSTEM_URI_PRIVATE=${SYSTEM_URI_PRIVATE:-"https://localhost:17005"} \ | ||||||
|   SYSTEM_URI_PUBLIC=${SYSTEM_URI_PUBLIC:-"https://localhost:16005"} \ |   SYSTEM_URI_PUBLIC=${SYSTEM_URI_PUBLIC:-"https://localhost:16005"} \ | ||||||
|   SYSTEM_URI_UI=${SYSTEM_URI_UI:-"http://localhost"} \ |   SYSTEM_URI_UI=${SYSTEM_URI_UI:-"http://localhost"} \ | ||||||
|  |   SECURITY_RESTAPI_DISABLE=${SECURITY_RESTAPI_DISABLE:-"false"} \ | ||||||
|   KAFKA_ENABLE=${KAFKA_ENABLE:-"true"} \ |   KAFKA_ENABLE=${KAFKA_ENABLE:-"true"} \ | ||||||
|   KAFKA_BROKERLIST=${KAFKA_BROKERLIST:-"localhost:9092"} \ |   KAFKA_BROKERLIST=${KAFKA_BROKERLIST:-"localhost:9092"} \ | ||||||
|  |   KAFKA_SSL_CA_LOCATION=${KAFKA_SSL_CA_LOCATION:-""} \ | ||||||
|  |   KAFKA_SSL_CERTIFICATE_LOCATION=${KAFKA_SSL_CERTIFICATE_LOCATION:-""} \ | ||||||
|  |   KAFKA_SSL_KEY_LOCATION=${KAFKA_SSL_KEY_LOCATION:-""} \ | ||||||
|  |   KAFKA_SSL_KEY_PASSWORD=${KAFKA_SSL_KEY_PASSWORD:-""} \ | ||||||
|   STORAGE_TYPE=${STORAGE_TYPE:-"sqlite"} \ |   STORAGE_TYPE=${STORAGE_TYPE:-"sqlite"} \ | ||||||
|   STORAGE_TYPE_POSTGRESQL_HOST=${STORAGE_TYPE_POSTGRESQL_HOST:-"localhost"} \ |   STORAGE_TYPE_POSTGRESQL_HOST=${STORAGE_TYPE_POSTGRESQL_HOST:-"localhost"} \ | ||||||
|   STORAGE_TYPE_POSTGRESQL_USERNAME=${STORAGE_TYPE_POSTGRESQL_USERNAME:-"owprov"} \ |   STORAGE_TYPE_POSTGRESQL_USERNAME=${STORAGE_TYPE_POSTGRESQL_USERNAME:-"owprov"} \ | ||||||
| @@ -44,7 +49,7 @@ if [ "$1" = '/openwifi/owprov' -a "$(id -u)" = '0' ]; then | |||||||
|     if [ "$RUN_CHOWN" = 'true' ]; then |     if [ "$RUN_CHOWN" = 'true' ]; then | ||||||
|       chown -R "$OWPROV_USER": "$OWPROV_ROOT" "$OWPROV_CONFIG" |       chown -R "$OWPROV_USER": "$OWPROV_ROOT" "$OWPROV_CONFIG" | ||||||
|     fi |     fi | ||||||
|     exec su-exec "$OWPROV_USER" "$@" |     exec gosu "$OWPROV_USER" "$@" | ||||||
| fi | fi | ||||||
|  |  | ||||||
| exec "$@" | exec "$@" | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								helm/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								helm/.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1 +1,3 @@ | |||||||
| *.swp | *.swp | ||||||
|  | Chart.lock | ||||||
|  | charts/ | ||||||
|   | |||||||
| @@ -5,14 +5,14 @@ name: owprov | |||||||
| 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 | ||||||
|   | |||||||
| @@ -70,8 +70,8 @@ The following table lists the configurable parameters of the chart and their def | |||||||
| | persistence.size | string | Defines PV size | `'10Gi'` | | | persistence.size | string | Defines PV size | `'10Gi'` | | ||||||
| | public_env_variables | hash | Defines list of environment variables to be passed to the Provisioning | | | | public_env_variables | hash | Defines list of environment variables to be passed to the Provisioning | | | ||||||
| | configProperties | hash | Configuration properties that should be passed to the application in `owprov.properties`. May be passed by key in set (i.e. `configProperties."rtty\.token"`) | | | | configProperties | hash | Configuration properties that should be passed to the application in `owprov.properties`. May be passed by key in set (i.e. `configProperties."rtty\.token"`) | | | ||||||
| | certs | hash | Defines files (keys and certificates) that should be passed to the Provisioning (PEM format is adviced to be used) (see `volumes.owprov` on where it is mounted) |  | | | existingCertsSecret | string | Existing Kubernetes secret containing all required certificates and private keys for microservice operation. If set, certificates from `certs` key are ignored | `""` | | ||||||
|  | | certs | hash | Defines files (keys and certificates) that should be passed to the Gateway (PEM format is adviced to be used) (see `volumes.owprov` on where it is mounted). If `existingCertsSecret` is set, certificates passed this way will not be used. |  | | ||||||
|  |  | ||||||
| Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, | Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, | ||||||
|  |  | ||||||
|   | |||||||
| @@ -30,3 +30,13 @@ Create chart name and version as used by the chart label. | |||||||
| {{- define "owprov.chart" -}} | {{- define "owprov.chart" -}} | ||||||
| {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} | ||||||
| {{- end -}} | {{- end -}} | ||||||
|  |  | ||||||
|  | {{- define "owprov.ingress.apiVersion" -}} | ||||||
|  |   {{- if .Capabilities.APIVersions.Has "networking.k8s.io/v1" -}} | ||||||
|  |       {{- print "networking.k8s.io/v1" -}} | ||||||
|  |   {{- else if .Capabilities.APIVersions.Has "networking.k8s.io/v1beta1" -}} | ||||||
|  |     {{- print "networking.k8s.io/v1beta1" -}} | ||||||
|  |   {{- else -}} | ||||||
|  |     {{- print "extensions/v1beta1" -}} | ||||||
|  |   {{- end -}} | ||||||
|  | {{- end -}} | ||||||
|   | |||||||
| @@ -1,4 +1,5 @@ | |||||||
| {{- $root := . -}} | {{- $root := . -}} | ||||||
|  | {{- $storageType := index .Values.configProperties "storage.type" -}} | ||||||
| --- | --- | ||||||
| apiVersion: apps/v1 | apiVersion: apps/v1 | ||||||
| kind: Deployment | kind: Deployment | ||||||
| @@ -46,6 +47,39 @@ spec: | |||||||
|             - -timeout |             - -timeout | ||||||
|             - 600s |             - 600s | ||||||
|  |  | ||||||
|  | {{- if eq $storageType "postgresql" }} | ||||||
|  |         - name: wait-postgres | ||||||
|  |           image: "{{ .Values.images.owprov.repository }}:{{ .Values.images.owprov.tag }}" | ||||||
|  |           imagePullPolicy: {{ .Values.images.owprov.pullPolicy }} | ||||||
|  |           command: | ||||||
|  |             - /wait-for-postgres.sh | ||||||
|  |             - {{ index .Values.configProperties "storage.type.postgresql.host" }} | ||||||
|  |             - echo | ||||||
|  |             - "PostgreSQL is ready" | ||||||
|  |           env: | ||||||
|  |             - name: KUBERNETES_DEPLOYED | ||||||
|  |               value: "{{ now }}" | ||||||
|  |           {{- range $key, $value := .Values.public_env_variables }} | ||||||
|  |             - name: {{ $key }} | ||||||
|  |               value: {{ $value | quote }} | ||||||
|  |           {{- end }} | ||||||
|  |           {{- range $key, $value := .Values.secret_env_variables }} | ||||||
|  |             - name: {{ $key }} | ||||||
|  |               valueFrom: | ||||||
|  |                 secretKeyRef: | ||||||
|  |                   name: {{ include "owprov.fullname" $root }}-env | ||||||
|  |                   key: {{ $key }} | ||||||
|  |           {{- end }} | ||||||
|  |           volumeMounts: | ||||||
|  |           {{- range .Values.volumes.owprov }} | ||||||
|  |           - name: {{ .name }} | ||||||
|  |             mountPath: {{ .mountPath }} | ||||||
|  |             {{- if .subPath }} | ||||||
|  |             subPath: {{ .subPath }} | ||||||
|  |             {{- end }} | ||||||
|  |           {{- end }} | ||||||
|  | {{- end }} | ||||||
|  |  | ||||||
|       containers: |       containers: | ||||||
|  |  | ||||||
|         - name: owprov |         - name: owprov | ||||||
| @@ -97,8 +131,10 @@ spec: | |||||||
|             {{- toYaml . | nindent 12 }} |             {{- toYaml . | nindent 12 }} | ||||||
|           {{- end }} |           {{- end }} | ||||||
|  |  | ||||||
|  |       {{- with .Values.securityContext }} | ||||||
|       securityContext: |       securityContext: | ||||||
|         fsGroup: 101 |         {{- toYaml . | nindent 8 }} | ||||||
|  |       {{- end }} | ||||||
|  |  | ||||||
|       imagePullSecrets: |       imagePullSecrets: | ||||||
|       {{- range $image, $imageValue := .Values.images }} |       {{- range $image, $imageValue := .Values.images }} | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ | |||||||
| {{- range $ingress, $ingressValue := .Values.ingresses }} | {{- range $ingress, $ingressValue := .Values.ingresses }} | ||||||
| {{- if $ingressValue.enabled }} | {{- if $ingressValue.enabled }} | ||||||
| --- | --- | ||||||
| apiVersion: extensions/v1beta1 | apiVersion: {{ include "owprov.ingress.apiVersion" $root }} | ||||||
| kind: Ingress | kind: Ingress | ||||||
| metadata: | metadata: | ||||||
|   name: {{ include "owprov.fullname" $root }}-{{ $ingress }} |   name: {{ include "owprov.fullname" $root }}-{{ $ingress }} | ||||||
| @@ -36,11 +36,25 @@ spec: | |||||||
|       paths: |       paths: | ||||||
|       {{- range $ingressValue.paths }} |       {{- range $ingressValue.paths }} | ||||||
|         - path: {{ .path }} |         - path: {{ .path }} | ||||||
|  |           {{- if $root.Capabilities.APIVersions.Has "networking.k8s.io/v1" }} | ||||||
|  |           pathType: {{ .pathType | default "ImplementationSpecific" }} | ||||||
|  |           {{- end }} | ||||||
|           backend: |           backend: | ||||||
|  |             {{- if $root.Capabilities.APIVersions.Has "networking.k8s.io/v1" }} | ||||||
|  |             service: | ||||||
|  |               name: {{ include "owprov.fullname" $root }}-{{ .serviceName }} | ||||||
|  |               port: | ||||||
|  |               {{- if kindIs "string" .servicePort }} | ||||||
|  |                 name: {{ .servicePort }} | ||||||
|  |               {{- else }} | ||||||
|  |                 number: {{ .servicePort }} | ||||||
|  |               {{- end }} | ||||||
|  |             {{- else }} | ||||||
|             serviceName: {{ include "owprov.fullname" $root }}-{{ .serviceName }} |             serviceName: {{ include "owprov.fullname" $root }}-{{ .serviceName }} | ||||||
|             servicePort: {{ .servicePort }} |             servicePort: {{ .servicePort }} | ||||||
|             {{- end }} |             {{- end }} | ||||||
|       {{- end }} |       {{- end }} | ||||||
|  |   {{- end }} | ||||||
|  |  | ||||||
| {{- end }} | {{- end }} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ fullnameOverride: "" | |||||||
| images: | images: | ||||||
|   owprov: |   owprov: | ||||||
|     repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owprov |     repository: tip-tip-wlan-cloud-ucentral.jfrog.io/owprov | ||||||
|     tag: main |     tag: v2.7.0 | ||||||
|     pullPolicy: Always |     pullPolicy: Always | ||||||
| #    regcred: | #    regcred: | ||||||
| #      registry: tip-tip-wlan-cloud-ucentral.jfrog.io | #      registry: tip-tip-wlan-cloud-ucentral.jfrog.io | ||||||
| @@ -54,6 +54,7 @@ ingresses: | |||||||
|     - restapi.chart-example.local |     - restapi.chart-example.local | ||||||
|     paths: |     paths: | ||||||
|     - path: / |     - path: / | ||||||
|  |       pathType: ImplementationSpecific | ||||||
|       serviceName: owprov |       serviceName: owprov | ||||||
|       servicePort: restapi |       servicePort: restapi | ||||||
|  |  | ||||||
| @@ -70,7 +71,7 @@ volumes: | |||||||
|       mountPath: /owprov-data/certs |       mountPath: /owprov-data/certs | ||||||
|       volumeDefinition: | |       volumeDefinition: | | ||||||
|         secret: |         secret: | ||||||
|           secretName: {{ include "owprov.fullname" . }}-certs |           secretName: {{ if .Values.existingCertsSecret }}{{ .Values.existingCertsSecret }}{{ else }}{{ include "owprov.fullname" . }}-certs{{ end }} | ||||||
|     # Change this if you want to use another volume type |     # Change this if you want to use another volume type | ||||||
|     - name: persist |     - name: persist | ||||||
|       mountPath: /owprov-data/persist |       mountPath: /owprov-data/persist | ||||||
| @@ -90,6 +91,9 @@ resources: {} | |||||||
|   #  cpu: 100m |   #  cpu: 100m | ||||||
|   #  memory: 128Mi |   #  memory: 128Mi | ||||||
|  |  | ||||||
|  | securityContext: | ||||||
|  |   fsGroup: 1000 | ||||||
|  |  | ||||||
| nodeSelector: {} | nodeSelector: {} | ||||||
|  |  | ||||||
| tolerations: [] | tolerations: [] | ||||||
| @@ -148,6 +152,10 @@ configProperties: | |||||||
|   openwifi.kafka.brokerlist: localhost:9092 |   openwifi.kafka.brokerlist: localhost:9092 | ||||||
|   openwifi.kafka.auto.commit: false |   openwifi.kafka.auto.commit: false | ||||||
|   openwifi.kafka.queue.buffering.max.ms: 50 |   openwifi.kafka.queue.buffering.max.ms: 50 | ||||||
|  |   openwifi.kafka.ssl.ca.location: "" | ||||||
|  |   openwifi.kafka.ssl.certificate.location: "" | ||||||
|  |   openwifi.kafka.ssl.key.location: "" | ||||||
|  |   openwifi.kafka.ssl.key.password: "" | ||||||
|   # Storage |   # Storage | ||||||
|   storage.type: sqlite # (sqlite|postgresql|mysql|odbc) |   storage.type: sqlite # (sqlite|postgresql|mysql|odbc) | ||||||
|   ## SQLite |   ## SQLite | ||||||
| @@ -176,6 +184,7 @@ configProperties: | |||||||
|   openwifi.system.uri.public: https://localhost:16005 |   openwifi.system.uri.public: https://localhost:16005 | ||||||
|   openwifi.system.uri.ui: https://localhost |   openwifi.system.uri.ui: https://localhost | ||||||
|   openwifi.system.commandchannel: /tmp/app_owprov |   openwifi.system.commandchannel: /tmp/app_owprov | ||||||
|  |   iptocountry.provider: ipinfo | ||||||
|   # Logging |   # Logging | ||||||
|   logging.type: console |   logging.type: console | ||||||
|   logging.path: $OWPROV_ROOT/logs |   logging.path: $OWPROV_ROOT/logs | ||||||
| @@ -193,6 +202,9 @@ configProperties: | |||||||
|   storage.type.mysql.username: stephb |   storage.type.mysql.username: stephb | ||||||
|   storage.type.mysql.password: snoopy99 |   storage.type.mysql.password: snoopy99 | ||||||
|  |  | ||||||
|  | # NOTE: List of required certificates may be found in "certs" key. Alternative way to pass required certificates is to create external secret with all required certificates and set secret name in "existingCertsSecret" key. Details may be found in https://github.com/Telecominfraproject/wlan-cloud-ucentral-deploy/tree/main/chart#tldr | ||||||
|  | existingCertsSecret: "" | ||||||
|  |  | ||||||
| certs: | certs: | ||||||
|   # restapi-ca.pem: "" |   # restapi-ca.pem: "" | ||||||
|   # restapi-cert.pem: "" |   # restapi-cert.pem: "" | ||||||
|   | |||||||
							
								
								
									
										268
									
								
								openapi/ow_or_ameriband.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										268
									
								
								openapi/ow_or_ameriband.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,268 @@ | |||||||
|  | openapi: 3.0.1 | ||||||
|  | info: | ||||||
|  |   title: OpenWiFi Open roaming Ameriband Provisioning Model | ||||||
|  |   description: Registration of an OpenRoaming profile with Ameriband for TIP OpenWifi. | ||||||
|  |   version: 1.0.0 | ||||||
|  |   license: | ||||||
|  |     name: BSD3 | ||||||
|  |     url: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE | ||||||
|  |  | ||||||
|  | servers: | ||||||
|  |   - url: 'https://tip.regiatration.ameriband.com:8001/api/v1' | ||||||
|  |  | ||||||
|  | security: | ||||||
|  |   - bearerAuth: [] | ||||||
|  |  | ||||||
|  | components: | ||||||
|  |   securitySchemes: | ||||||
|  |     bearerAuth: | ||||||
|  |       type: http | ||||||
|  |       scheme: bearer | ||||||
|  |  | ||||||
|  |   responses: | ||||||
|  |     NotFound: | ||||||
|  |       description: The specified resource was not found. | ||||||
|  |       content: | ||||||
|  |         application/json: | ||||||
|  |           schema: | ||||||
|  |             properties: | ||||||
|  |               ErrorCode: | ||||||
|  |                 type: integer | ||||||
|  |               ErrorDetails: | ||||||
|  |                 type: string | ||||||
|  |               ErrorDescription: | ||||||
|  |                 type: string | ||||||
|  |  | ||||||
|  |     Unauthorized: | ||||||
|  |       description: The requested does not have sufficient rights to perform the operation. | ||||||
|  |       content: | ||||||
|  |         application/json: | ||||||
|  |           schema: | ||||||
|  |             properties: | ||||||
|  |               ErrorCode: | ||||||
|  |                 type: integer | ||||||
|  |                 enum: | ||||||
|  |                   - 0     # Success | ||||||
|  |                   - 8     # INVALID_TOKEN | ||||||
|  |                   - 9     # EXPIRED_TOKEN | ||||||
|  |               ErrorDetails: | ||||||
|  |                 type: string | ||||||
|  |               ErrorDescription: | ||||||
|  |                 type: string | ||||||
|  |  | ||||||
|  |     Success: | ||||||
|  |       description: The requested operation was performed. | ||||||
|  |       content: | ||||||
|  |         application/json: | ||||||
|  |           schema: | ||||||
|  |             properties: | ||||||
|  |               Operation: | ||||||
|  |                 type: string | ||||||
|  |               Details: | ||||||
|  |                 type: string | ||||||
|  |               Code: | ||||||
|  |                 type: integer | ||||||
|  |  | ||||||
|  |     BadRequest: | ||||||
|  |       description: The requested operation failed. | ||||||
|  |       content: | ||||||
|  |         application/json: | ||||||
|  |           schema: | ||||||
|  |             properties: | ||||||
|  |               ErrorCode: | ||||||
|  |                 type: integer | ||||||
|  |               ErrorDetails: | ||||||
|  |                 type: string | ||||||
|  |               ErrorDescription: | ||||||
|  |                 type: integer | ||||||
|  |  | ||||||
|  |   schemas: | ||||||
|  |     RegistrationRequest: | ||||||
|  |       type: object | ||||||
|  |       properties: | ||||||
|  |         orgRequestId: | ||||||
|  |           type: string | ||||||
|  |           format: uuid | ||||||
|  |           minLength: 36 | ||||||
|  |           maxLength: 36 | ||||||
|  |           example: | ||||||
|  |             Client will generate a UUID that must be returned in the response. | ||||||
|  |         orgAcceptedTermsAndConditions: | ||||||
|  |           type: boolean | ||||||
|  |           default: false | ||||||
|  |         orgLegalName: | ||||||
|  |           type: string | ||||||
|  |           minLength: 1 | ||||||
|  |         orgWebSite: | ||||||
|  |           type: string | ||||||
|  |           format: url | ||||||
|  |           minLength: 1 | ||||||
|  |         orgContact: | ||||||
|  |           type: string | ||||||
|  |           minLength: 1 | ||||||
|  |           example: | ||||||
|  |             John Smith | ||||||
|  |         orgEmail: | ||||||
|  |           type: string | ||||||
|  |           format: email | ||||||
|  |           minLength: 1 | ||||||
|  |         orgPhone: | ||||||
|  |           type: string | ||||||
|  |           example: | ||||||
|  |             (607)555-1234 or +1(223)555-1222 | ||||||
|  |         orgLocation: | ||||||
|  |           type: string | ||||||
|  |           example: | ||||||
|  |             Boston, NH - LA, CA | ||||||
|  |         orgCertificate: | ||||||
|  |           type: string | ||||||
|  |           minLength: 1 | ||||||
|  |           example: | ||||||
|  |             This must be the entire PEM file content of the certificate, encoded using base64 | ||||||
|  |  | ||||||
|  |     RegistrationResponse: | ||||||
|  |       type: object | ||||||
|  |       properties: | ||||||
|  |         orgRequestId: | ||||||
|  |           type: string | ||||||
|  |           format: uuid | ||||||
|  |           minLength: 36 | ||||||
|  |           maxLength: 36 | ||||||
|  |           example: | ||||||
|  |             This should be the same orgRequestId passed during registration. | ||||||
|  |         orgNASID: | ||||||
|  |           type: string | ||||||
|  |           minLength: 10 | ||||||
|  |           description: | ||||||
|  |             This is the NASID generated by Ameriband. It will be used by the operator as NASID when contacting Ameriband. | ||||||
|  |         ameribandCertificate: | ||||||
|  |           type: string | ||||||
|  |           minLength: 1 | ||||||
|  |           example: | ||||||
|  |             This must be the entire PEM file content of the certificate, encoded using base64 | ||||||
|  |  | ||||||
|  |     RegistrationInformationRequest: | ||||||
|  |       type: object | ||||||
|  |       properties: | ||||||
|  |         link: | ||||||
|  |           description: This should be the link where a potential registrant can read the terms and conditions of registering with Ameriband. | ||||||
|  |           type: string | ||||||
|  |           format: url | ||||||
|  |           minLength: 1 | ||||||
|  |           example: | ||||||
|  |             https://ameriband.com/romain-registration.html | ||||||
|  |  | ||||||
|  | paths: | ||||||
|  |   /termsAndConditions: | ||||||
|  |     get: | ||||||
|  |       summary: The registrant must be given a chance to view the terms and conditions of the relationship they are entering into | ||||||
|  |       operationId: getTermsAndConditions | ||||||
|  |       responses: | ||||||
|  |         200: | ||||||
|  |           description: Sucessfully retrieved Terms and Conditions | ||||||
|  |           content: | ||||||
|  |             application/json: | ||||||
|  |               schema: | ||||||
|  |                 $ref: '#/components/schemas/RegistrationInformationRequest' | ||||||
|  |         404: | ||||||
|  |           $ref: '#/components/responses/Unauthorized' | ||||||
|  |  | ||||||
|  |   /registration: | ||||||
|  |     get: | ||||||
|  |       tags: | ||||||
|  |         - Registration | ||||||
|  |       operationId: getRegistrationInformation | ||||||
|  |       summary: This should return the information from a registration based on the NASID | ||||||
|  |       parameters: | ||||||
|  |         - in: query | ||||||
|  |           name: orgNASID | ||||||
|  |           schema: | ||||||
|  |             type: string | ||||||
|  |           required: true | ||||||
|  |           example: | ||||||
|  |             This is the orgNASID returned during registration. | ||||||
|  |       responses: | ||||||
|  |         200: | ||||||
|  |           $ref: '#/components/schemas/RegistrationResponse' | ||||||
|  |         403: | ||||||
|  |           $ref: '#/components/responses/Unauthorized' | ||||||
|  |         404: | ||||||
|  |           $ref: '#/components/responses/NotFound' | ||||||
|  |  | ||||||
|  |     post: | ||||||
|  |       summary: Called when the registrant ahs read the T&Cs and iw willing to submit their information to enter in a partnership | ||||||
|  |       tags: | ||||||
|  |         - Registration | ||||||
|  |       operationId: createRegistration | ||||||
|  |       requestBody: | ||||||
|  |         required: true | ||||||
|  |         content: | ||||||
|  |           application/json: | ||||||
|  |             schema: | ||||||
|  |               $ref: '#/components/schemas/RegistrationRequest' | ||||||
|  |       responses: | ||||||
|  |         200: | ||||||
|  |           description: Succesfully registered | ||||||
|  |           content: | ||||||
|  |             application/json: | ||||||
|  |               schema: | ||||||
|  |                 $ref: '#/components/schemas/RegistrationResponse' | ||||||
|  |         400: | ||||||
|  |           description: Registration failed due to  missing or incomplete information | ||||||
|  |           $ref: '#/components/responses/BadRequest' | ||||||
|  |         403: | ||||||
|  |           $ref: '#/components/responses/Unauthorized' | ||||||
|  |  | ||||||
|  |     put: | ||||||
|  |       summary: Called when the registrant needs to update its information with Ameriband. The does not generate a new NASID. | ||||||
|  |       tags: | ||||||
|  |         - Registration | ||||||
|  |       operationId: updateRegistration | ||||||
|  |       parameters: | ||||||
|  |         - in: query | ||||||
|  |           name: orgNASID | ||||||
|  |           schema: | ||||||
|  |             type: string | ||||||
|  |           required: true | ||||||
|  |           example: | ||||||
|  |             This is the orgNASID returned during registration. | ||||||
|  |       requestBody: | ||||||
|  |         required: true | ||||||
|  |         content: | ||||||
|  |           application/json: | ||||||
|  |             schema: | ||||||
|  |               $ref: '#/components/schemas/RegistrationRequest' | ||||||
|  |       responses: | ||||||
|  |         200: | ||||||
|  |           description: Succesfully found the information based on the orgNASID | ||||||
|  |           content: | ||||||
|  |             application/json: | ||||||
|  |               schema: | ||||||
|  |                 $ref: '#/components/schemas/RegistrationResponse' | ||||||
|  |         400: | ||||||
|  |           $ref: '#/components/responses/BadRequest' | ||||||
|  |         403: | ||||||
|  |           $ref: '#/components/responses/Unauthorized' | ||||||
|  |         404: | ||||||
|  |           $ref: '#/components/responses/NotFound' | ||||||
|  |  | ||||||
|  |     delete: | ||||||
|  |       tags: | ||||||
|  |         - Registration | ||||||
|  |       summary: When a registrant wants to terminate a relationship with Ameriband. Ameriband should also delete all information from the registrant | ||||||
|  |       operationId: deleteRegistration | ||||||
|  |       parameters: | ||||||
|  |         - in: query | ||||||
|  |           name: orgNASID | ||||||
|  |           schema: | ||||||
|  |             type: string | ||||||
|  |           required: true | ||||||
|  |           example: | ||||||
|  |             This is the orgNASID returned during registration. | ||||||
|  |       responses: | ||||||
|  |         204: | ||||||
|  |           $ref: '#/components/responses/Success' | ||||||
|  |         403: | ||||||
|  |           $ref: '#/components/responses/Unauthorized' | ||||||
|  |         404: | ||||||
|  |           $ref: '#/components/responses/NotFound' | ||||||
							
								
								
									
										2002
									
								
								openapi/owprov.yaml
									
									
									
									
									
								
							
							
						
						
									
										2002
									
								
								openapi/owprov.yaml
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										174
									
								
								openapi/rrm_provider.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								openapi/rrm_provider.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,174 @@ | |||||||
|  | openapi: 3.0.1 | ||||||
|  | info: | ||||||
|  |   title: OpenWiFi RRM Provider Model | ||||||
|  |   description: Definitions and APIs to manages an OpenWiFi RRM Providers. | ||||||
|  |   version: 1.0.0 | ||||||
|  |   license: | ||||||
|  |     name: BSD3 | ||||||
|  |     url: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE | ||||||
|  |  | ||||||
|  | servers: | ||||||
|  |   - url: 'https://localhost:16022/api/v1' | ||||||
|  |  | ||||||
|  | security: | ||||||
|  |   - bearerAuth: [] | ||||||
|  |   - ApiKeyAuth: [] | ||||||
|  |  | ||||||
|  | components: | ||||||
|  |   securitySchemes: | ||||||
|  |     ApiKeyAuth: | ||||||
|  |       type: apiKey | ||||||
|  |       in: header | ||||||
|  |       name: X-API-KEY | ||||||
|  |     bearerAuth: | ||||||
|  |       type: http | ||||||
|  |       scheme: bearer | ||||||
|  |       bearerFormat: JWT | ||||||
|  |  | ||||||
|  |   responses: | ||||||
|  |     NotFound: | ||||||
|  |       $ref: 'https://github.com/Telecominfraproject/wlan-cloud-ucentralsec/blob/main/openpapi/owsec.yaml#/components/responses/NotFound' | ||||||
|  |     Unauthorized: | ||||||
|  |       $ref: 'https://github.com/Telecominfraproject/wlan-cloud-ucentralsec/blob/main/openpapi/owsec.yaml#/components/responses/Unauthorized' | ||||||
|  |     Success: | ||||||
|  |       $ref: 'https://github.com/Telecominfraproject/wlan-cloud-ucentralsec/blob/main/openpapi/owsec.yaml#/components/responses/Success' | ||||||
|  |     BadRequest: | ||||||
|  |       $ref: 'https://github.com/Telecominfraproject/wlan-cloud-ucentralsec/blob/main/openpapi/owsec.yaml#/components/responses/BadRequest' | ||||||
|  |  | ||||||
|  |   schemas: | ||||||
|  |  | ||||||
|  |     Provider: | ||||||
|  |       type: object | ||||||
|  |       properties: | ||||||
|  |         vendor: | ||||||
|  |           description: The name of the vendor for display. | ||||||
|  |           type: string | ||||||
|  |           minLength: 1 | ||||||
|  |           maxLength: 128 | ||||||
|  |         vendorShortname: | ||||||
|  |           description: A shortname for the vendor. Only letters and numbers are allowed. This is the name used internally. | ||||||
|  |           type: string | ||||||
|  |           minLength: 4 | ||||||
|  |           maxLength: 16 | ||||||
|  |         version: | ||||||
|  |           description: An identifier that will help users identify the version of the RRM module they are using. | ||||||
|  |           type: string | ||||||
|  |         about: | ||||||
|  |           description: A link to the Vendor page for this RRM Module | ||||||
|  |           type: string | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     Algorithm: | ||||||
|  |       type: object | ||||||
|  |       properties: | ||||||
|  |         name: | ||||||
|  |           description: A display for this algorithm. | ||||||
|  |           type: string | ||||||
|  |           minLength: 1 | ||||||
|  |           maxLength: 128 | ||||||
|  |         description: | ||||||
|  |           description: A description of the algorithm. | ||||||
|  |           type: string | ||||||
|  |         shortName: | ||||||
|  |           description: This is the name used internally. | ||||||
|  |           type: string | ||||||
|  |           minLength: 4 | ||||||
|  |           maxLength: 16 | ||||||
|  |         parameterFormat: | ||||||
|  |           description: this is a Regex used to validate the input. If this is empty, no validation will be performed. | ||||||
|  |           type: string | ||||||
|  |         parameterSamples: | ||||||
|  |           description: These samples will be displayed in the UI to the user trying to configure the options | ||||||
|  |           type: array | ||||||
|  |           items: | ||||||
|  |             type: string | ||||||
|  |         helper: | ||||||
|  |           description: A link to a web page or PDF document explaining the algorithm and its parameters | ||||||
|  |           type: string | ||||||
|  |  | ||||||
|  |     Algorithms: | ||||||
|  |       description: The list of all algorithms supported by the vendor | ||||||
|  |       type: array | ||||||
|  |       items: | ||||||
|  |         $ref: '#/components/schemas/Algorithm' | ||||||
|  |  | ||||||
|  | paths: | ||||||
|  |   /provider: | ||||||
|  |     get: | ||||||
|  |       tags: | ||||||
|  |         - RRM | ||||||
|  |       operationId: getProvider | ||||||
|  |       summary: Retrieve information about the provider for this RRM Module | ||||||
|  |       responses: | ||||||
|  |         200: | ||||||
|  |           $ref: '#/components/schemas/Provider' | ||||||
|  |         400: | ||||||
|  |           $ref: '#/components/responses/BadRequest' | ||||||
|  |         403: | ||||||
|  |           $ref: '#/components/responses/Unauthorized' | ||||||
|  |         404: | ||||||
|  |           $ref: '#/components/responses/NotFound' | ||||||
|  |  | ||||||
|  |   /algorithms: | ||||||
|  |     get: | ||||||
|  |       tags: | ||||||
|  |         - RRM | ||||||
|  |       operationId: getAlgorithms | ||||||
|  |       summary: Retrieve a lists of algorithms supported in the module. | ||||||
|  |       responses: | ||||||
|  |         200: | ||||||
|  |           $ref: '#/components/schemas/Algorithms' | ||||||
|  |         400: | ||||||
|  |           $ref: '#/components/responses/BadRequest' | ||||||
|  |         403: | ||||||
|  |           $ref: '#/components/responses/Unauthorized' | ||||||
|  |         404: | ||||||
|  |           $ref: '#/components/responses/NotFound' | ||||||
|  |  | ||||||
|  |   /runRRM: | ||||||
|  |     put: | ||||||
|  |       tags: | ||||||
|  |         - RRM | ||||||
|  |       operationId: runRRMNow | ||||||
|  |       summary: Run a specific or default RRM algorithm. The UI user or CLI user will have the ability to run an algorithm on demand. | ||||||
|  |       parameters: | ||||||
|  |         - in: query | ||||||
|  |           description: | ||||||
|  |           name: venue | ||||||
|  |           schema: | ||||||
|  |             type: string | ||||||
|  |             format: uuid | ||||||
|  |           required: true | ||||||
|  |         - in: query | ||||||
|  |           description: Perform RRM without updating anything. This may be used by an admin to see what RRM would do. | ||||||
|  |           name: mock | ||||||
|  |           schema: | ||||||
|  |             type: boolean | ||||||
|  |             default: false | ||||||
|  |           required: false | ||||||
|  |         - in: query | ||||||
|  |           description: Specify the RRM algorithm to use. If omitted, select the default algorithm. | ||||||
|  |           schema: | ||||||
|  |             type: string | ||||||
|  |           required: false | ||||||
|  |         - in: query | ||||||
|  |           description: Specify the parameters to use with the RRM algorithm to use. If omitted, select the default parameters. | ||||||
|  |           schema: | ||||||
|  |             type: string | ||||||
|  |           required: false | ||||||
|  |       responses: | ||||||
|  |         200: | ||||||
|  |           description: Return the list of actions that were or would be performed. | ||||||
|  |           content: | ||||||
|  |             application/json: | ||||||
|  |               schema: | ||||||
|  |                 type: array | ||||||
|  |                 items: | ||||||
|  |                   type: string | ||||||
|  |         400: | ||||||
|  |           $ref: '#/components/responses/BadRequest' | ||||||
|  |         403: | ||||||
|  |           $ref: '#/components/responses/Unauthorized' | ||||||
|  |         404: | ||||||
|  |           $ref: '#/components/responses/NotFound' | ||||||
|  |  | ||||||
| @@ -34,9 +34,11 @@ openwifi.system.uri.private = https://localhost:17005 | |||||||
| openwifi.system.uri.public = https://ucentral.dpaas.arilia.com:16005 | openwifi.system.uri.public = https://ucentral.dpaas.arilia.com:16005 | ||||||
| openwifi.system.commandchannel = /tmp/app.owprov | openwifi.system.commandchannel = /tmp/app.owprov | ||||||
| openwifi.system.uri.ui = owprov-ui.arilia.com | openwifi.system.uri.ui = owprov-ui.arilia.com | ||||||
|  | openwifi.security.restapi.disable = false | ||||||
|  |  | ||||||
| firmware.updater.upgrade = false | firmware.updater.upgrade = false | ||||||
| firmware.updater.releaseonly = false | firmware.updater.releaseonly = false | ||||||
|  | rrm.default = false; | ||||||
|  |  | ||||||
| geocodeapi = google | geocodeapi = google | ||||||
| google.apikey = ********************************** | google.apikey = ********************************** | ||||||
| @@ -65,6 +67,13 @@ openwifi.kafka.enable = true | |||||||
| openwifi.kafka.brokerlist = a1.arilia.com:9092 | openwifi.kafka.brokerlist = a1.arilia.com:9092 | ||||||
| openwifi.kafka.auto.commit = false | openwifi.kafka.auto.commit = false | ||||||
| openwifi.kafka.queue.buffering.max.ms = 50 | openwifi.kafka.queue.buffering.max.ms = 50 | ||||||
|  | openwifi.kafka.ssl.ca.location = | ||||||
|  | openwifi.kafka.ssl.certificate.location = | ||||||
|  | openwifi.kafka.ssl.key.location = | ||||||
|  | openwifi.kafka.ssl.key.password = | ||||||
|  |  | ||||||
|  | signup.graceperiod = 3600 | ||||||
|  | signup.lingerperiod = 84400 | ||||||
|  |  | ||||||
| # | # | ||||||
| # This section select which form of persistence you need | # This section select which form of persistence you need | ||||||
|   | |||||||
| @@ -39,6 +39,7 @@ openwifi.system.uri.private = ${SYSTEM_URI_PRIVATE} | |||||||
| openwifi.system.uri.public = ${SYSTEM_URI_PUBLIC} | openwifi.system.uri.public = ${SYSTEM_URI_PUBLIC} | ||||||
| openwifi.system.commandchannel = /tmp/app.ucentralfms | openwifi.system.commandchannel = /tmp/app.ucentralfms | ||||||
| openwifi.system.uri.ui = ${SYSTEM_URI_UI} | openwifi.system.uri.ui = ${SYSTEM_URI_UI} | ||||||
|  | openwifi.security.restapi.disable = ${SECURITY_RESTAPI_DISABLE} | ||||||
|  |  | ||||||
| ############################# | ############################# | ||||||
| # Generic information for all micro services | # Generic information for all micro services | ||||||
| @@ -58,6 +59,10 @@ openwifi.kafka.enable = ${KAFKA_ENABLE} | |||||||
| openwifi.kafka.brokerlist = ${KAFKA_BROKERLIST} | openwifi.kafka.brokerlist = ${KAFKA_BROKERLIST} | ||||||
| openwifi.kafka.auto.commit = false | openwifi.kafka.auto.commit = false | ||||||
| openwifi.kafka.queue.buffering.max.ms = 50 | openwifi.kafka.queue.buffering.max.ms = 50 | ||||||
|  | openwifi.kafka.ssl.ca.location = ${KAFKA_SSL_CA_LOCATION} | ||||||
|  | openwifi.kafka.ssl.certificate.location = ${KAFKA_SSL_CERTIFICATE_LOCATION} | ||||||
|  | openwifi.kafka.ssl.key.location = ${KAFKA_SSL_KEY_LOCATION} | ||||||
|  | openwifi.kafka.ssl.key.password = ${KAFKA_SSL_KEY_PASSWORD} | ||||||
|  |  | ||||||
| # | # | ||||||
| # This section select which form of persistence you need | # This section select which form of persistence you need | ||||||
|   | |||||||
							
								
								
									
										250
									
								
								src/APConfig.cpp
									
									
									
									
									
								
							
							
						
						
									
										250
									
								
								src/APConfig.cpp
									
									
									
									
									
								
							| @@ -12,7 +12,16 @@ namespace OpenWifi { | |||||||
|             DeviceType_(DeviceType), |             DeviceType_(DeviceType), | ||||||
|             Logger_(L), |             Logger_(L), | ||||||
|             Explain_(Explain) |             Explain_(Explain) | ||||||
|     {} |     { | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     APConfig::APConfig(const std::string & SerialNumber, Poco::Logger & L) | ||||||
|  |         :   SerialNumber_(SerialNumber), | ||||||
|  |             Logger_(L) | ||||||
|  |     { | ||||||
|  |         Explain_ = false; | ||||||
|  |         Sub_ = true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     bool APConfig::FindRadio(const std::string &Band, const Poco::JSON::Array::Ptr &Arr, Poco::JSON::Object::Ptr & Radio) { |     bool APConfig::FindRadio(const std::string &Band, const Poco::JSON::Array::Ptr &Arr, Poco::JSON::Object::Ptr & Radio) { | ||||||
|         for(const auto &i:*Arr) { |         for(const auto &i:*Arr) { | ||||||
| @@ -36,7 +45,8 @@ namespace OpenWifi { | |||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     static void ShowJSON(const char *S, const Poco::JSON::Object::Ptr &Obj) { |  | ||||||
|  |     [[maybe_unused ]] static void ShowJSON([[maybe_unused]] const char *S, [[maybe_unused]] const Poco::JSON::Object::Ptr &Obj) { | ||||||
|         /* |         /* | ||||||
|         std::stringstream O; |         std::stringstream O; | ||||||
|         Poco::JSON::Stringifier::stringify(Obj,O); |         Poco::JSON::Stringifier::stringify(Obj,O); | ||||||
| @@ -45,149 +55,160 @@ namespace OpenWifi { | |||||||
|          */ |          */ | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool APConfig::mergeArray(const std::string &K, const Poco::JSON::Array::Ptr &A , const Poco::JSON::Array::Ptr &B, Poco::JSON::Array &Arr) { |     bool APConfig::ReplaceVariablesInObject( const Poco::JSON::Object::Ptr & Original, Poco::JSON::Object::Ptr & Result) { | ||||||
|         if(K=="radios") { |         // get all the names and expand | ||||||
|             auto BB=Poco::makeShared<Poco::JSON::Array>(); |         auto Names = Original->getNames(); | ||||||
|             BB = B; |         for(const auto &i:Names) { | ||||||
|             for(const auto &i:*A) { |             if(i=="__variableBlock") { | ||||||
|                 auto A_Radio = i.extract<Poco::JSON::Object::Ptr>(); |                 if(Original->isArray(i)) { | ||||||
|                 // std::cout << "Radio A:" << std::endl; |                     auto UUIDs = Original->getArray(i); | ||||||
|                 // ShowJSON(A_Radio); |                     for(const auto &uuid:*UUIDs) { | ||||||
|                 if(A_Radio->has("band")) { |                         ProvObjects::VariableBlock  VB; | ||||||
|                     std::string Band = A_Radio->get("band").toString(); |                         if(StorageService()->VariablesDB().GetRecord("id", uuid, VB)) { | ||||||
|                     // std::cout << "Looking for band: " << Band << std::endl; |                             for(const auto &var:VB.variables) { | ||||||
|                     auto B_Radio=Poco::makeShared<Poco::JSON::Object>(); |                                 Poco::JSON::Parser P; | ||||||
|                     if(FindRadio(Band,B,B_Radio)) { |                                 auto VariableBlockInfo = P.parse(var.value).extract<Poco::JSON::Object::Ptr>(); | ||||||
|                         ShowJSON("Data to be merged", B_Radio); |                                 auto VarNames = VariableBlockInfo->getNames(); | ||||||
|                         auto RR = Poco::makeShared<Poco::JSON::Object>(); |                                 for(const auto &j:VarNames) { | ||||||
|                         merge(A_Radio, B_Radio,RR); |                                     Result->set(j,VariableBlockInfo->get(j)); | ||||||
|                         ShowJSON("Merged data", RR); |                                 } | ||||||
|                         auto CC = Poco::makeShared<Poco::JSON::Array>(); |                             } | ||||||
|                         RemoveBand(Band, BB, CC ); |                         } | ||||||
|                         BB = CC; |                     } | ||||||
|                         Arr.add(RR); |                 } | ||||||
|  |             } else if(Original->isArray(i)) { | ||||||
|  |                 auto Arr = Poco::makeShared<Poco::JSON::Array>(); | ||||||
|  |                 auto Obj = Original->getArray(i); | ||||||
|  |                 ReplaceVariablesInArray(Obj,Arr); | ||||||
|  |                 Result->set(i,Arr); | ||||||
|  |             } else if (Original->isObject(i)) { | ||||||
|  |                 auto Expanded = Poco::makeShared<Poco::JSON::Object>(); | ||||||
|  |                 auto Obj = Original->getObject(i); | ||||||
|  |                 ReplaceVariablesInObject(Obj,Expanded); | ||||||
|  |                 Result->set(i,Expanded); | ||||||
|             } else { |             } else { | ||||||
|                         Arr.add(A_Radio); |                 Result->set(i,Original->get(i)); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|             } |  | ||||||
|             for(const auto &i:*BB) |  | ||||||
|                 Arr.add(i); |  | ||||||
|         } else { |  | ||||||
|             Arr = *A; |  | ||||||
|         } |  | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool APConfig::merge(const Poco::JSON::Object::Ptr & A, const Poco::JSON::Object::Ptr & B, Poco::JSON::Object::Ptr &C) { |     bool APConfig::ReplaceVariablesInArray( const Poco::JSON::Array::Ptr & Original, Poco::JSON::Array::Ptr & ResultArray) { | ||||||
|         for(const auto &i:*A) { |  | ||||||
|             const std::string & K = i.first; |  | ||||||
|             //  std::cout << "KEY: " << K << std::endl; |  | ||||||
|             if(B->has(K)) { |  | ||||||
|                 if(A->isArray(K)) { |  | ||||||
|                     //  std::cout << "ISARRAY" << std::endl; |  | ||||||
|                     if(B->isArray(K)) { |  | ||||||
|                         Poco::JSON::Array   Arr; |  | ||||||
|                         auto AR1=A->getArray(K); |  | ||||||
|                         auto AR2=B->getArray(K); |  | ||||||
|                         mergeArray(K,AR1,AR2,Arr); |  | ||||||
|                         C->set(K,Arr); |  | ||||||
|                     } else { |  | ||||||
|                         C->set(K,A->getArray(K)); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|                 else if(A->isObject(K) && B->isObject(K)) { |  | ||||||
|                     //  std::cout << "ISOBJECT" << std::endl; |  | ||||||
|                     auto R=Poco::makeShared<Poco::JSON::Object>(); |  | ||||||
|                     merge(A->getObject(K),B->getObject(K),R); |  | ||||||
|                     C->set(K,R); |  | ||||||
|                 } |  | ||||||
|                 else { |  | ||||||
|                     C->set(K,i.second); |  | ||||||
|                 } |  | ||||||
|             } else { |  | ||||||
|                 C->set(K,i.second); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         for(const auto &i:*B) { |         for(const auto &element:*Original) { | ||||||
|             const std::string & K = i.first; |  | ||||||
|             if(!A->has(K)) { |  | ||||||
|                 // std::cout << "Before leave" << std::endl; |  | ||||||
|                 // ShowJSON(C); |  | ||||||
|                 C->set(K, i.second); |  | ||||||
|                 // std::cout << "After leave" << std::endl; |  | ||||||
|                 // ShowJSON(C); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|  |             if(element.isArray()) { | ||||||
|  |                 auto Expanded = Poco::makeShared<Poco::JSON::Array>(); | ||||||
|  |                 const auto & Object = element.extract<Poco::JSON::Array::Ptr>(); | ||||||
|  |                 ReplaceVariablesInArray(Object,Expanded); | ||||||
|  |                 ResultArray->add(Expanded); | ||||||
|  |             } else if(element.isStruct()) { | ||||||
|  |                 auto Expanded = Poco::makeShared<Poco::JSON::Object>(); | ||||||
|  |                 const auto & Object = element.extract<Poco::JSON::Object::Ptr>(); | ||||||
|  |                 ReplaceVariablesInObject(Object,Expanded); | ||||||
|  |                 ResultArray->add(Expanded); | ||||||
|  |             } else if(  element.isString() || | ||||||
|  |                         element.isNumeric() || | ||||||
|  |                         element.isBoolean() || | ||||||
|  |                         element.isInteger() || | ||||||
|  |                         element.isSigned() ) { | ||||||
|  |                 ResultArray->add(element); | ||||||
|  |             } else { | ||||||
|  |                 auto Expanded = Poco::makeShared<Poco::JSON::Object>(); | ||||||
|  |                 const auto & Object = element.extract<Poco::JSON::Object::Ptr>(); | ||||||
|  |                 ReplaceVariablesInObject(Object,Expanded); | ||||||
|  |                 ResultArray->add(Expanded); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool APConfig::Get(Poco::JSON::Object::Ptr &Configuration) { |     bool APConfig::Get(Poco::JSON::Object::Ptr & Configuration) { | ||||||
|         if(Config_.empty()) { |         if(Config_.empty()) { | ||||||
|             Explanation_.clear(); |             Explanation_.clear(); | ||||||
|             try { |             try { | ||||||
|  |                 if(!Sub_) { | ||||||
|                     ProvObjects::InventoryTag D; |                     ProvObjects::InventoryTag D; | ||||||
|                 if(StorageService()->InventoryDB().GetRecord("serialNumber", SerialNumber_, D)) { |                     if (StorageService()->InventoryDB().GetRecord("serialNumber", SerialNumber_, D)) { | ||||||
|                     if(!D.deviceConfiguration.empty()) { |                         if (!D.deviceConfiguration.empty()) { | ||||||
|                             AddConfiguration(D.deviceConfiguration); |                             AddConfiguration(D.deviceConfiguration); | ||||||
|                         } |                         } | ||||||
|                     if(!D.entity.empty()) { |                         if (!D.entity.empty()) { | ||||||
|                             AddEntityConfig(D.entity); |                             AddEntityConfig(D.entity); | ||||||
|                     } else if(!D.venue.empty()) { |                         } else if (!D.venue.empty()) { | ||||||
|                             AddVenueConfig(D.venue); |                             AddVenueConfig(D.venue); | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|  |                 } else { | ||||||
|  |                     ProvObjects::SubscriberDevice D; | ||||||
|  |                     if (StorageService()->SubscriberDeviceDB().GetRecord("serialNumber", SerialNumber_, D)) { | ||||||
|  |                         if (!D.configuration.empty()) { | ||||||
|  |                             AddConfiguration(D.configuration); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|                 //  Now we have all the config we need. |                 //  Now we have all the config we need. | ||||||
|             } catch (const Poco::Exception &E ) { |             } catch (const Poco::Exception &E ) { | ||||||
|                 Logger_.log(E); |                 Logger_.log(E); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         //  So we have sections... |         try { | ||||||
|         //      interfaces |  | ||||||
|         //      metrics |  | ||||||
|         //      radios |  | ||||||
|         //      services |  | ||||||
|         //      globals |  | ||||||
|         //      unit |  | ||||||
|         auto Tmp=Poco::makeShared<Poco::JSON::Object>(); |  | ||||||
|             std::set<std::string> Sections; |             std::set<std::string> Sections; | ||||||
|         for(const auto &i:Config_) { |             for (const auto &i: Config_) { | ||||||
|             ShowJSON("Iteration Start:", Tmp); |  | ||||||
|                 Poco::JSON::Parser P; |                 Poco::JSON::Parser P; | ||||||
|                 auto O = P.parse(i.element.configuration).extract<Poco::JSON::Object::Ptr>(); |                 auto O = P.parse(i.element.configuration).extract<Poco::JSON::Object::Ptr>(); | ||||||
|                 auto Names = O->getNames(); |                 auto Names = O->getNames(); | ||||||
|             auto SectionInfo = O->get(Names[0]); |                 for (const auto &SectionName: Names) { | ||||||
|             auto InsertInfo = Sections.insert(Names[0]); |                     auto InsertInfo = Sections.insert(SectionName); | ||||||
|             if(InsertInfo.second) { |                     if (InsertInfo.second) { | ||||||
|                 if(Explain_) { |                         if (O->isArray(SectionName)) { | ||||||
|  |                             auto OriginalArray = O->getArray(SectionName); | ||||||
|  |                             if (Explain_) { | ||||||
|                                 Poco::JSON::Object ExObj; |                                 Poco::JSON::Object ExObj; | ||||||
|                                 ExObj.set("from-uuid", i.info.id); |                                 ExObj.set("from-uuid", i.info.id); | ||||||
|                                 ExObj.set("from-name", i.info.name); |                                 ExObj.set("from-name", i.info.name); | ||||||
|                                 ExObj.set("action", "added"); |                                 ExObj.set("action", "added"); | ||||||
|                     ExObj.set("element",SectionInfo); |                                 ExObj.set("element", OriginalArray); | ||||||
|                                 Explanation_.add(ExObj); |                                 Explanation_.add(ExObj); | ||||||
|                             } |                             } | ||||||
|                 Tmp->set(Names[0],O->get(Names[0])); |                             auto ExpandedArray = Poco::makeShared<Poco::JSON::Array>(); | ||||||
|  |                             ReplaceVariablesInArray(OriginalArray, ExpandedArray); | ||||||
|  |                             Configuration->set(SectionName, ExpandedArray); | ||||||
|  |                         } else if (O->isObject(SectionName)) { | ||||||
|  |                             auto OriginalSection = O->get(SectionName).extract<Poco::JSON::Object::Ptr>(); | ||||||
|  |                             if (Explain_) { | ||||||
|  |                                 Poco::JSON::Object ExObj; | ||||||
|  |                                 ExObj.set("from-uuid", i.info.id); | ||||||
|  |                                 ExObj.set("from-name", i.info.name); | ||||||
|  |                                 ExObj.set("action", "added"); | ||||||
|  |                                 ExObj.set("element", OriginalSection); | ||||||
|  |                                 Explanation_.add(ExObj); | ||||||
|  |                             } | ||||||
|  |                             auto ExpandedSection = Poco::makeShared<Poco::JSON::Object>(); | ||||||
|  |                             ReplaceVariablesInObject(OriginalSection, ExpandedSection); | ||||||
|  |                             Configuration->set(SectionName, ExpandedSection); | ||||||
|                         } else { |                         } else { | ||||||
|                 if(Explain_) { |                             std::cout << " --- unknown element type --- " << O->get(SectionName).toString() | ||||||
|  |                                       << std::endl; | ||||||
|  |                         } | ||||||
|  |                     } else { | ||||||
|  |                         if (Explain_) { | ||||||
|                             Poco::JSON::Object ExObj; |                             Poco::JSON::Object ExObj; | ||||||
|                             ExObj.set("from-uuid", i.info.id); |                             ExObj.set("from-uuid", i.info.id); | ||||||
|                             ExObj.set("from-name", i.info.name); |                             ExObj.set("from-name", i.info.name); | ||||||
|                             ExObj.set("action", "ignored"); |                             ExObj.set("action", "ignored"); | ||||||
|                     ExObj.set("reason","weight insufficient"); |                             ExObj.set("reason", "weight insufficient"); | ||||||
|                     ExObj.set("element",SectionInfo); |                             ExObj.set("element", O->get(SectionName)); | ||||||
|                             Explanation_.add(ExObj); |                             Explanation_.add(ExObj); | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|         Configuration = Tmp; |             } | ||||||
|         if(Config_.empty()) |         } catch (...) { | ||||||
|             return false; |  | ||||||
|  |  | ||||||
|         return true; |         } | ||||||
|  |         return !Config_.empty(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     static bool DeviceTypeMatch(const std::string &DeviceType, const Types::StringVec & Types) { |     static bool DeviceTypeMatch(const std::string &DeviceType, const Types::StringVec & Types) { | ||||||
| @@ -198,19 +219,33 @@ namespace OpenWifi { | |||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     void APConfig::AddConfiguration(const ProvObjects::DeviceConfigurationElementVec &Elements) { | ||||||
|  |         for(const auto &i:Elements) { | ||||||
|  |             if(i.weight==0) { | ||||||
|  |                 VerboseElement  VE{ .element = i, .info = ProvObjects::ObjectInfo{} }; | ||||||
|  |                 Config_.push_back(VE); | ||||||
|  |             } else { | ||||||
|  |                 // we need to insert after everything bigger or equal | ||||||
|  |                 auto Hint = std::lower_bound(Config_.cbegin(),Config_.cend(),i.weight, | ||||||
|  |                                              [](const VerboseElement &Elem, uint64_t Value) { | ||||||
|  |                                                  return Elem.element.weight>=Value; }); | ||||||
|  |                 VerboseElement  VE{ .element = i, .info = ProvObjects::ObjectInfo{}}; | ||||||
|  |                 Config_.insert(Hint,VE); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     void APConfig::AddConfiguration(const Types::UUIDvec_t &UUIDs) { |     void APConfig::AddConfiguration(const Types::UUIDvec_t &UUIDs) { | ||||||
|         for(const auto &i:UUIDs) |         for(const auto &i:UUIDs) | ||||||
|             AddConfiguration(i); |             AddConfiguration(i); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void APConfig::AddConfiguration(const std::string &UUID) { |     void APConfig::AddConfiguration(const std::string &UUID) { | ||||||
|  |  | ||||||
|         ProvObjects::DeviceConfiguration    Config; |  | ||||||
|         if(UUID.empty()) |         if(UUID.empty()) | ||||||
|             return; |             return; | ||||||
|  |  | ||||||
|         if(StorageService()->ConfigurationDB().GetRecord("id", UUID,Config)) { |         ProvObjects::DeviceConfiguration    Config; | ||||||
|             //  find where to insert into this list using the weight. |         if(StorageService()->ConfigurationDB().GetRecord("id", UUID, Config)) { | ||||||
|             if(!Config.configuration.empty()) { |             if(!Config.configuration.empty()) { | ||||||
|                 if(DeviceTypeMatch(DeviceType_,Config.deviceTypes)) { |                 if(DeviceTypeMatch(DeviceType_,Config.deviceTypes)) { | ||||||
|                     for(const auto &i:Config.configuration) { |                     for(const auto &i:Config.configuration) { | ||||||
| @@ -220,7 +255,7 @@ namespace OpenWifi { | |||||||
|                         } else { |                         } else { | ||||||
|                             // we need to insert after everything bigger or equal |                             // we need to insert after everything bigger or equal | ||||||
|                             auto Hint = std::lower_bound(Config_.cbegin(),Config_.cend(),i.weight, |                             auto Hint = std::lower_bound(Config_.cbegin(),Config_.cend(),i.weight, | ||||||
|                                                          [](const VerboseElement &Elem, int Value) { |                                                          [](const VerboseElement &Elem, uint64_t Value) { | ||||||
|                                 return Elem.element.weight>=Value; }); |                                 return Elem.element.weight>=Value; }); | ||||||
|                             VerboseElement  VE{ .element = i, .info = Config.info}; |                             VerboseElement  VE{ .element = i, .info = Config.info}; | ||||||
|                             Config_.insert(Hint,VE); |                             Config_.insert(Hint,VE); | ||||||
| @@ -241,21 +276,24 @@ namespace OpenWifi { | |||||||
|     void APConfig::AddEntityConfig(const std::string &UUID) { |     void APConfig::AddEntityConfig(const std::string &UUID) { | ||||||
|         ProvObjects::Entity E; |         ProvObjects::Entity E; | ||||||
|         if(StorageService()->EntityDB().GetRecord("id",UUID,E)) { |         if(StorageService()->EntityDB().GetRecord("id",UUID,E)) { | ||||||
|             AddConfiguration(E.deviceConfiguration); |             AddConfiguration(E.configurations); | ||||||
|             if(!E.parent.empty()) |             if(!E.parent.empty()) { | ||||||
|                 AddEntityConfig(E.parent); |                 AddEntityConfig(E.parent); | ||||||
|             } |             } | ||||||
|  |         } else { | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void APConfig::AddVenueConfig(const std::string &UUID) { |     void APConfig::AddVenueConfig(const std::string &UUID) { | ||||||
|         ProvObjects::Venue V; |         ProvObjects::Venue V; | ||||||
|         if(StorageService()->VenueDB().GetRecord("id",UUID,V)) { |         if(StorageService()->VenueDB().GetRecord("id",UUID,V)) { | ||||||
|             AddConfiguration(V.deviceConfiguration); |             AddConfiguration(V.configurations); | ||||||
|             if(!V.entity.empty()) { |             if(!V.entity.empty()) { | ||||||
|                 AddEntityConfig(V.entity); |                 AddEntityConfig(V.entity); | ||||||
|             } else if(!V.parent.empty()) { |             } else if(!V.parent.empty()) { | ||||||
|                 AddVenueConfig(V.parent); |                 AddVenueConfig(V.parent); | ||||||
|             } |             } | ||||||
|  |         } else { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -19,12 +19,14 @@ namespace OpenWifi { | |||||||
|     class APConfig { |     class APConfig { | ||||||
|         public: |         public: | ||||||
|             explicit APConfig(const std::string & SerialNumber, const std::string & DeviceType, Poco::Logger & L, bool Explain=false); |             explicit APConfig(const std::string & SerialNumber, const std::string & DeviceType, Poco::Logger & L, bool Explain=false); | ||||||
|  |             explicit APConfig(const std::string & SerialNumber, Poco::Logger & L); | ||||||
|  |  | ||||||
|  |  | ||||||
|             [[nodiscard]] bool Get(Poco::JSON::Object::Ptr &Configuration); |             [[nodiscard]] bool Get(Poco::JSON::Object::Ptr &Configuration); | ||||||
|  |  | ||||||
|             void AddConfiguration(const std::string &UUID); |             void AddConfiguration(const std::string &UUID); | ||||||
|             void AddConfiguration(const Types::UUIDvec_t &UUID); |             void AddConfiguration(const Types::UUIDvec_t &UUID); | ||||||
|  |             void AddConfiguration(const ProvObjects::DeviceConfigurationElementVec &Elements); | ||||||
|             void AddVenueConfig(const std::string &UUID); |             void AddVenueConfig(const std::string &UUID); | ||||||
|             void AddEntityConfig(const std::string &UUID); |             void AddEntityConfig(const std::string &UUID); | ||||||
|             const Poco::JSON::Array & Explanation() { return Explanation_; }; |             const Poco::JSON::Array & Explanation() { return Explanation_; }; | ||||||
| @@ -37,6 +39,11 @@ namespace OpenWifi { | |||||||
|             Types::StringPairVec        Errors; |             Types::StringPairVec        Errors; | ||||||
|             bool                        Explain_=false; |             bool                        Explain_=false; | ||||||
|             Poco::JSON::Array           Explanation_; |             Poco::JSON::Array           Explanation_; | ||||||
|  |             bool                        Sub_=false; | ||||||
|  |             Poco::Logger & Logger()     { return Logger_;} | ||||||
|  |  | ||||||
|  |             bool ReplaceVariablesInArray( const Poco::JSON::Array::Ptr & O, Poco::JSON::Array::Ptr & Result); | ||||||
|  |             bool ReplaceVariablesInObject( const Poco::JSON::Object::Ptr & Original, Poco::JSON::Object::Ptr & Result); | ||||||
|  |  | ||||||
|             bool FindRadio(const std::string &Band, const Poco::JSON::Array::Ptr &Arr, Poco::JSON::Object::Ptr & Radio); |             bool FindRadio(const std::string &Band, const Poco::JSON::Array::Ptr &Arr, Poco::JSON::Object::Ptr & Radio); | ||||||
|             bool mergeArray(const std::string &K, const Poco::JSON::Array::Ptr &A , const Poco::JSON::Array::Ptr &B, Poco::JSON::Array &Arr); |             bool mergeArray(const std::string &K, const Poco::JSON::Array::Ptr &A , const Poco::JSON::Array::Ptr &B, Poco::JSON::Array &Arr); | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ | |||||||
| // | // | ||||||
|  |  | ||||||
| #include "AutoDiscovery.h" | #include "AutoDiscovery.h" | ||||||
| #include "framework/uCentral_Protocol.h" | #include "framework/ow_constants.h" | ||||||
| #include "framework/KafkaTopics.h" | #include "framework/KafkaTopics.h" | ||||||
| #include "StorageService.h" | #include "StorageService.h" | ||||||
|  |  | ||||||
| @@ -26,6 +26,7 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
|     void AutoDiscovery::run() { |     void AutoDiscovery::run() { | ||||||
|         Poco::AutoPtr<Poco::Notification>	Note(Queue_.waitDequeueNotification()); |         Poco::AutoPtr<Poco::Notification>	Note(Queue_.waitDequeueNotification()); | ||||||
|  |         Utils::SetThreadName("auto-discovery"); | ||||||
|         while(Note && Running_) { |         while(Note && Running_) { | ||||||
|             auto Msg = dynamic_cast<DiscoveryMessage *>(Note.get()); |             auto Msg = dynamic_cast<DiscoveryMessage *>(Note.get()); | ||||||
|             if(Msg!= nullptr) { |             if(Msg!= nullptr) { | ||||||
| @@ -55,8 +56,12 @@ namespace OpenWifi { | |||||||
|                                 DeviceType = PingMessage->get(uCentralProtocol::COMPATIBLE).toString(); |                                 DeviceType = PingMessage->get(uCentralProtocol::COMPATIBLE).toString(); | ||||||
|                             } |                             } | ||||||
|                         } |                         } | ||||||
|  |                         std::string Locale; | ||||||
|  |                         if(PayloadObj->has("locale")) | ||||||
|  |                             Locale = PayloadObj->get("locale").toString(); | ||||||
|  |  | ||||||
|                         if (!SerialNumber.empty()) { |                         if (!SerialNumber.empty()) { | ||||||
|                             StorageService()->InventoryDB().CreateFromConnection(SerialNumber, ConnectedIP, DeviceType); |                             StorageService()->InventoryDB().CreateFromConnection(SerialNumber, ConnectedIP, DeviceType, Locale); | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                 } catch (const Poco::Exception &E) { |                 } catch (const Poco::Exception &E) { | ||||||
|   | |||||||
| @@ -33,7 +33,7 @@ namespace OpenWifi { | |||||||
|             void Stop() override; |             void Stop() override; | ||||||
|             void ConnectionReceived( const std::string & Key, const std::string & Payload) { |             void ConnectionReceived( const std::string & Key, const std::string & Payload) { | ||||||
|                 std::lock_guard G(Mutex_); |                 std::lock_guard G(Mutex_); | ||||||
|                 Logger().information(Poco::format("Device(%s): Connection/Ping message.", Key)); |                 poco_debug(Logger(),Poco::format("Device(%s): Connection/Ping message.", Key)); | ||||||
|                 Queue_.enqueueNotification( new DiscoveryMessage(Key,Payload)); |                 Queue_.enqueueNotification( new DiscoveryMessage(Key,Payload)); | ||||||
|             } |             } | ||||||
|             void run() override; |             void run() override; | ||||||
|   | |||||||
| @@ -25,27 +25,27 @@ namespace OpenWifi { | |||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void ConfigSanityChecker::Check_radios(nlohmann::json &d) { |     void ConfigSanityChecker::Check_radios([[maybe_unused]] nlohmann::json &d) { | ||||||
|         std::cout << "Validating radios" << std::endl; |         std::cout << "Validating radios" << std::endl; | ||||||
|  |  | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     void ConfigSanityChecker::Check_interfaces(nlohmann::json &d) { |     void ConfigSanityChecker::Check_interfaces([[maybe_unused]] nlohmann::json &d) { | ||||||
|         std::cout << "Validating interfaces" << std::endl; |         std::cout << "Validating interfaces" << std::endl; | ||||||
|  |  | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     void ConfigSanityChecker::Check_metrics(nlohmann::json &d) { |     void ConfigSanityChecker::Check_metrics([[maybe_unused]] nlohmann::json &d) { | ||||||
|         std::cout << "Validating metrics" << std::endl; |         std::cout << "Validating metrics" << std::endl; | ||||||
|  |  | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     void ConfigSanityChecker::Check_services(nlohmann::json &d) { |     void ConfigSanityChecker::Check_services([[maybe_unused]] nlohmann::json &d) { | ||||||
|         std::cout << "Validating services" << std::endl; |         std::cout << "Validating services" << std::endl; | ||||||
|  |  | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     void ConfigSanityChecker::Check_uuid(nlohmann::json &d) { |     void ConfigSanityChecker::Check_uuid([[maybe_unused]] nlohmann::json &d) { | ||||||
|         std::cout << "Validating uuid" << std::endl; |         std::cout << "Validating uuid" << std::endl; | ||||||
|  |  | ||||||
|     }; |     }; | ||||||
|   | |||||||
| @@ -16,8 +16,10 @@ | |||||||
| #include "framework/ConfigurationValidator.h" | #include "framework/ConfigurationValidator.h" | ||||||
| #include "SerialNumberCache.h" | #include "SerialNumberCache.h" | ||||||
| #include "JobController.h" | #include "JobController.h" | ||||||
| #include "WebSocketClientServer.h" |  | ||||||
| #include "FindCountry.h" | #include "FindCountry.h" | ||||||
|  | #include "Signup.h" | ||||||
|  | #include "DeviceTypeCache.h" | ||||||
|  | #include "FileDownloader.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace OpenWifi { | ||||||
| 	class Daemon *Daemon::instance_ = nullptr; | 	class Daemon *Daemon::instance_ = nullptr; | ||||||
| @@ -31,18 +33,21 @@ namespace OpenWifi { | |||||||
| 								   vDAEMON_BUS_TIMER, | 								   vDAEMON_BUS_TIMER, | ||||||
| 								   SubSystemVec{ | 								   SubSystemVec{ | ||||||
| 									   OpenWifi::StorageService(), | 									   OpenWifi::StorageService(), | ||||||
|  |                                        DeviceTypeCache(), | ||||||
| 									   ConfigurationValidator(), | 									   ConfigurationValidator(), | ||||||
| 									   SerialNumberCache(), | 									   SerialNumberCache(), | ||||||
| 									   AutoDiscovery(), | 									   AutoDiscovery(), | ||||||
| 									   JobController(), | 									   JobController(), | ||||||
| 									   WebSocketClientServer(), | 									   WebSocketClientServer(), | ||||||
|                                        FindCountryFromIP() |                                        FindCountryFromIP(), | ||||||
|  |                                        Signup(), | ||||||
|  |                                        FileDownloader() | ||||||
| 								   }); | 								   }); | ||||||
| 		} | 		} | ||||||
| 		return instance_; | 		return instance_; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	void Daemon::initialize() { | 	void Daemon::PostInitialization([[maybe_unused]] Poco::Util::Application &self) { | ||||||
| 	    if(MicroService::instance().ConfigGetBool("firmware.updater.upgrade",false)) { | 	    if(MicroService::instance().ConfigGetBool("firmware.updater.upgrade",false)) { | ||||||
| 	        if(MicroService::instance().ConfigGetBool("firmware.updater.releaseonly",false)) { | 	        if(MicroService::instance().ConfigGetBool("firmware.updater.releaseonly",false)) { | ||||||
| 	            FWRules_ = ProvObjects::upgrade_release_only; | 	            FWRules_ = ProvObjects::upgrade_release_only; | ||||||
| @@ -52,25 +57,41 @@ namespace OpenWifi { | |||||||
| 	    } else { | 	    } else { | ||||||
| 	        FWRules_ = ProvObjects::dont_upgrade; | 	        FWRules_ = ProvObjects::dont_upgrade; | ||||||
| 	    } | 	    } | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void MicroServicePostInitialization() { |         WebSocketProcessor_ = std::make_unique<ProvWebSocketClient>(logger()); | ||||||
|         Daemon()->initialize(); |  | ||||||
|  |         AssetDir_ = MicroService::instance().DataDir() + "/wwwassets"; | ||||||
|  |         Poco::File	DataDir(AssetDir_); | ||||||
|  |         if(!DataDir.exists()) { | ||||||
|  |             try { | ||||||
|  |                 DataDir.createDirectory(); | ||||||
|  |             } catch (const Poco::Exception &E) { | ||||||
|  |                 logger().log(E); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| int main(int argc, char **argv) { | int main(int argc, char **argv) { | ||||||
|  |     int ExitCode; | ||||||
|     try { |     try { | ||||||
|  |         Poco::Net::SSLManager::instance().initializeServer(nullptr, nullptr, nullptr); | ||||||
|         auto App = OpenWifi::Daemon::instance(); |         auto App = OpenWifi::Daemon::instance(); | ||||||
| 		auto ExitCode =  App->run(argc, argv); |         ExitCode =  App->run(argc, argv); | ||||||
| 		delete App; |         Poco::Net::SSLManager::instance().shutdown(); | ||||||
|  |  | ||||||
| 		return ExitCode; |  | ||||||
|  |  | ||||||
|     } catch (Poco::Exception &exc) { |     } catch (Poco::Exception &exc) { | ||||||
| 		std::cerr << exc.displayText() << std::endl; |         ExitCode = Poco::Util::Application::EXIT_SOFTWARE; | ||||||
| 		return Poco::Util::Application::EXIT_SOFTWARE; |         std::cout << exc.displayText() << std::endl; | ||||||
|  |     } catch (std::exception &exc) { | ||||||
|  |         ExitCode = Poco::Util::Application::EXIT_TEMPFAIL; | ||||||
|  |         std::cout << exc.what() << std::endl; | ||||||
|  |     } catch (...) { | ||||||
|  |         ExitCode = Poco::Util::Application::EXIT_TEMPFAIL; | ||||||
|  |         std::cout << "Exception on closure" << std::endl; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     std::cout << "Exitcode: " << ExitCode << std::endl; | ||||||
|  |     return ExitCode; | ||||||
| } | } | ||||||
|  |  | ||||||
| // end of namespace | // end of namespace | ||||||
							
								
								
									
										21
									
								
								src/Daemon.h
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								src/Daemon.h
									
									
									
									
									
								
							| @@ -18,14 +18,15 @@ | |||||||
| #include "framework/MicroService.h" | #include "framework/MicroService.h" | ||||||
| #include "framework/OpenWifiTypes.h" | #include "framework/OpenWifiTypes.h" | ||||||
| #include "RESTObjects/RESTAPI_ProvObjects.h" | #include "RESTObjects/RESTAPI_ProvObjects.h" | ||||||
|  | #include "ProvWebSocketClient.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace OpenWifi { | ||||||
|  |  | ||||||
| 	static const char * vDAEMON_PROPERTIES_FILENAME = "owprov.properties"; | 	[[maybe_unused]] static const char * vDAEMON_PROPERTIES_FILENAME = "owprov.properties"; | ||||||
| 	static const char * vDAEMON_ROOT_ENV_VAR = "OWPROV_ROOT"; |     [[maybe_unused]] static const char * vDAEMON_ROOT_ENV_VAR = "OWPROV_ROOT"; | ||||||
| 	static const char * vDAEMON_CONFIG_ENV_VAR = "OWPROV_CONFIG"; |     [[maybe_unused]] static const char * vDAEMON_CONFIG_ENV_VAR = "OWPROV_CONFIG"; | ||||||
| 	static const char * vDAEMON_APP_NAME = uSERVICE_PROVISIONING.c_str() ; |     [[maybe_unused]] static const char * vDAEMON_APP_NAME = uSERVICE_PROVISIONING.c_str() ; | ||||||
| 	static const uint64_t vDAEMON_BUS_TIMER = 10000; |     [[maybe_unused]] static const uint64_t vDAEMON_BUS_TIMER = 10000; | ||||||
|  |  | ||||||
|     class Daemon : public MicroService { |     class Daemon : public MicroService { | ||||||
| 		public: | 		public: | ||||||
| @@ -37,18 +38,24 @@ namespace OpenWifi { | |||||||
| 							const SubSystemVec & SubSystems) : | 							const SubSystemVec & SubSystems) : | ||||||
| 				MicroService( PropFile, RootEnv, ConfigEnv, AppName, BusTimer, SubSystems) {}; | 				MicroService( PropFile, RootEnv, ConfigEnv, AppName, BusTimer, SubSystems) {}; | ||||||
|  |  | ||||||
| 			void initialize(); |  | ||||||
| 			static Daemon *instance(); | 			static Daemon *instance(); | ||||||
| 			inline OpenWifi::ProvisioningDashboard & GetDashboard() { return DB_; } | 			inline OpenWifi::ProvisioningDashboard & GetDashboard() { return DB_; } | ||||||
| 			Poco::Logger & Log() { return Poco::Logger::get(AppName()); } | 			Poco::Logger & Log() { return Poco::Logger::get(AppName()); } | ||||||
| 			ProvObjects::FIRMWARE_UPGRADE_RULES FirmwareRules() const { return FWRules_; } | 			ProvObjects::FIRMWARE_UPGRADE_RULES FirmwareRules() const { return FWRules_; } | ||||||
|  |             inline const std::string & AssetDir() { return AssetDir_; } | ||||||
|  |             void PostInitialization(Poco::Util::Application &self); | ||||||
|  |  | ||||||
| 	  	private: | 	  	private: | ||||||
| 			static Daemon 				            *instance_; | 			static Daemon 				            *instance_; | ||||||
| 			OpenWifi::ProvisioningDashboard		    DB_{}; | 			OpenWifi::ProvisioningDashboard		    DB_{}; | ||||||
| 			ProvObjects::FIRMWARE_UPGRADE_RULES     FWRules_{ProvObjects::dont_upgrade}; | 			ProvObjects::FIRMWARE_UPGRADE_RULES     FWRules_{ProvObjects::dont_upgrade}; | ||||||
|  |             std::string                             AssetDir_; | ||||||
|  |             std::unique_ptr<ProvWebSocketClient>    WebSocketProcessor_; | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
| 	inline Daemon * Daemon() { return Daemon::instance(); } | 	inline Daemon * Daemon() { return Daemon::instance(); } | ||||||
|  |     inline void DaemonPostInitialization(Poco::Util::Application &self) { | ||||||
|  |         Daemon()->PostInitialization(self); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ | |||||||
|  |  | ||||||
| namespace OpenWifi { | namespace OpenWifi { | ||||||
| 	void ProvisioningDashboard::Create() { | 	void ProvisioningDashboard::Create() { | ||||||
| 		uint64_t Now = std::time(nullptr); | 		uint64_t Now = OpenWifi::Now(); | ||||||
| 		if(LastRun_==0 || (Now-LastRun_)>120) { | 		if(LastRun_==0 || (Now-LastRun_)>120) { | ||||||
| 			DB_.reset(); | 			DB_.reset(); | ||||||
| 			//  Todo: call dashboard creation code. | 			//  Todo: call dashboard creation code. | ||||||
|   | |||||||
							
								
								
									
										126
									
								
								src/DeviceTypeCache.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								src/DeviceTypeCache.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,126 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2022-02-23. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include <set> | ||||||
|  |  | ||||||
|  | #include "framework/MicroService.h" | ||||||
|  | #include "Poco/Timer.h" | ||||||
|  |  | ||||||
|  | namespace OpenWifi { | ||||||
|  |  | ||||||
|  |     class DeviceTypeCache : public SubSystemServer { | ||||||
|  |     public: | ||||||
|  |         inline static auto instance() { | ||||||
|  |             static auto instance_ = new DeviceTypeCache; | ||||||
|  |             return instance_; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         inline int Start() final { | ||||||
|  |             InitializeCache(); | ||||||
|  |             TimerCallback_ = std::make_unique<Poco::TimerCallback<DeviceTypeCache>>(*this,&DeviceTypeCache::onTimer); | ||||||
|  |             Timer_.setStartInterval( 60 * 1000);            // first run in 60 seconds | ||||||
|  |             Timer_.setPeriodicInterval(1 * 60 * 60 * 1000); // 1 hours | ||||||
|  |             Timer_.start(*TimerCallback_); | ||||||
|  |             return 0; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         inline void Stop() final { | ||||||
|  |             Timer_.stop(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         inline void onTimer([[maybe_unused]] Poco::Timer & timer) { | ||||||
|  |             UpdateDeviceTypes(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         inline bool IsAcceptableDeviceType(const std::string &D) const { return (DeviceTypes_.find(D)!=DeviceTypes_.end());}; | ||||||
|  |         inline bool AreAcceptableDeviceTypes(const Types::StringVec &S, bool WildCardAllowed=true) const { | ||||||
|  |             for(const auto &i:S) { | ||||||
|  |                 if(WildCardAllowed && i=="*") { | ||||||
|  |                     //   We allow wildcards | ||||||
|  |                 } else if(DeviceTypes_.find(i)==DeviceTypes_.end()) | ||||||
|  |                     return false; | ||||||
|  |             } | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |     private: | ||||||
|  |         std::atomic_bool                                        Initialized_=false; | ||||||
|  |         Poco::Timer                                             Timer_; | ||||||
|  |         std::set<std::string>                                   DeviceTypes_; | ||||||
|  |         std::unique_ptr<Poco::TimerCallback<DeviceTypeCache>>   TimerCallback_; | ||||||
|  |  | ||||||
|  |         inline DeviceTypeCache() noexcept: | ||||||
|  |                 SubSystemServer("DeviceTypes", "DEV-TYPES", "devicetypes") | ||||||
|  |         { | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         inline void InitializeCache() { | ||||||
|  |             std::lock_guard G(Mutex_); | ||||||
|  |  | ||||||
|  |             Initialized_ = true; | ||||||
|  |             std::string DeviceTypes; | ||||||
|  |             if(AppServiceRegistry().Get("deviceTypes",DeviceTypes)) { | ||||||
|  |                 Poco::JSON::Parser  P; | ||||||
|  |                 try { | ||||||
|  |                     auto O = P.parse(DeviceTypes).extract<Poco::JSON::Array::Ptr>(); | ||||||
|  |                     for(const auto &i:*O) { | ||||||
|  |                         DeviceTypes_.insert(i.toString()); | ||||||
|  |                     } | ||||||
|  |                 } catch (...) { | ||||||
|  |  | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         inline bool UpdateDeviceTypes() { | ||||||
|  |             try { | ||||||
|  |                 Types::StringPairVec QueryData; | ||||||
|  |  | ||||||
|  |                 QueryData.push_back(std::make_pair("deviceSet","true")); | ||||||
|  |                 OpenAPIRequestGet	Req(    uSERVICE_FIRMWARE, | ||||||
|  |                                              "/api/v1/firmwares", | ||||||
|  |                                              QueryData, | ||||||
|  |                                              10000); | ||||||
|  |  | ||||||
|  |                 auto Response = Poco::makeShared<Poco::JSON::Object>(); | ||||||
|  |                 auto StatusCode = Req.Do(Response); | ||||||
|  |                 if( StatusCode == Poco::Net::HTTPResponse::HTTP_OK) { | ||||||
|  |                     if(Response->isArray("deviceTypes")) { | ||||||
|  |                         std::lock_guard G(Mutex_); | ||||||
|  |                         DeviceTypes_.clear(); | ||||||
|  |                         auto Array = Response->getArray("deviceTypes"); | ||||||
|  |                         for(const auto &i:*Array) { | ||||||
|  |                             // std::cout << "Adding deviceType:" << i.toString() << std::endl; | ||||||
|  |                             DeviceTypes_.insert(i.toString()); | ||||||
|  |                         } | ||||||
|  |                         SaveCache(); | ||||||
|  |                         return true; | ||||||
|  |                     } | ||||||
|  |                 } else { | ||||||
|  |                 } | ||||||
|  |             } catch (const Poco::Exception &E) { | ||||||
|  |                 Logger().log(E); | ||||||
|  |             } | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         inline void SaveCache() { | ||||||
|  |             std::lock_guard G(Mutex_); | ||||||
|  |  | ||||||
|  |             Poco::JSON::Array   Arr; | ||||||
|  |             for(auto const &i:DeviceTypes_) | ||||||
|  |                 Arr.add(i); | ||||||
|  |  | ||||||
|  |             std::stringstream OS; | ||||||
|  |             Arr.stringify(OS); | ||||||
|  |  | ||||||
|  |             AppServiceRegistry().Set("deviceTypes", OS.str()); | ||||||
|  |         } | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     inline auto DeviceTypeCache() { return DeviceTypeCache::instance(); } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										45
									
								
								src/FileDownloader.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								src/FileDownloader.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2022-03-11. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #include "FileDownloader.h" | ||||||
|  | #include "Daemon.h" | ||||||
|  |  | ||||||
|  | namespace OpenWifi { | ||||||
|  |     int FileDownloader::Start() { | ||||||
|  |         TimerCallback_ = std::make_unique<Poco::TimerCallback<FileDownloader>>(*this,&FileDownloader::onTimer); | ||||||
|  |         Timer_.setStartInterval( 20 * 1000);  // first run in 20 seconds | ||||||
|  |         Timer_.setPeriodicInterval(2 * 60 * 60 * 1000); // 1 hours | ||||||
|  |         Timer_.start(*TimerCallback_); | ||||||
|  |         return 0; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void FileDownloader::Stop() { | ||||||
|  |         Timer_.stop(); | ||||||
|  |         Logger().notice("Stopping."); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void FileDownloader::onTimer([[maybe_unused]] Poco::Timer &timer) { | ||||||
|  |         const static std::vector<std::pair<std::string,std::string>> Files | ||||||
|  |             { | ||||||
|  |                 {"https://raw.githubusercontent.com/blogic/ucentral-schema/main/ucentral.schema.json", "ucentral.schema.json" }, | ||||||
|  |                 {"https://ucentral.io/ucentral.schema.pretty.json", "ucentral.schema.pretty.json" } | ||||||
|  |             }; | ||||||
|  |  | ||||||
|  |         Utils::SetThreadName("file-dmnldr"); | ||||||
|  |  | ||||||
|  |         for(const auto &[url,filename]:Files) { | ||||||
|  |             try { | ||||||
|  |                 std::string FileContent; | ||||||
|  |                 if (Utils::wgets(url, FileContent)) { | ||||||
|  |                     std::ofstream OutputStream(Daemon()->AssetDir() + "/" + filename, | ||||||
|  |                                      std::ios_base::out | std::ios_base::trunc); | ||||||
|  |                     OutputStream << FileContent; | ||||||
|  |                     Logger().warning(Poco::format("File %s was downloaded",url)); | ||||||
|  |                 } | ||||||
|  |             } catch(...) { | ||||||
|  |                 Logger().warning(Poco::format("File %s could not be downloaded",url)); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										34
									
								
								src/FileDownloader.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/FileDownloader.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2022-03-11. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  | #include "framework/MicroService.h" | ||||||
|  | #include "Poco/Timer.h" | ||||||
|  |  | ||||||
|  | namespace OpenWifi { | ||||||
|  |  | ||||||
|  |     class FileDownloader : public SubSystemServer { | ||||||
|  |     public: | ||||||
|  |  | ||||||
|  |         static auto instance() { | ||||||
|  |             static auto instance_ = new FileDownloader; | ||||||
|  |             return instance_; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         int Start() override; | ||||||
|  |         void Stop() override; | ||||||
|  |         void onTimer(Poco::Timer & timer); | ||||||
|  |  | ||||||
|  |     private: | ||||||
|  |         Poco::Timer                                         Timer_; | ||||||
|  |         std::unique_ptr<Poco::TimerCallback<FileDownloader>>       TimerCallback_; | ||||||
|  |         std::atomic_bool Running_ = false; | ||||||
|  |  | ||||||
|  |         FileDownloader() noexcept: | ||||||
|  |                 SubSystemServer("FileDownloader", "FILE-DOWNLOADER", "downloader") { | ||||||
|  |         } | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     inline auto FileDownloader() { return FileDownloader::instance(); } | ||||||
|  | } | ||||||
| @@ -27,11 +27,32 @@ namespace OpenWifi { | |||||||
|  |  | ||||||
|     void JobController::run() { |     void JobController::run() { | ||||||
|         Running_ = true ; |         Running_ = true ; | ||||||
|  |         Utils::SetThreadName("job-controller"); | ||||||
|         while(Running_) { |         while(Running_) { | ||||||
|             Poco::Thread::trySleep(2000); |             Poco::Thread::trySleep(2000); | ||||||
|  |  | ||||||
|  |             std::lock_guard G(Mutex_); | ||||||
|  |  | ||||||
|  |             for(auto ¤t_job:jobs_) { | ||||||
|  |                 if(current_job!=nullptr) { | ||||||
|  |                     if(current_job->Started()==0 && Pool_.used()<Pool_.available()) { | ||||||
|  |                         current_job->Logger().information(fmt::format("Starting {}: {}",current_job->JobId(),current_job->Name())); | ||||||
|  |                         current_job->Start(); | ||||||
|  |                         Pool_.start(*current_job); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|  |  | ||||||
|  |             for(auto it = jobs_.begin(); it!=jobs_.end();) {\ | ||||||
|  |                 auto current_job = *it; | ||||||
|  |                 if(current_job!=nullptr && current_job->Completed()!=0) { | ||||||
|  |                     current_job->Logger().information(fmt::format("Completed {}: {}",current_job->JobId(),current_job->Name())); | ||||||
|  |                     it = jobs_.erase(it); | ||||||
|  |                     delete current_job; | ||||||
|  |                 } else { | ||||||
|  |                     ++it; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| } | } | ||||||
| @@ -7,101 +7,45 @@ | |||||||
| #include <vector> | #include <vector> | ||||||
| #include <utility> | #include <utility> | ||||||
| #include <functional> | #include <functional> | ||||||
|  | #include <list> | ||||||
| #include "framework/MicroService.h" | #include "framework/MicroService.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace OpenWifi { | ||||||
|  |  | ||||||
|     class Job { |     class Job : public Poco::Runnable { | ||||||
|     public: |     public: | ||||||
|             struct Parameter { |         Job(const std::string &JobID, const std::string &name, const std::vector<std::string> & parameters, uint64_t when, const SecurityObjects::UserInfo &UI, Poco::Logger &L) : | ||||||
|                 std::string name; |             jobId_(JobID), | ||||||
|                 std::string value; |             name_(name), | ||||||
|                 inline void to_json(Poco::JSON::Object &Obj) const { |             parameters_(parameters), | ||||||
|                     RESTAPI_utils::field_to_json(Obj,"name",name); |             when_(when), | ||||||
|                     RESTAPI_utils::field_to_json(Obj,"value",value); |             userinfo_(UI), | ||||||
|                 } |             Logger_(L) | ||||||
|  |         {}; | ||||||
|  |  | ||||||
|                 inline bool from_json(const Poco::JSON::Object::Ptr &Obj) { |         virtual void run() = 0; | ||||||
|                     try { |         [[nodiscard]] std::string Name() const { return name_; } | ||||||
|                         RESTAPI_utils::field_from_json(Obj,"name",name); |         const SecurityObjects::UserInfo & UserInfo() const { return userinfo_; } | ||||||
|                         RESTAPI_utils::field_from_json(Obj,"value",value); |         Poco::Logger & Logger() { return Logger_; } | ||||||
|                         return true; |         const std::string & JobId() const { return jobId_; } | ||||||
|                     } catch (...) { |         const std::string & Parameter(int x) const { return parameters_[x];} | ||||||
|  |         uint64_t When() const { return when_; } | ||||||
|                     } |         void Start() { started_ = OpenWifi::Now(); } | ||||||
|                     return false; |         uint64_t Started() const { return started_; } | ||||||
|                 } |         uint64_t Completed() const { return completed_;} | ||||||
|             }; |         void Complete() { completed_ = OpenWifi::Now(); } | ||||||
|  |  | ||||||
|             struct Status { |  | ||||||
|                 Types::UUID_t   UUID; |  | ||||||
|                 uint64_t        Start = 0 ; |  | ||||||
|                 uint64_t        Progress = 0 ; |  | ||||||
|                 uint64_t        Completed = 0 ; |  | ||||||
|                 std::string     CurrentDisplay; |  | ||||||
|             }; |  | ||||||
|  |  | ||||||
|             struct Result { |  | ||||||
|                 int         Error=0; |  | ||||||
|                 std::string Reason; |  | ||||||
|             }; |  | ||||||
|  |  | ||||||
|             typedef std::vector<Parameter>       Parameters; |  | ||||||
|             typedef std::vector<Parameters>      ParametersVec; |  | ||||||
|             typedef std::function<bool(const Parameters &Parameters, Result &Result, bool &Retry)>  WorkerFunction; |  | ||||||
|             typedef std::vector<Status>          Statuses; |  | ||||||
|  |  | ||||||
|             Job(std::string Title, |  | ||||||
|                          std::string Description, |  | ||||||
|                          std::string RegisteredName, |  | ||||||
|                          ParametersVec Parameters, |  | ||||||
|                          bool Parallel=true) : |  | ||||||
|                     Title_(std::move(Title)), |  | ||||||
|                     Description_(std::move(Description)), |  | ||||||
|                     RegisteredName_(std::move(RegisteredName)), |  | ||||||
|                     Parameters_(std::move(Parameters)), |  | ||||||
|                     Parallel_(Parallel) |  | ||||||
|                 { |  | ||||||
|                     UUID_ = MicroService::instance().CreateUUID(); |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|             [[nodiscard]] inline const Types::UUID_t & ID() const { return UUID_; } |  | ||||||
|  |  | ||||||
|     private: |     private: | ||||||
|             Types::UUID_t       UUID_; |         std::string                 jobId_; | ||||||
|             std::string         Title_; |         std::string                 name_; | ||||||
|             std::string         Description_; |         std::vector<std::string>    parameters_; | ||||||
|             std::string         RegisteredName_; |         uint64_t                    when_=0; | ||||||
|             ParametersVec       Parameters_; |         SecurityObjects::UserInfo   userinfo_; | ||||||
|             bool                Parallel_=true; |         Poco::Logger                & Logger_; | ||||||
|  |         uint64_t                    started_=0; | ||||||
|  |         uint64_t                    completed_=0; | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     class JobRegistry { |  | ||||||
|         public: |  | ||||||
|             static auto instance() { |  | ||||||
|                 static auto instance_ = new JobRegistry; |  | ||||||
|                 return instance_; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             inline void RegisterJobType( const std::string & JobType, Job::WorkerFunction Function) { |  | ||||||
|                     JobTypes_[JobType] = std::move(Function); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             inline bool Execute(const std::string &JobType, const Job::Parameters & Params, Job::Result &Result, bool & Retry) { |  | ||||||
|                 auto Hint = JobTypes_.find(JobType); |  | ||||||
|                 if(Hint != end(JobTypes_)) { |  | ||||||
|                     Hint->second(Params, Result, Retry); |  | ||||||
|                     return true; |  | ||||||
|                 } |  | ||||||
|                 return false; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|         private: |  | ||||||
|             std::map<std::string,Job::WorkerFunction>  JobTypes_; |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     inline auto JobRegistry() { return JobRegistry::instance(); } |  | ||||||
|  |  | ||||||
|     class JobController : public SubSystemServer, Poco::Runnable { |     class JobController : public SubSystemServer, Poco::Runnable { | ||||||
|         public: |         public: | ||||||
|             static auto instance() { |             static auto instance() { | ||||||
| @@ -114,11 +58,16 @@ namespace OpenWifi { | |||||||
|             void run() override; |             void run() override; | ||||||
|             inline void wakeup() { Thr_.wakeUp(); } |             inline void wakeup() { Thr_.wakeUp(); } | ||||||
|  |  | ||||||
|             bool JobList(Job::Statuses & Statuses); |             void AddJob( Job* newJob ) { | ||||||
|  |                 std::lock_guard G(Mutex_); | ||||||
|  |                 jobs_.push_back(newJob); | ||||||
|  |             } | ||||||
|  |  | ||||||
|         private: |         private: | ||||||
|             Poco::Thread                        Thr_; |             Poco::Thread                        Thr_; | ||||||
|             std::atomic_bool                    Running_=false; |             std::atomic_bool                    Running_=false; | ||||||
|  |             std::list<Job *>                    jobs_; | ||||||
|  |             Poco::ThreadPool                    Pool_; | ||||||
|  |  | ||||||
|         JobController() noexcept: |         JobController() noexcept: | ||||||
|             SubSystemServer("JobController", "JOB-SVR", "job") |             SubSystemServer("JobController", "JOB-SVR", "job") | ||||||
|   | |||||||
							
								
								
									
										5
									
								
								src/Kafka_ProvUpdater.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/Kafka_ProvUpdater.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2022-04-01. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #include "Kafka_ProvUpdater.h" | ||||||
							
								
								
									
										48
									
								
								src/Kafka_ProvUpdater.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/Kafka_ProvUpdater.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,48 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2022-04-01. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "framework/MicroService.h" | ||||||
|  | #include "RESTObjects/RESTAPI_ProvObjects.h" | ||||||
|  |  | ||||||
|  | namespace OpenWifi { | ||||||
|  |  | ||||||
|  |     enum ProvisioningOperation { | ||||||
|  |         creation=0, modification, removal | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     template <typename ObjectType> inline bool UpdateKafkaProvisioningObject( ProvisioningOperation op, const ObjectType & obj) { | ||||||
|  |         static std::vector<std::string> Ops{ "creation", "modification", "removal" }; | ||||||
|  |  | ||||||
|  |         std::string OT{"object"}; | ||||||
|  |         if constexpr(std::is_same_v<ObjectType,ProvObjects::Venue>) { | ||||||
|  |             OT = "Venue"; | ||||||
|  |         } | ||||||
|  |         if constexpr(std::is_same_v<ObjectType,ProvObjects::Entity>) { | ||||||
|  |             OT = "Entity"; | ||||||
|  |         } | ||||||
|  |         if constexpr(std::is_same_v<ObjectType,ProvObjects::InventoryTag>) { | ||||||
|  |             OT = "InventoryTag"; | ||||||
|  |         } | ||||||
|  |         if constexpr(std::is_same_v<ObjectType,ProvObjects::Contact>) { | ||||||
|  |             OT = "Contact"; | ||||||
|  |         } | ||||||
|  |         if constexpr(std::is_same_v<ObjectType,ProvObjects::Location>) { | ||||||
|  |             OT = "Location"; | ||||||
|  |         } | ||||||
|  |         if constexpr(std::is_same_v<ObjectType,ProvObjects::DeviceConfiguration>) { | ||||||
|  |             OT = "DeviceConfiguration"; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         Poco::JSON::Object  Payload; | ||||||
|  |         obj.to_json(Payload); | ||||||
|  |         Payload.set("ObjectType",OT); | ||||||
|  |         std::ostringstream OS; | ||||||
|  |         Payload.stringify(OS); | ||||||
|  |         KafkaManager()->PostMessage(KafkaTopics::PROVISIONING_CHANGE, Ops[op] , OS.str()); | ||||||
|  |  | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										167
									
								
								src/ProvWebSocketClient.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										167
									
								
								src/ProvWebSocketClient.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,167 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2022-04-28. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #include "ProvWebSocketClient.h" | ||||||
|  |  | ||||||
|  | #include "StorageService.h" | ||||||
|  | #include "SerialNumberCache.h" | ||||||
|  | #include "sdks/SDK_sec.h" | ||||||
|  |  | ||||||
|  | namespace OpenWifi { | ||||||
|  |  | ||||||
|  |     ProvWebSocketClient::ProvWebSocketClient(Poco::Logger &Logger) : | ||||||
|  |             Logger_(Logger){ | ||||||
|  |         WebSocketClientServer()->SetProcessor(this); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     ProvWebSocketClient::~ProvWebSocketClient() { | ||||||
|  |         WebSocketClientServer()->SetProcessor(nullptr); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void ProvWebSocketClient::ws_command_serial_number_search(const Poco::JSON::Object::Ptr &O, | ||||||
|  |                                                               bool &Done, std::string &Answer) { | ||||||
|  |         Done = false; | ||||||
|  |         auto Prefix = O->get("serial_prefix").toString(); | ||||||
|  |         Poco::toLowerInPlace(Prefix); | ||||||
|  |         Logger().information(Poco::format("serial_number_search: %s", Prefix)); | ||||||
|  |         if (!Prefix.empty() && Prefix.length() < 13) { | ||||||
|  |             std::vector<uint64_t> Numbers; | ||||||
|  |             SerialNumberCache()->FindNumbers(Prefix, 50, Numbers); | ||||||
|  |             Poco::JSON::Array Arr; | ||||||
|  |             for (const auto &i : Numbers) | ||||||
|  |                 Arr.add(Utils::int_to_hex(i)); | ||||||
|  |             Poco::JSON::Object RetObj; | ||||||
|  |             RetObj.set("serialNumbers", Arr); | ||||||
|  |             std::ostringstream SS; | ||||||
|  |             Poco::JSON::Stringifier::stringify(RetObj, SS); | ||||||
|  |             Answer = SS.str(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void ProvWebSocketClient::ws_command_address_completion(const Poco::JSON::Object::Ptr &O, bool &Done, std::string &Answer) { | ||||||
|  |         Done = false; | ||||||
|  |         auto Address = O->get("address").toString(); | ||||||
|  |         Answer = GoogleGeoCodeCall(Address); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void ProvWebSocketClient::ws_command_exit([[maybe_unused]] const Poco::JSON::Object::Ptr &O, bool &Done, std::string &Answer) { | ||||||
|  |         Done = true; | ||||||
|  |         Answer = R"lit({ "closing" : "Goodbye! Aurevoir! Hasta la vista!" })lit"; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void ProvWebSocketClient::ws_command_invalid([[maybe_unused]] const Poco::JSON::Object::Ptr &O, bool &Done, std::string &Answer) { | ||||||
|  |         Done = false; | ||||||
|  |         Answer = std::string{R"lit({ "error" : "invalid command" })lit"}; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void ProvWebSocketClient::ws_command_subuser_search( const Poco::JSON::Object::Ptr &O, bool &Done, std::string &Answer) { | ||||||
|  |         Done = false; | ||||||
|  |         auto operatorId = O->get("operatorId").toString(); | ||||||
|  |         std::string nameSearch, emailSearch; | ||||||
|  |         OpenWifi::RESTAPIHandler::AssignIfPresent(O,"nameSearch",nameSearch); | ||||||
|  |         OpenWifi::RESTAPIHandler::AssignIfPresent(O,"emailSearch",emailSearch); | ||||||
|  |         SecurityObjects::UserInfoList   Users; | ||||||
|  |         SDK::Sec::Subscriber::Search(nullptr,operatorId,nameSearch,emailSearch,Users); | ||||||
|  |  | ||||||
|  |         Poco::JSON::Array   Arr; | ||||||
|  |         for(const auto &i:Users.users) { | ||||||
|  |             Poco::JSON::Object  OO; | ||||||
|  |             OO.set("name", i.name); | ||||||
|  |             OO.set("email", i.email); | ||||||
|  |             OO.set("id", i.id); | ||||||
|  |             i.to_json(OO); | ||||||
|  |             Arr.add(OO); | ||||||
|  |         } | ||||||
|  |         Poco::JSON::Object  ObjAnswer; | ||||||
|  |         ObjAnswer.set("users", Arr); | ||||||
|  |         std::ostringstream SS; | ||||||
|  |         Poco::JSON::Stringifier::stringify(ObjAnswer, SS); | ||||||
|  |         Answer = SS.str(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void ProvWebSocketClient::ws_command_subdevice_search( const Poco::JSON::Object::Ptr &O, bool &Done, std::string &Answer) { | ||||||
|  |         Done = false; | ||||||
|  |         auto operatorId = O->get("operatorId").toString(); | ||||||
|  |         auto Prefix = O->get("serial_prefix").toString(); | ||||||
|  |         Poco::toLowerInPlace(Prefix); | ||||||
|  |         std::string Query; | ||||||
|  |  | ||||||
|  |         if(Prefix[0]=='*') { | ||||||
|  |             Query = fmt::format(" operatorId='{}' and (right(serialNumber,{})='{}' or right(realMacAddress,{})='{}' ) ", | ||||||
|  |                                 operatorId, Prefix.size()-1, Prefix.substr(1), Prefix.size()-1, Prefix.substr(1)); | ||||||
|  |         } else { | ||||||
|  |             Query = fmt::format(" operatorId='{}' and (left(serialNumber,{})='{}'  or left(realMacAddress,{})='{}' ) ", | ||||||
|  |                                 operatorId, Prefix.size(), Prefix, Prefix.size(), Prefix); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         std::vector<ProvObjects::SubscriberDevice>  SubDevices; | ||||||
|  |  | ||||||
|  |         StorageService()->SubscriberDeviceDB().GetRecords(0,200,SubDevices,Query); | ||||||
|  |         Poco::JSON::Array   Arr; | ||||||
|  |         for(const auto &i:SubDevices) { | ||||||
|  |             Arr.add(i.serialNumber); | ||||||
|  |         } | ||||||
|  |         Poco::JSON::Object  RetObj; | ||||||
|  |         RetObj.set("serialNumbers", Arr); | ||||||
|  |         std::ostringstream SS; | ||||||
|  |         Poco::JSON::Stringifier::stringify(RetObj, SS); | ||||||
|  |         Answer = SS.str(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void ProvWebSocketClient::Processor(const Poco::JSON::Object::Ptr &O, std::string &Result, bool &Done ) { | ||||||
|  |         try { | ||||||
|  |             if (O->has("command") && O->has("id")) { | ||||||
|  |                 auto id = (uint64_t) O->get("id"); | ||||||
|  |                 std::string Answer; | ||||||
|  |                 auto Command = O->get("command").toString(); | ||||||
|  |                 if (Command == "serial_number_search" && O->has("serial_prefix")) { | ||||||
|  |                     ws_command_serial_number_search(O,Done,Answer); | ||||||
|  |                 } else if (WebSocketClientServer()->GeoCodeEnabled() && Command == "address_completion" && O->has("address")) { | ||||||
|  |                     ws_command_address_completion(O,Done,Answer); | ||||||
|  |                 } else if (WebSocketClientServer()->GeoCodeEnabled() && Command == "subuser_search" && O->has("operatorId")) { | ||||||
|  |                     ws_command_subuser_search(O,Done,Answer); | ||||||
|  |                 } else if (WebSocketClientServer()->GeoCodeEnabled() && Command == "subdevice_search" && O->has("operatorId") && O->has("serial_prefix")) { | ||||||
|  |                     ws_command_subdevice_search(O,Done,Answer); | ||||||
|  |                 } else if (Command=="exit") { | ||||||
|  |                     ws_command_exit(O,Done,Answer); | ||||||
|  |                 } else { | ||||||
|  |                     ws_command_invalid(O,Done,Answer); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 Result = fmt::format("{{ \"command_response_id\" : {} , \"response\" : {}  }}" , id, Answer); | ||||||
|  |             } | ||||||
|  |         } catch (const Poco::Exception &E) { | ||||||
|  |             Logger().log(E); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     std::string ProvWebSocketClient::GoogleGeoCodeCall(const std::string &A) { | ||||||
|  |         try { | ||||||
|  |             std::string URI = { "https://maps.googleapis.com/maps/api/geocode/json"}; | ||||||
|  |             Poco::URI   uri(URI); | ||||||
|  |  | ||||||
|  |             uri.addQueryParameter("address",A); | ||||||
|  |             uri.addQueryParameter("key", WebSocketClientServer()->GoogleApiKey()); | ||||||
|  |  | ||||||
|  |             Poco::Net::HTTPSClientSession session(uri.getHost(), uri.getPort()); | ||||||
|  |             Poco::Net::HTTPRequest req(Poco::Net::HTTPRequest::HTTP_GET, uri.getPathAndQuery(), Poco::Net::HTTPMessage::HTTP_1_1); | ||||||
|  |             session.sendRequest(req); | ||||||
|  |             Poco::Net::HTTPResponse res; | ||||||
|  |             std::istream& rs = session.receiveResponse(res); | ||||||
|  |             if(res.getStatus()==Poco::Net::HTTPResponse::HTTP_OK) { | ||||||
|  |                 std::ostringstream os; | ||||||
|  |                 Poco::StreamCopier::copyStream(rs,os); | ||||||
|  |                 return os.str(); | ||||||
|  |             } else { | ||||||
|  |                 std::ostringstream os; | ||||||
|  |                 Poco::StreamCopier::copyStream(rs,os); | ||||||
|  |                 return R"lit({ "error: )lit" + os.str() + R"lit( })lit"; | ||||||
|  |             } | ||||||
|  |         } catch(...) { | ||||||
|  |  | ||||||
|  |         } | ||||||
|  |         return "{ \"error\" : \"No call made\" }"; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										28
									
								
								src/ProvWebSocketClient.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/ProvWebSocketClient.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2022-04-28. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "framework/MicroService.h" | ||||||
|  |  | ||||||
|  | namespace OpenWifi { | ||||||
|  |  | ||||||
|  |     class ProvWebSocketClient : public WebSocketClientProcessor { | ||||||
|  |     public: | ||||||
|  |         explicit ProvWebSocketClient(Poco::Logger &Logger); | ||||||
|  |         virtual ~ProvWebSocketClient(); | ||||||
|  |         virtual void Processor(const Poco::JSON::Object::Ptr &O, std::string &Answer, bool &Done ); | ||||||
|  |         void ws_command_serial_number_search( const Poco::JSON::Object::Ptr &O, bool &Done, std::string &Answer); | ||||||
|  |         void ws_command_address_completion( const Poco::JSON::Object::Ptr &O, bool &Done, std::string &Answer); | ||||||
|  |         void ws_command_exit( const Poco::JSON::Object::Ptr &O, bool &Done, std::string &Answer); | ||||||
|  |         void ws_command_invalid( const Poco::JSON::Object::Ptr &O, bool &Done, std::string &Answer); | ||||||
|  |         void ws_command_subuser_search( const Poco::JSON::Object::Ptr &O, bool &Done, std::string &Answer); | ||||||
|  |         void ws_command_subdevice_search( const Poco::JSON::Object::Ptr &O, bool &Done, std::string &Answer); | ||||||
|  |         std::string GoogleGeoCodeCall(const std::string &A); | ||||||
|  |     private: | ||||||
|  |         Poco::Logger & Logger_; | ||||||
|  |         inline Poco::Logger & Logger() { return Logger_; } | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										21
									
								
								src/RESTAPI/RESTAPI_asset_server.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/RESTAPI/RESTAPI_asset_server.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2021-07-10. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #include "RESTAPI_asset_server.h" | ||||||
|  | #include "Poco/File.h" | ||||||
|  | #include "framework/ow_constants.h" | ||||||
|  | #include "Daemon.h" | ||||||
|  |  | ||||||
|  | namespace OpenWifi { | ||||||
|  |     void RESTAPI_asset_server::DoGet() { | ||||||
|  |         Poco::File  AssetFile; | ||||||
|  |  | ||||||
|  |         std::string AssetName = GetBinding(RESTAPI::Protocol::ID, ""); | ||||||
|  |         AssetFile = Daemon()->AssetDir() + "/" + AssetName; | ||||||
|  |         if(!AssetFile.isFile()) { | ||||||
|  |             return NotFound(); | ||||||
|  |         } | ||||||
|  |         SendFile(AssetFile); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										31
									
								
								src/RESTAPI/RESTAPI_asset_server.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/RESTAPI/RESTAPI_asset_server.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2021-07-10. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "../framework/MicroService.h" | ||||||
|  |  | ||||||
|  | namespace OpenWifi { | ||||||
|  |     class RESTAPI_asset_server : public RESTAPIHandler { | ||||||
|  |     public: | ||||||
|  |         RESTAPI_asset_server(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, false) {} | ||||||
|  |         static auto PathName() { return std::list<std::string>{"/wwwassets/{id}"}; }; | ||||||
|  |         void DoGet() final; | ||||||
|  |         void DoPost() final {}; | ||||||
|  |         void DoDelete() final {}; | ||||||
|  |         void DoPut() final {}; | ||||||
|  |  | ||||||
|  |     private: | ||||||
|  |  | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  |  | ||||||
| @@ -11,9 +11,9 @@ | |||||||
| #include "RESTAPI_configurations_handler.h" | #include "RESTAPI_configurations_handler.h" | ||||||
| #include "RESTObjects/RESTAPI_ProvObjects.h" | #include "RESTObjects/RESTAPI_ProvObjects.h" | ||||||
| #include "StorageService.h" | #include "StorageService.h" | ||||||
| #include "framework/RESTAPI_errors.h" |  | ||||||
| #include "framework/ConfigurationValidator.h" | #include "framework/ConfigurationValidator.h" | ||||||
| #include "RESTAPI/RESTAPI_db_helpers.h" | #include "RESTAPI/RESTAPI_db_helpers.h" | ||||||
|  | #include "DeviceTypeCache.h" | ||||||
|  |  | ||||||
| namespace OpenWifi{ | namespace OpenWifi{ | ||||||
|  |  | ||||||
| @@ -65,40 +65,15 @@ namespace OpenWifi{ | |||||||
|             return BadRequest(RESTAPI::Errors::StillInUse); |             return BadRequest(RESTAPI::Errors::StillInUse); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(DB_.DeleteRecord("id", UUID)) { |         DB_.DeleteRecord("id", UUID); | ||||||
|  |         MoveUsage(StorageService()->PolicyDB(),DB_,Existing.managementPolicy,"",Existing.info.id); | ||||||
|  |         RemoveMembership(StorageService()->VenueDB(),&ProvObjects::Venue::configurations,Existing.venue,Existing.info.id); | ||||||
|  |         RemoveMembership(StorageService()->EntityDB(),&ProvObjects::Entity::configurations,Existing.entity,Existing.info.id); | ||||||
|  |         for(const auto &i:Existing.variables) | ||||||
|  |             RemoveMembership(StorageService()->VariablesDB(),&ProvObjects::VariableBlock::configurations,i,Existing.info.id); | ||||||
|  |  | ||||||
|         return OK(); |         return OK(); | ||||||
|     } |     } | ||||||
|         InternalError(RESTAPI::Errors::CouldNotBeDeleted); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     bool RESTAPI_configurations_handler::ValidateConfigBlock(const ProvObjects::DeviceConfiguration &Config, std::string & Error) { |  | ||||||
|         static const std::vector<std::string> SectionNames{ "globals", "interfaces", "metrics", "radios", "services", "unit" }; |  | ||||||
|  |  | ||||||
|         for(const auto &i:Config.configuration) { |  | ||||||
|             Poco::JSON::Parser  P; |  | ||||||
|             if(i.name.empty()) { |  | ||||||
|                 BadRequest(RESTAPI::Errors::NameMustBeSet); |  | ||||||
|                 return false; |  | ||||||
|             } |  | ||||||
|             auto Blocks = P.parse(i.configuration).extract<Poco::JSON::Object::Ptr>(); |  | ||||||
|             auto N = Blocks->getNames(); |  | ||||||
|             for(const auto &j:N) { |  | ||||||
|                 if(std::find(SectionNames.cbegin(),SectionNames.cend(),j)==SectionNames.cend()) { |  | ||||||
|                     BadRequest(RESTAPI::Errors::ConfigBlockInvalid); |  | ||||||
|                     return false; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             if(ValidateUCentralConfiguration(i.configuration, Error)) { |  | ||||||
|                 /* nothing to do */ ; |  | ||||||
|             } else { |  | ||||||
|                 // std::cout << "Block: " << std::endl << ">>>" << std::endl << i.configuration << std::endl << ">>> REJECTED" << std::endl; |  | ||||||
|                 return false; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|         } |  | ||||||
|         return true; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void RESTAPI_configurations_handler::DoPost() { |     void RESTAPI_configurations_handler::DoPost() { | ||||||
|         auto UUID = GetBinding("uuid",""); |         auto UUID = GetBinding("uuid",""); | ||||||
| @@ -106,13 +81,13 @@ namespace OpenWifi{ | |||||||
|             return BadRequest(RESTAPI::Errors::MissingUUID); |             return BadRequest(RESTAPI::Errors::MissingUUID); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         const auto & RawObject = ParsedBody_; | ||||||
|         std::string Arg; |         std::string Arg; | ||||||
|         if(HasParameter("validateOnly",Arg) && Arg=="true") { |         if(HasParameter("validateOnly",Arg) && Arg=="true") { | ||||||
|             auto Body = ParseStream(); |             if(!RawObject->has("configuration")) { | ||||||
|             if(!Body->has("configuration")) { |                 return BadRequest(RESTAPI::Errors::MustHaveConfigElement); | ||||||
|                 return BadRequest("Must have 'configuration' element."); |  | ||||||
|             } |             } | ||||||
|             auto Config=Body->get("configuration").toString(); |             auto Config=RawObject->get("configuration").toString(); | ||||||
|             Poco::JSON::Object  Answer; |             Poco::JSON::Object  Answer; | ||||||
|             std::string Error; |             std::string Error; | ||||||
|             auto Res = ValidateUCentralConfiguration(Config,Error); |             auto Res = ValidateUCentralConfiguration(Config,Error); | ||||||
| @@ -121,37 +96,50 @@ namespace OpenWifi{ | |||||||
|             return ReturnObject(Answer); |             return ReturnObject(Answer); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         ProvObjects::DeviceConfiguration C; |         ProvObjects::DeviceConfiguration NewObject; | ||||||
|         Poco::JSON::Object::Ptr Obj = ParseStream(); |         if (!NewObject.from_json(RawObject)) { | ||||||
|         if (!C.from_json(Obj)) { |  | ||||||
|             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); |             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(!ProvObjects::CreateObjectInfo(Obj,UserInfo_.userinfo,C.info)) { |         if((RawObject->has("deviceRules") && !ValidDeviceRules(NewObject.deviceRules,*this))) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(!ProvObjects::CreateObjectInfo(RawObject,UserInfo_.userinfo,NewObject.info)) { | ||||||
|             return BadRequest(RESTAPI::Errors::NameMustBeSet); |             return BadRequest(RESTAPI::Errors::NameMustBeSet); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(!C.managementPolicy.empty() && !StorageService()->PolicyDB().Exists("id",C.managementPolicy)) { |         if(!NewObject.entity.empty() && !StorageService()->EntityDB().Exists("id",NewObject.entity)) { | ||||||
|             return BadRequest(RESTAPI::Errors::UnknownId); |             return BadRequest(RESTAPI::Errors::EntityMustExist); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         C.inUse.clear(); |         if(!NewObject.venue.empty() && !StorageService()->VenueDB().Exists("id",NewObject.venue)) { | ||||||
|         if(C.deviceTypes.empty() || !StorageService()->AreAcceptableDeviceTypes(C.deviceTypes, true)) { |             return BadRequest(RESTAPI::Errors::VenueMustExist); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(!NewObject.managementPolicy.empty() && !StorageService()->PolicyDB().Exists("id",NewObject.managementPolicy)) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::UnknownManagementPolicyUUID); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         NewObject.inUse.clear(); | ||||||
|  |         if(NewObject.deviceTypes.empty() || !DeviceTypeCache()->AreAcceptableDeviceTypes(NewObject.deviceTypes, true)) { | ||||||
|             return BadRequest(RESTAPI::Errors::InvalidDeviceTypes); |             return BadRequest(RESTAPI::Errors::InvalidDeviceTypes); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         std::string Error; |         RESTAPI::Errors::msg Error; | ||||||
|         if(!ValidateConfigBlock(C,Error)) { |         if(!ValidateConfigBlock(NewObject,Error)) { | ||||||
|             return BadRequest(RESTAPI::Errors::ConfigBlockInvalid + ", error: " + Error); |             return BadRequest(Error); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(DB_.CreateRecord(C)) { |         if(DB_.CreateRecord(NewObject)) { | ||||||
|             DB_.GetRecord("id", C.info.id, C); |             MoveUsage(StorageService()->PolicyDB(),DB_,"",NewObject.managementPolicy,NewObject.info.id); | ||||||
|             if(!C.managementPolicy.empty()) |             AddMembership(StorageService()->VenueDB(),&ProvObjects::Venue::configurations,NewObject.venue, NewObject.info.id); | ||||||
|                 StorageService()->PolicyDB().AddInUse("id",C.managementPolicy,DB_.Prefix(), C.info.id); |             AddMembership(StorageService()->EntityDB(),&ProvObjects::Entity::configurations,NewObject.entity, NewObject.info.id); | ||||||
|  |  | ||||||
|  |             ConfigurationDB::RecordName AddedRecord; | ||||||
|  |             DB_.GetRecord("id", NewObject.info.id, AddedRecord); | ||||||
|             Poco::JSON::Object  Answer; |             Poco::JSON::Object  Answer; | ||||||
|             C.to_json(Answer); |             AddedRecord.to_json(Answer); | ||||||
|             return ReturnObject(Answer); |             return ReturnObject(Answer); | ||||||
|         } |         } | ||||||
|         InternalError(RESTAPI::Errors::RecordNotCreated); |         InternalError(RESTAPI::Errors::RecordNotCreated); | ||||||
| @@ -164,57 +152,72 @@ namespace OpenWifi{ | |||||||
|             return NotFound(); |             return NotFound(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         ProvObjects::DeviceConfiguration    NewConfig; |         ProvObjects::DeviceConfiguration    NewObject; | ||||||
|         auto ParsedObj = ParseStream(); |         const auto & RawObject = ParsedBody_; | ||||||
|         if (!NewConfig.from_json(ParsedObj)) { |         if (!NewObject.from_json(RawObject)) { | ||||||
|             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); |             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(!UpdateObjectInfo(ParsedObj, UserInfo_.userinfo, Existing.info)) { |         if((RawObject->has("deviceRules") && !ValidDeviceRules(NewObject.deviceRules,*this))) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(!UpdateObjectInfo(RawObject, UserInfo_.userinfo, Existing.info)) { | ||||||
|             return BadRequest(RESTAPI::Errors::NameMustBeSet); |             return BadRequest(RESTAPI::Errors::NameMustBeSet); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(!NewConfig.deviceTypes.empty() && !StorageService()->AreAcceptableDeviceTypes(NewConfig.deviceTypes, true)) { |         if(!NewObject.deviceTypes.empty() && !DeviceTypeCache()->AreAcceptableDeviceTypes(NewObject.deviceTypes, true)) { | ||||||
|             return BadRequest(RESTAPI::Errors::InvalidDeviceTypes); |             return BadRequest(RESTAPI::Errors::InvalidDeviceTypes); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         std::string Error; |         if(!NewObject.deviceTypes.empty()) | ||||||
|         if(!ValidateConfigBlock( NewConfig,Error)) { |             Existing.deviceTypes = NewObject.deviceTypes; | ||||||
|             return BadRequest(RESTAPI::Errors::ConfigBlockInvalid + ", error: " + Error); |  | ||||||
|  |         RESTAPI::Errors::msg Error; | ||||||
|  |         if(!ValidateConfigBlock( NewObject,Error)) { | ||||||
|  |             return BadRequest(Error); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(ParsedObj->has("configuration")) { |         if(RawObject->has("configuration")) { | ||||||
|             Existing.configuration = NewConfig.configuration; |             Existing.configuration = NewObject.configuration; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         std::string MovePolicy; |         std::string FromPolicy, ToPolicy; | ||||||
|         bool        MovingPolicy=false; |         if(!CreateMove(RawObject,"managementPolicy",&ConfigurationDB::RecordName::managementPolicy, Existing, FromPolicy, ToPolicy, StorageService()->PolicyDB())) | ||||||
|         if(AssignIfPresent(ParsedObj,"managementPolicy",MovePolicy)) { |             return BadRequest(RESTAPI::Errors::EntityMustExist); | ||||||
|             if(!MovePolicy.empty() && !StorageService()->PolicyDB().Exists("id",NewConfig.managementPolicy)) { |  | ||||||
|                 return BadRequest(RESTAPI::Errors::UnknownManagementPolicyUUID); |         std::string FromEntity, ToEntity; | ||||||
|  |         if(!CreateMove(RawObject,"entity",&ConfigurationDB::RecordName::entity, Existing, FromEntity, ToEntity, StorageService()->EntityDB())) | ||||||
|  |             return BadRequest(RESTAPI::Errors::EntityMustExist); | ||||||
|  |  | ||||||
|  |         std::string FromVenue, ToVenue; | ||||||
|  |         if(!CreateMove(RawObject,"venue",&ConfigurationDB::RecordName::venue, Existing, FromVenue, ToVenue, StorageService()->VenueDB())) | ||||||
|  |             return BadRequest(RESTAPI::Errors::VenueMustExist); | ||||||
|  |  | ||||||
|  |         Types::UUIDvec_t FromVariables, ToVariables; | ||||||
|  |         if(RawObject->has("variables")) { | ||||||
|  |             for(const auto &i:NewObject.variables) { | ||||||
|  |                 if(!i.empty() && !StorageService()->VariablesDB().Exists("id",i)) { | ||||||
|  |                     return BadRequest(RESTAPI::Errors::VariableMustExist); | ||||||
|                 } |                 } | ||||||
|             MovingPolicy = NewConfig.managementPolicy != Existing.managementPolicy; |             } | ||||||
|  |             for(const auto &i:Existing.variables) | ||||||
|  |                 FromVariables.emplace_back(i); | ||||||
|  |             for(const auto &i:NewObject.variables) | ||||||
|  |                 ToVariables.emplace_back(i); | ||||||
|  |             FromVariables = Existing.variables; | ||||||
|  |             ToVariables = NewObject.variables; | ||||||
|  |             Existing.variables = ToVariables; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(!NewConfig.deviceTypes.empty()) |         if(RawObject->has("deviceRules")) | ||||||
|             Existing.deviceTypes = NewConfig.deviceTypes; |             Existing.deviceRules = NewObject.deviceRules; | ||||||
|  |  | ||||||
|         AssignIfPresent(ParsedObj, "rrm", Existing.rrm); |  | ||||||
|         AssignIfPresent(ParsedObj,"firmwareUpgrade",Existing.firmwareUpgrade); |  | ||||||
|         AssignIfPresent(ParsedObj,"firmwareRCOnly", Existing.firmwareRCOnly); |  | ||||||
|  |  | ||||||
|         if(!NewConfig.variables.empty()) |  | ||||||
|             Existing.variables = NewConfig.variables; |  | ||||||
|  |  | ||||||
|         if(DB_.UpdateRecord("id",UUID,Existing)) { |         if(DB_.UpdateRecord("id",UUID,Existing)) { | ||||||
|             if(MovingPolicy) { |             ManageMembership(StorageService()->VariablesDB(),&ProvObjects::VariableBlock::configurations, FromVariables, ToVariables, Existing.info.id); | ||||||
|                 if(!Existing.managementPolicy.empty()) |             ManageMembership(StorageService()->VenueDB(), &ProvObjects::Venue::configurations, FromVenue, ToVenue, Existing.info.id); | ||||||
|                     StorageService()->PolicyDB().DeleteInUse("id",Existing.managementPolicy,DB_.Prefix(),Existing.info.id); |             ManageMembership(StorageService()->EntityDB(), &ProvObjects::Entity::configurations, FromEntity, ToEntity, Existing.info.id); | ||||||
|                 if(!MovePolicy.empty()) |             MoveUsage(StorageService()->PolicyDB(),DB_,FromPolicy,ToPolicy,Existing.info.id); | ||||||
|                     StorageService()->PolicyDB().AddInUse("id",MovePolicy,DB_.Prefix(),Existing.info.id); |  | ||||||
|                 Existing.managementPolicy = MovePolicy; |  | ||||||
|             } |  | ||||||
|             DB_.UpdateRecord("id", UUID, Existing); |  | ||||||
|  |  | ||||||
|             ProvObjects::DeviceConfiguration    D; |             ProvObjects::DeviceConfiguration    D; | ||||||
|             DB_.GetRecord("id",UUID,D); |             DB_.GetRecord("id",UUID,D); | ||||||
|   | |||||||
| @@ -22,17 +22,13 @@ namespace OpenWifi { | |||||||
|             Poco::Net::HTTPRequest::HTTP_OPTIONS}, |             Poco::Net::HTTPRequest::HTTP_OPTIONS}, | ||||||
|             Server, |             Server, | ||||||
|             TransactionId, |             TransactionId, | ||||||
|             Internal), |             Internal){} | ||||||
|             DB_(StorageService()->ConfigurationDB()){} |         static auto PathName() { return std::list<std::string>{"/api/v1/configuration/{uuid}"}; }; | ||||||
|  |     private: | ||||||
|         static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/configurations/{uuid}"}; }; |         ConfigurationDB     &DB_=StorageService()->ConfigurationDB(); | ||||||
|  |  | ||||||
|         void DoGet(); |         void DoGet(); | ||||||
|         void DoPost(); |         void DoPost(); | ||||||
|         void DoPut(); |         void DoPut(); | ||||||
|         void DoDelete(); |         void DoDelete(); | ||||||
|     private: |  | ||||||
|         bool ValidateConfigBlock(const ProvObjects::DeviceConfiguration &Config, std::string & Error); |  | ||||||
|         ConfigurationDB     &DB_; |  | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -10,17 +10,6 @@ | |||||||
|  |  | ||||||
| namespace OpenWifi{ | namespace OpenWifi{ | ||||||
|     void RESTAPI_configurations_list_handler::DoGet() { |     void RESTAPI_configurations_list_handler::DoGet() { | ||||||
|         if(!QB_.Select.empty()) { |         return ListHandler<ConfigurationDB>("configurations", DB_, *this); | ||||||
|             return ReturnRecordList<decltype(StorageService()->ConfigurationDB()), |  | ||||||
|                     ProvObjects::DeviceConfiguration>("configurations",StorageService()->ConfigurationDB(),*this ); |  | ||||||
|         } else if(QB_.CountOnly) { |  | ||||||
|             Poco::JSON::Object  Answer; |  | ||||||
|             auto C = StorageService()->ConfigurationDB().Count(); |  | ||||||
|             return ReturnCountOnly(C); |  | ||||||
|         } else { |  | ||||||
|             ProvObjects::DeviceConfigurationVec Configs; |  | ||||||
|             StorageService()->ConfigurationDB().GetRecords(QB_.Offset,QB_.Limit,Configs); |  | ||||||
|             return MakeJSONObjectArray("configurations", Configs, *this); |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -5,6 +5,7 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include "framework/MicroService.h" | #include "framework/MicroService.h" | ||||||
|  | #include "StorageService.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace OpenWifi { | ||||||
|  |  | ||||||
| @@ -17,10 +18,10 @@ namespace OpenWifi { | |||||||
|             Poco::Net::HTTPRequest::HTTP_OPTIONS}, |             Poco::Net::HTTPRequest::HTTP_OPTIONS}, | ||||||
|             Server, |             Server, | ||||||
|             TransactionId, |             TransactionId, | ||||||
|             Internal) {} |             Internal){} | ||||||
|  |         static auto PathName() { return std::list<std::string>{"/api/v1/configuration"}; }; | ||||||
|         static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/configurations"}; }; |     private: | ||||||
|  |         ConfigurationDB & DB_=StorageService()->ConfigurationDB(); | ||||||
|         void DoGet() final; |         void DoGet() final; | ||||||
|         void DoPost() final {}; |         void DoPost() final {}; | ||||||
|         void DoPut() final {}; |         void DoPut() final {}; | ||||||
|   | |||||||
| @@ -8,8 +8,7 @@ | |||||||
|  |  | ||||||
| #include "RESTAPI_contact_handler.h" | #include "RESTAPI_contact_handler.h" | ||||||
|  |  | ||||||
| #include "framework/RESTAPI_protocol.h" | #include "framework/ow_constants.h" | ||||||
| #include "framework/RESTAPI_errors.h" |  | ||||||
| #include "RESTObjects/RESTAPI_ProvObjects.h" | #include "RESTObjects/RESTAPI_ProvObjects.h" | ||||||
| #include "RESTAPI_db_helpers.h" | #include "RESTAPI_db_helpers.h" | ||||||
|  |  | ||||||
| @@ -67,13 +66,11 @@ namespace OpenWifi{ | |||||||
|             return BadRequest(RESTAPI::Errors::StillInUse); |             return BadRequest(RESTAPI::Errors::StillInUse); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(DB_.DeleteRecord("id",UUID)) { |         DB_.DeleteRecord("id",UUID); | ||||||
|             if(!Existing.entity.empty()) |         RemoveMembership(StorageService()->EntityDB(),&ProvObjects::Entity::contacts,Existing.entity,Existing.info.id); | ||||||
|                 StorageService()->EntityDB().DeleteLocation("id",Existing.entity,UUID); |         MoveUsage(StorageService()->PolicyDB(),DB_,Existing.info.id,"",Existing.info.id); | ||||||
|         return OK(); |         return OK(); | ||||||
|     } |     } | ||||||
|         InternalError(RESTAPI::Errors::CouldNotBeDeleted); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void RESTAPI_contact_handler::DoPost() { |     void RESTAPI_contact_handler::DoPost() { | ||||||
|         std::string UUID = GetBinding(RESTAPI::Protocol::UUID,""); |         std::string UUID = GetBinding(RESTAPI::Protocol::UUID,""); | ||||||
| @@ -82,7 +79,7 @@ namespace OpenWifi{ | |||||||
|             return BadRequest(RESTAPI::Errors::MissingUUID); |             return BadRequest(RESTAPI::Errors::MissingUUID); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         auto Obj = ParseStream(); |         const auto & Obj = ParsedBody_; | ||||||
|         ProvObjects::Contact NewObject; |         ProvObjects::Contact NewObject; | ||||||
|         if (!NewObject.from_json(Obj)) { |         if (!NewObject.from_json(Obj)) { | ||||||
|             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); |             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); | ||||||
| @@ -92,7 +89,7 @@ namespace OpenWifi{ | |||||||
|             return BadRequest(RESTAPI::Errors::NameMustBeSet); |             return BadRequest(RESTAPI::Errors::NameMustBeSet); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(NewObject.entity.empty() || !StorageService()->EntityDB().Exists("id",NewObject.entity)) { |         if(NewObject.entity.empty() && !StorageService()->EntityDB().Exists("id",NewObject.entity)) { | ||||||
|             return BadRequest(RESTAPI::Errors::EntityMustExist); |             return BadRequest(RESTAPI::Errors::EntityMustExist); | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -103,10 +100,8 @@ namespace OpenWifi{ | |||||||
|         NewObject.inUse.clear(); |         NewObject.inUse.clear(); | ||||||
|  |  | ||||||
|         if(DB_.CreateRecord(NewObject)) { |         if(DB_.CreateRecord(NewObject)) { | ||||||
|  |             AddMembership(StorageService()->EntityDB(),&ProvObjects::Entity::contacts,NewObject.entity,NewObject.info.id); | ||||||
|             StorageService()->EntityDB().AddContact("id",NewObject.entity,NewObject.info.id); |             MoveUsage(StorageService()->PolicyDB(),DB_,"",NewObject.managementPolicy,NewObject.info.id); | ||||||
|             if(!NewObject.managementPolicy.empty()) |  | ||||||
|                 StorageService()->PolicyDB().AddInUse("id",NewObject.managementPolicy,DB_.Prefix(),NewObject.info.id); |  | ||||||
|  |  | ||||||
|             ProvObjects::Contact    NewContact; |             ProvObjects::Contact    NewContact; | ||||||
|             StorageService()->ContactDB().GetRecord("id", NewObject.info.id, NewContact); |             StorageService()->ContactDB().GetRecord("id", NewObject.info.id, NewContact); | ||||||
| @@ -126,7 +121,7 @@ namespace OpenWifi{ | |||||||
|             return NotFound(); |             return NotFound(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         auto RawObject = ParseStream(); |         const auto & RawObject = ParsedBody_; | ||||||
|         ProvObjects::Contact NewObject; |         ProvObjects::Contact NewObject; | ||||||
|         if (!NewObject.from_json(RawObject)) { |         if (!NewObject.from_json(RawObject)) { | ||||||
|             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); |             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); | ||||||
| @@ -136,25 +131,13 @@ namespace OpenWifi{ | |||||||
|             return BadRequest(RESTAPI::Errors::NameMustBeSet); |             return BadRequest(RESTAPI::Errors::NameMustBeSet); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         std::string MoveToPolicy, MoveFromPolicy; |         std::string FromPolicy, ToPolicy; | ||||||
|         bool MovingPolicy=false; |         if(!CreateMove(RawObject,"managementPolicy",&ContactDB::RecordName::managementPolicy, Existing, FromPolicy, ToPolicy, StorageService()->PolicyDB())) | ||||||
|         if(AssignIfPresent(RawObject,"managementPolicy",MoveToPolicy)) { |             return BadRequest(RESTAPI::Errors::EntityMustExist); | ||||||
|             if(!MoveToPolicy.empty() && !StorageService()->PolicyDB().Exists("id",MoveToPolicy)) { |  | ||||||
|                 return BadRequest(RESTAPI::Errors::UnknownManagementPolicyUUID); |         std::string FromEntity, ToEntity; | ||||||
|             } |         if(!CreateMove(RawObject,"entity",&ContactDB::RecordName::entity, Existing, FromEntity, ToEntity, StorageService()->EntityDB())) | ||||||
|             MoveFromPolicy = Existing.managementPolicy; |  | ||||||
|             MovingPolicy = MoveToPolicy != Existing.managementPolicy; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         std::string MoveToEntity,MoveFromEntity; |  | ||||||
|         bool MovingEntity=false; |  | ||||||
|         if(AssignIfPresent(RawObject,"entity",MoveToEntity)) { |  | ||||||
|             if(!MoveToEntity.empty() && !StorageService()->EntityDB().Exists("id",MoveToEntity)) { |  | ||||||
|             return BadRequest(RESTAPI::Errors::EntityMustExist); |             return BadRequest(RESTAPI::Errors::EntityMustExist); | ||||||
|             } |  | ||||||
|             MoveFromEntity = Existing.entity; |  | ||||||
|             MovingEntity = MoveToEntity != Existing.entity ; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         AssignIfPresent(RawObject, "title", Existing.title); |         AssignIfPresent(RawObject, "title", Existing.title); | ||||||
|         AssignIfPresent(RawObject, "salutation", Existing.salutation); |         AssignIfPresent(RawObject, "salutation", Existing.salutation); | ||||||
| @@ -172,26 +155,9 @@ namespace OpenWifi{ | |||||||
|         if(RawObject->has("phones")) |         if(RawObject->has("phones")) | ||||||
|             Existing.phones = NewObject.phones; |             Existing.phones = NewObject.phones; | ||||||
|  |  | ||||||
|         Existing.entity = MoveToEntity; |  | ||||||
|         Existing.managementPolicy = MoveToPolicy; |  | ||||||
|  |  | ||||||
|         if(DB_.UpdateRecord("id", UUID, Existing)) { |         if(DB_.UpdateRecord("id", UUID, Existing)) { | ||||||
|  |             MoveUsage(StorageService()->PolicyDB(),DB_,FromPolicy,ToPolicy,Existing.info.id); | ||||||
|             if(MovingPolicy) { |             ManageMembership(StorageService()->EntityDB(),&ProvObjects::Entity::contacts,FromEntity,ToEntity,Existing.info.id); | ||||||
|                 if(!MoveFromPolicy.empty()) |  | ||||||
|                     StorageService()->PolicyDB().DeleteInUse("id",MoveFromPolicy,DB_.Prefix(),Existing.info.id); |  | ||||||
|                 if(!MoveToPolicy.empty()) |  | ||||||
|                     StorageService()->PolicyDB().AddInUse("id", MoveToPolicy, DB_.Prefix(), Existing.info.id); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             if(MovingEntity) { |  | ||||||
|                 if(!MoveFromEntity.empty()) { |  | ||||||
|                     StorageService()->EntityDB().DeleteContact("id", MoveFromEntity, Existing.info.id); |  | ||||||
|                 } |  | ||||||
|                 if(!MoveToEntity.empty()) { |  | ||||||
|                     StorageService()->EntityDB().AddContact("id", MoveToEntity, Existing.info.id); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             ProvObjects::Contact    NewObjectAdded; |             ProvObjects::Contact    NewObjectAdded; | ||||||
|             DB_.GetRecord("id", UUID, NewObjectAdded); |             DB_.GetRecord("id", UUID, NewObjectAdded); | ||||||
|   | |||||||
| @@ -22,15 +22,14 @@ namespace OpenWifi { | |||||||
|             Poco::Net::HTTPRequest::HTTP_OPTIONS}, |             Poco::Net::HTTPRequest::HTTP_OPTIONS}, | ||||||
|             Server, |             Server, | ||||||
|             TransactionId, |             TransactionId, | ||||||
|             Internal), |             Internal){} | ||||||
|             DB_(StorageService()->ContactDB()){} |         static auto PathName() { return std::list<std::string>{"/api/v1/contact/{uuid}"}; }; | ||||||
|         static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/contact/{uuid}"}; }; |  | ||||||
|  |  | ||||||
|     private: |     private: | ||||||
|  |         ContactDB       &DB_=StorageService()->ContactDB(); | ||||||
|         void DoGet() final; |         void DoGet() final; | ||||||
|         void DoPost() final; |         void DoPost() final; | ||||||
|         void DoPut() final; |         void DoPut() final; | ||||||
|         void DoDelete() final; |         void DoDelete() final; | ||||||
|         ContactDB       &DB_; |  | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -10,17 +10,6 @@ | |||||||
|  |  | ||||||
| namespace OpenWifi{ | namespace OpenWifi{ | ||||||
|     void RESTAPI_contact_list_handler::DoGet() { |     void RESTAPI_contact_list_handler::DoGet() { | ||||||
|         if(!QB_.Select.empty()) { |         return ListHandler<ContactDB>("contacts", DB_, *this); | ||||||
|             return ReturnRecordList<decltype(StorageService()->ContactDB()), |  | ||||||
|             ProvObjects::Contact>("contacts",StorageService()->ContactDB(),*this ); |  | ||||||
|         } else if(QB_.CountOnly) { |  | ||||||
|             Poco::JSON::Object  Answer; |  | ||||||
|             auto C = StorageService()->ContactDB().Count(); |  | ||||||
|             return ReturnCountOnly(C); |  | ||||||
|         } else { |  | ||||||
|             ProvObjects::ContactVec Contacts; |  | ||||||
|             StorageService()->ContactDB().GetRecords(QB_.Offset,QB_.Limit,Contacts); |  | ||||||
|             return MakeJSONObjectArray("contacts", Contacts, *this); |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -6,6 +6,7 @@ | |||||||
|  |  | ||||||
| #include "framework/MicroService.h" | #include "framework/MicroService.h" | ||||||
| #include "RESTObjects/RESTAPI_ProvObjects.h" | #include "RESTObjects/RESTAPI_ProvObjects.h" | ||||||
|  | #include "StorageService.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace OpenWifi { | ||||||
|  |  | ||||||
| @@ -18,9 +19,10 @@ namespace OpenWifi { | |||||||
|             Poco::Net::HTTPRequest::HTTP_OPTIONS}, |             Poco::Net::HTTPRequest::HTTP_OPTIONS}, | ||||||
|             Server, |             Server, | ||||||
|             TransactionId, |             TransactionId, | ||||||
|             Internal) {} |             Internal){} | ||||||
|         static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/contact"}; }; |         static auto PathName() { return std::list<std::string>{"/api/v1/contact"}; }; | ||||||
|  |     private: | ||||||
|  |         ContactDB   & DB_=StorageService()->ContactDB(); | ||||||
|         void DoGet() final; |         void DoGet() final; | ||||||
|         void DoPost() final {}; |         void DoPost() final {}; | ||||||
|         void DoPut() final {}; |         void DoPut() final {}; | ||||||
|   | |||||||
| @@ -7,11 +7,15 @@ | |||||||
| #include "RESTObjects/RESTAPI_ProvObjects.h" | #include "RESTObjects/RESTAPI_ProvObjects.h" | ||||||
| #include "StorageService.h" | #include "StorageService.h" | ||||||
| #include "framework/MicroService.h" | #include "framework/MicroService.h" | ||||||
| #include "framework/RESTAPI_errors.h" | #include "framework/ConfigurationValidator.h" | ||||||
|  | #include "sdks/SDK_sec.h" | ||||||
|  | #include "Poco/StringTokenizer.h" | ||||||
|  |  | ||||||
|  | #include "libs/croncpp.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace OpenWifi { | ||||||
|  |  | ||||||
|     static void AddInfoBlock(const ProvObjects::ObjectInfo & O, Poco::JSON::Object &J) { |     inline static void AddInfoBlock(const ProvObjects::ObjectInfo & O, Poco::JSON::Object &J) { | ||||||
|         J.set("name", O.name); |         J.set("name", O.name); | ||||||
|         J.set("description", O.description); |         J.set("description", O.description); | ||||||
|         J.set("id", O.id); |         J.set("id", O.id); | ||||||
| @@ -154,9 +158,6 @@ namespace OpenWifi { | |||||||
|         return R.ReturnObject(Answer); |         return R.ReturnObject(Answer); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| //    ReturnRecordList<decltype(StorageService()->InventoryDB()), |  | ||||||
| //            ProvObjects::InventoryTag>("taglist",StorageService()->InventoryDB(),*this ); |  | ||||||
|  |  | ||||||
|     inline static bool is_uuid(const std::string &u) { |     inline static bool is_uuid(const std::string &u) { | ||||||
|         return u.find('-') != std::string::npos; |         return u.find('-') != std::string::npos; | ||||||
|     } |     } | ||||||
| @@ -172,7 +173,7 @@ namespace OpenWifi { | |||||||
|                     AddExtendedInfo(E,Obj); |                     AddExtendedInfo(E,Obj); | ||||||
|                 ObjArr.add(Obj); |                 ObjArr.add(Obj); | ||||||
|             } else { |             } else { | ||||||
|                 return R.BadRequest(RESTAPI::Errors::UnknownId + i); |                 return R.BadRequest(RESTAPI::Errors::UnknownId); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         Poco::JSON::Object  Answer; |         Poco::JSON::Object  Answer; | ||||||
| @@ -191,7 +192,7 @@ namespace OpenWifi { | |||||||
|                     AddExtendedInfo(E,Obj); |                     AddExtendedInfo(E,Obj); | ||||||
|                 ObjArr.add(Obj); |                 ObjArr.add(Obj); | ||||||
|             } else { |             } else { | ||||||
|                 return R.BadRequest(RESTAPI::Errors::UnknownId + i); |                 return R.BadRequest(RESTAPI::Errors::UnknownId); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         Poco::JSON::Object  Answer; |         Poco::JSON::Object  Answer; | ||||||
| @@ -212,4 +213,492 @@ namespace OpenWifi { | |||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     typedef std::tuple<std::string,std::string,std::string> triplet_t; | ||||||
|  |  | ||||||
|  |     inline void AddLocationTriplet(const std::string &id, std::vector<triplet_t> & IDs) { | ||||||
|  |         ProvObjects::Location   L; | ||||||
|  |         if(StorageService()->LocationDB().GetRecord("id",id,L)) { | ||||||
|  |             IDs.emplace_back(std::make_tuple(L.info.name,L.info.description,L.info.id)); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     inline void AddLocationTriplet(const std::vector<std::string> &id, std::vector<triplet_t> & IDs) { | ||||||
|  |         for(const auto &i:id) | ||||||
|  |             AddLocationTriplet(i,IDs); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     inline void GetLocationsForEntity(const std::string &ID, std::vector<triplet_t> & IDs) { | ||||||
|  |         ProvObjects::Entity  Existing; | ||||||
|  |         if(StorageService()->EntityDB().template GetRecord("id",ID,Existing)) { | ||||||
|  |             if(!Existing.locations.empty()) { | ||||||
|  |                 AddLocationTriplet(Existing.locations,IDs); | ||||||
|  |             } | ||||||
|  |             if(!Existing.parent.empty()) { | ||||||
|  |                 GetLocationsForEntity(Existing.parent,IDs); | ||||||
|  |             } | ||||||
|  |             if(ID==EntityDB::RootUUID()) | ||||||
|  |                 return; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     inline void GetLocationsForVenue(const std::string &ID, std::vector<triplet_t> & IDs) { | ||||||
|  |         ProvObjects::Venue  Existing; | ||||||
|  |         if(StorageService()->VenueDB().template GetRecord("id",ID,Existing)) { | ||||||
|  |             if(!Existing.parent.empty()) { | ||||||
|  |                 GetLocationsForVenue(Existing.parent,IDs); | ||||||
|  |             } | ||||||
|  |             ProvObjects::Entity E; | ||||||
|  |             if(StorageService()->EntityDB().GetRecord("id", Existing.entity, E)) { | ||||||
|  |                 AddLocationTriplet(E.locations,IDs); | ||||||
|  |             } | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     template <typename DB> void ListHandler(const char *BlockName,DB & DBInstance, RESTAPIHandler & R) { | ||||||
|  |         auto Entity = R.GetParameter("entity", ""); | ||||||
|  |         auto Venue = R.GetParameter("venue", ""); | ||||||
|  |  | ||||||
|  |         typedef typename DB::RecordVec      RecVec; | ||||||
|  |         typedef typename DB::RecordName     RecType; | ||||||
|  |  | ||||||
|  |         if constexpr(std::is_same_v<RecType,ProvObjects::Venue>) { | ||||||
|  |             auto LocationsForVenue = R.GetParameter("locationsForVenue",""); | ||||||
|  |             if(!LocationsForVenue.empty()) { | ||||||
|  |                 std::vector<triplet_t>  IDs; | ||||||
|  |                 GetLocationsForVenue(LocationsForVenue,IDs); | ||||||
|  |                 Poco::JSON::Array   A; | ||||||
|  |                 for(const auto &[name,description,uuid]:IDs) { | ||||||
|  |                     Poco::JSON::Object  O; | ||||||
|  |                     O.set("name", name); | ||||||
|  |                     O.set("description",description); | ||||||
|  |                     O.set("uuid",uuid); | ||||||
|  |                     A.add(O); | ||||||
|  |                 } | ||||||
|  |                 Poco::JSON::Object  Answer; | ||||||
|  |                 Answer.set("locations",A); | ||||||
|  |                 return R.ReturnObject(Answer); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(!R.QB_.Select.empty()) { | ||||||
|  |             return ReturnRecordList<decltype(DBInstance), | ||||||
|  |                     RecType>(BlockName, DBInstance, R); | ||||||
|  |         } if(!Entity.empty()) { | ||||||
|  |             RecVec Entries; | ||||||
|  |             DBInstance.GetRecords(R.QB_.Offset,R.QB_.Limit,Entries," entity=' " + Entity +"'"); | ||||||
|  |             if(R.QB_.CountOnly) | ||||||
|  |                 return R.ReturnCountOnly(Entries.size()); | ||||||
|  |             return MakeJSONObjectArray(BlockName, Entries, R); | ||||||
|  |         } if(!Venue.empty()) { | ||||||
|  |             RecVec Entries; | ||||||
|  |             DBInstance.GetRecords(R.QB_.Offset,R.QB_.Limit,Entries," venue=' " + Venue +"'"); | ||||||
|  |             if(R.QB_.CountOnly) | ||||||
|  |                 return R.ReturnCountOnly(Entries.size()); | ||||||
|  |             return MakeJSONObjectArray(BlockName, Entries, R); | ||||||
|  |         } else if(R.QB_.CountOnly) { | ||||||
|  |             Poco::JSON::Object  Answer; | ||||||
|  |             auto C = DBInstance.Count(); | ||||||
|  |             return R.ReturnCountOnly(C); | ||||||
|  |         } else { | ||||||
|  |             RecVec Entries; | ||||||
|  |             DBInstance.GetRecords(R.QB_.Offset,R.QB_.Limit,Entries); | ||||||
|  |             return MakeJSONObjectArray(BlockName, Entries, R); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     template <typename db_type> void ListHandlerForOperator(const char *BlockName,db_type & DB, RESTAPIHandler & R, const Types::UUID_t & OperatorId, const Types::UUID_t & subscriberId="") { | ||||||
|  |         typedef typename db_type::RecordVec      RecVec; | ||||||
|  |         typedef typename db_type::RecordName     RecType; | ||||||
|  |  | ||||||
|  |         auto whereClause = subscriberId.empty() ? | ||||||
|  |                             fmt::format(" operatorId='{}'", OperatorId) : | ||||||
|  |                             fmt::format(" operatorId='{}' and subscriberId='{}' ", OperatorId, subscriberId); | ||||||
|  |  | ||||||
|  |         if(R.QB_.CountOnly) { | ||||||
|  |             auto Count = DB.Count( whereClause ); | ||||||
|  |             return R.ReturnCountOnly(Count); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(!R.QB_.Select.empty()) { | ||||||
|  |             return ReturnRecordList<decltype(DB), | ||||||
|  |                     RecType>(BlockName, DB, R); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         RecVec  Entries; | ||||||
|  |         DB.GetRecords(R.QB_.Offset,R.QB_.Limit,Entries,whereClause); | ||||||
|  |         return MakeJSONObjectArray(BlockName, Entries, R); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     template <typename db_type, typename ObjectDB> void MoveUsage(db_type &DB_InUse, ObjectDB & DB, const std::string & From, const std::string & To, const std::string &Id) { | ||||||
|  |         if(From!=To) { | ||||||
|  |             if(!From.empty()) | ||||||
|  |                 DB_InUse.DeleteInUse("id",From,DB.Prefix(),Id); | ||||||
|  |             if(!To.empty()) | ||||||
|  |                 DB_InUse.AddInUse("id",To,DB.Prefix(),Id); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     template <typename db_type, typename ObjectDB> void MoveUsage(db_type &DB_InUse, ObjectDB & DB, const Types::UUIDvec_t & From, const Types::UUIDvec_t & To, const std::string &Id) { | ||||||
|  |         if(From!=To) { | ||||||
|  |             if(!From.empty()) { | ||||||
|  |                 for(const auto &i:From) | ||||||
|  |                     DB_InUse.DeleteInUse("id", i, DB.Prefix(), Id); | ||||||
|  |             } | ||||||
|  |             if(!To.empty()) { | ||||||
|  |                 for(const auto &i:To) | ||||||
|  |                     DB_InUse.AddInUse("id", i, DB.Prefix(), Id); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     template <typename db_type> void MoveChild(db_type &DB, const std::string & Parent, const std::string & Child, const std::string &Id) { | ||||||
|  |         if(Parent!=Child) { | ||||||
|  |             if(!Parent.empty()) | ||||||
|  |                 DB.InUse.DeleteInUse("id",Parent,Id); | ||||||
|  |             if(!Child.empty()) | ||||||
|  |                 DB.AddInUse("id",Child,Id); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     template <typename db_type, typename Member> void RemoveMembership( db_type & DB, Member T, const std::string & Obj, const std::string &Id) { | ||||||
|  |         if(!Obj.empty()) | ||||||
|  |             DB.ManipulateVectorMember(T, "id", Obj, Id, false); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     template <typename db_type, typename Member> void AddMembership( db_type & DB, Member T, const std::string & Obj, const std::string &Id) { | ||||||
|  |         if(!Obj.empty()) | ||||||
|  |             DB.ManipulateVectorMember(T, "id", Obj, Id, true); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     template <typename db_type, typename Member> void ManageMembership( db_type & DB, Member T, const std::string & From, const std::string & To, const std::string &Id) { | ||||||
|  |         RemoveMembership(DB,T,From,Id); | ||||||
|  |         AddMembership(DB,T,To,Id); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     template <typename db_type, typename Member> void ManageMembership( db_type & DB, Member T, const Types::UUIDvec_t & From, const Types::UUIDvec_t & To, const std::string &Id) { | ||||||
|  |         if(From!=To) { | ||||||
|  |             for (const auto &i: From) { | ||||||
|  |                 RemoveMembership(DB, T, i, Id); | ||||||
|  |             } | ||||||
|  |             for (const auto &i: To) { | ||||||
|  |                 AddMembership(DB, T, i, Id); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     template <typename Member, typename Rec, typename db_type > bool CreateMove(const Poco::JSON::Object::Ptr & RawObj, const char *fieldname, Member T, Rec & Existing, std::string &From, std::string &To, db_type & TheDB) { | ||||||
|  |         if(RawObj->has(fieldname)) { | ||||||
|  |             From = Existing.*T; | ||||||
|  |             To = RawObj->get(fieldname).toString(); | ||||||
|  |             if(!To.empty() && !TheDB.Exists("id",To)) | ||||||
|  |                 return false; | ||||||
|  |             Existing.*T=To; | ||||||
|  |         } | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     inline std::string FindParentEntity(const ProvObjects::Venue &V) { | ||||||
|  |         if(V.parent.empty()) | ||||||
|  |             return V.entity; | ||||||
|  |         ProvObjects::Venue  P; | ||||||
|  |         if(StorageService()->VenueDB().GetRecord("id",V.parent,P)) | ||||||
|  |             return FindParentEntity(P); | ||||||
|  |         return EntityDB::RootUUID(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     inline bool ValidateConfigBlock(const ProvObjects::DeviceConfiguration &Config, RESTAPI::Errors::msg & Error) { | ||||||
|  |         static const std::vector<std::string> SectionNames{ "globals", "interfaces", "metrics", "radios", "services", | ||||||
|  |                                                             "unit", "definitions", "ethernet", "switch", "config-raw", | ||||||
|  |                                                             "third-party" }; | ||||||
|  |  | ||||||
|  |         for(const auto &i:Config.configuration) { | ||||||
|  |             Poco::JSON::Parser  P; | ||||||
|  |             if(i.name.empty()) { | ||||||
|  |                 std::cout << "Name is empty" << std::endl; | ||||||
|  |                 Error = RESTAPI::Errors::NameMustBeSet; | ||||||
|  |                 return false; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             try { | ||||||
|  |                 auto Blocks = P.parse(i.configuration).extract<Poco::JSON::Object::Ptr>(); | ||||||
|  |                 auto N = Blocks->getNames(); | ||||||
|  |                 for (const auto &j: N) { | ||||||
|  |                     if (std::find(SectionNames.cbegin(), SectionNames.cend(), j) == SectionNames.cend()) { | ||||||
|  |                         Error = RESTAPI::Errors::UnknownConfigurationSection; | ||||||
|  |                         return false; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } catch (const Poco::JSON::JSONException &E ) { | ||||||
|  |                 Error = RESTAPI::Errors::InvalidJSONDocument; | ||||||
|  |                 return false; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             try { | ||||||
|  |                 std::string ErrorText; | ||||||
|  |                 if (ValidateUCentralConfiguration(i.configuration, ErrorText)) { | ||||||
|  |                     // std::cout << "Block: " << i.name << " is valid" << std::endl; | ||||||
|  |                 } else { | ||||||
|  |                     Error =  RESTAPI::Errors::ConfigBlockInvalid ; | ||||||
|  |                     return false; | ||||||
|  |                 } | ||||||
|  |             } catch(...) { | ||||||
|  |                 std::cout << "Exception in validation" << std::endl; | ||||||
|  |                 return false; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |         } | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     template <typename Type> std::map<std::string,std::string>   CreateObjects(Type & NewObject, RESTAPIHandler & R, RESTAPI::Errors::msg & Error) { | ||||||
|  |         std::map<std::string,std::string>   Result; | ||||||
|  |  | ||||||
|  |         auto createObjects = R.GetParameter("createObjects",""); | ||||||
|  |         if(!createObjects.empty()) { | ||||||
|  |             std::cout << "createObjects: " << createObjects << std::endl; | ||||||
|  |             Poco::JSON::Parser P; | ||||||
|  |             auto Objects = P.parse(createObjects).extract<Poco::JSON::Object::Ptr>(); | ||||||
|  |             if(Objects->isArray("objects")) { | ||||||
|  |                 auto ObjectsArray = Objects->getArray("objects"); | ||||||
|  |                 for(const auto &i:*ObjectsArray) { | ||||||
|  |                     auto Object = i.extract<Poco::JSON::Object::Ptr>(); | ||||||
|  |                     if (Object->has("location")) { | ||||||
|  |                         auto LocationDetails = Object->get("location").extract<Poco::JSON::Object::Ptr>(); | ||||||
|  |                         ProvObjects::Location LC; | ||||||
|  |                         if (LC.from_json(LocationDetails)) { | ||||||
|  |                             if constexpr(std::is_same_v<Type,ProvObjects::Venue>) { | ||||||
|  |                                 std::cout << "Location decoded: " << LC.info.name << std::endl; | ||||||
|  |                                 std::string ParentEntity = FindParentEntity(NewObject); | ||||||
|  |                                 ProvObjects::CreateObjectInfo(R.UserInfo_.userinfo, LC.info); | ||||||
|  |                                 LC.entity = ParentEntity; | ||||||
|  |                                 if (StorageService()->LocationDB().CreateRecord(LC)) { | ||||||
|  |                                     NewObject.location = LC.info.id; | ||||||
|  |                                     AddMembership(StorageService()->EntityDB(), &ProvObjects::Entity::locations, | ||||||
|  |                                                   ParentEntity, LC.info.id); | ||||||
|  |                                     Result["location"] = LC.info.id; | ||||||
|  |                                 } | ||||||
|  |                             } | ||||||
|  |                             if constexpr(std::is_same_v<Type,ProvObjects::Operator>) { | ||||||
|  |                                 std::cout << "Location decoded: " << LC.info.name << std::endl; | ||||||
|  |                                 std::string ParentEntity = FindParentEntity(NewObject); | ||||||
|  |                                 ProvObjects::CreateObjectInfo(R.UserInfo_.userinfo, LC.info); | ||||||
|  |                                 LC.entity = ParentEntity; | ||||||
|  |                                 if (StorageService()->LocationDB().CreateRecord(LC)) { | ||||||
|  |                                     NewObject.location = LC.info.id; | ||||||
|  |                                     AddMembership(StorageService()->EntityDB(), &ProvObjects::Entity::locations, | ||||||
|  |                                                   ParentEntity, LC.info.id); | ||||||
|  |                                     Result["location"] = LC.info.id; | ||||||
|  |                                 } | ||||||
|  |                             } | ||||||
|  |                         } else { | ||||||
|  |                             Error = RESTAPI::Errors::InvalidJSONDocument; | ||||||
|  |                             break; | ||||||
|  |                         } | ||||||
|  |                     } else if (Object->has("contact")) { | ||||||
|  |                         auto ContactDetails = Object->get("contact").extract<Poco::JSON::Object::Ptr>(); | ||||||
|  |                         ProvObjects::Contact CC; | ||||||
|  |                         if (CC.from_json(ContactDetails)) { | ||||||
|  |                             std::cout << "contact decoded: " << CC.info.name << std::endl; | ||||||
|  |                         } else { | ||||||
|  |                             std::cout << "contact not decoded." << std::endl; | ||||||
|  |                         } | ||||||
|  |                     } else if (Object->has("configuration")) { | ||||||
|  |                         auto ConfigurationDetails = Object->get("configuration").template extract<Poco::JSON::Object::Ptr>(); | ||||||
|  |                         ProvObjects::DeviceConfiguration    DC; | ||||||
|  |                         if(DC.from_json(ConfigurationDetails)) { | ||||||
|  |                             if constexpr(std::is_same_v<Type, ProvObjects::InventoryTag>) { | ||||||
|  |                                 if(!ValidateConfigBlock(DC,Error)) { | ||||||
|  |                                     break; | ||||||
|  |                                 } | ||||||
|  |                                 std::cout << "Configuration decoded: " << DC.info.name << std::endl; | ||||||
|  |                                 ProvObjects::CreateObjectInfo(R.UserInfo_.userinfo, DC.info); | ||||||
|  |                                 if (StorageService()->ConfigurationDB().CreateRecord(DC)) { | ||||||
|  |                                     NewObject.deviceConfiguration = DC.info.id; | ||||||
|  |                                     Result["configuration"] = DC.info.id; | ||||||
|  |                                 } | ||||||
|  |                             } | ||||||
|  |                         } else { | ||||||
|  |                             Error = RESTAPI::Errors::InvalidJSONDocument; | ||||||
|  |                             break; | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return Result; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     inline bool ValidSchedule(const std::string &v) { | ||||||
|  |         try | ||||||
|  |         { | ||||||
|  |             auto cron = cron::make_cron(v); | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |         catch (cron::bad_cronexpr const & ex) | ||||||
|  |         { | ||||||
|  |         } | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     inline bool ValidRRM(const std::string &v) { | ||||||
|  |         if((v=="no") || (v=="inherit")) return true; | ||||||
|  |         try { | ||||||
|  |             Poco::JSON::Parser  P; | ||||||
|  |             auto O = P.parse(v).extract<Poco::JSON::Object::Ptr>(); | ||||||
|  |  | ||||||
|  |             ProvObjects::RRMDetails D; | ||||||
|  |             if(D.from_json(O)) { | ||||||
|  |                 return ValidSchedule(D.schedule); | ||||||
|  |             } | ||||||
|  |         } catch (...) { | ||||||
|  |  | ||||||
|  |         } | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     inline bool ValidDeviceRules(const ProvObjects::DeviceRules & DR) { | ||||||
|  |         return  (ValidRRM(DR.rrm)) && | ||||||
|  |                 (DR.firmwareUpgrade=="yes" || DR.firmwareUpgrade=="no" || DR.firmwareUpgrade=="inherit") && | ||||||
|  |                 (DR.rcOnly=="yes" || DR.rcOnly=="no" || DR.rcOnly=="inherit"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     inline bool ValidDeviceRules(const ProvObjects::DeviceRules & DR, RESTAPIHandler &H) { | ||||||
|  |         if(ValidDeviceRules(DR)) | ||||||
|  |             return true; | ||||||
|  |         H.BadRequest(RESTAPI::Errors::InvalidRRM); | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     inline bool ValidSourceIP([[maybe_unused]] const std::vector<std::string> & IPs) { | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     inline bool ValidPeriod(const std::string &P) { | ||||||
|  |         return (P=="hourly" || P=="daily" || P=="monthly" || P=="yearly" || | ||||||
|  |                 P=="quarterly" || P=="lifetime" || P=="custom1" || | ||||||
|  |                 P=="custom2"|| P=="custom3"|| P=="custom4"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     inline bool ValidContactType(const std::string &contact) { | ||||||
|  |         auto C = Poco::toLower(contact); | ||||||
|  |         return (C=="subscriber" || C=="user" || C=="installer" || C=="csr" || | ||||||
|  |                 C=="manager" || C=="businessowner" || C=="technician" || | ||||||
|  |                 C=="corporate"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     inline bool ValidContactType(const std::string &contact, RESTAPIHandler &H) { | ||||||
|  |         auto C = Poco::toLower(contact); | ||||||
|  |         if (C=="subscriber" || C=="user" || C=="installer" || C=="csr" || | ||||||
|  |                 C=="manager" || C=="businessowner" || C=="technician" || | ||||||
|  |                 C=="corporate") | ||||||
|  |             return true; | ||||||
|  |         H.BadRequest(RESTAPI::Errors::InvalidContactType); | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     inline bool ValidLocationType(const std::string &location) { | ||||||
|  |         auto C = Poco::toLower(location); | ||||||
|  |         return (C=="service" || C=="equipment" || C=="auto" || C=="manual" || | ||||||
|  |                 C=="special" || C=="unknown" || C=="corporate"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     inline bool ValidLocationType(const std::string &location, RESTAPIHandler &H) { | ||||||
|  |         auto C = Poco::toLower(location); | ||||||
|  |         if((C=="service" || C=="equipment" || C=="auto" || C=="manual" || | ||||||
|  |                 C=="special" || C=="unknown" || C=="corporate")) | ||||||
|  |             return true; | ||||||
|  |         H.BadRequest(RESTAPI::Errors::InvalidLocationType); | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     template <typename DBType> bool ValidDbId(const Types::UUID_t &uuid, DBType & DB, bool AllowEmpty , const RESTAPI::Errors::msg &Error , RESTAPIHandler & H) { | ||||||
|  |         if(!AllowEmpty && uuid.empty()) { | ||||||
|  |             H.BadRequest(Error); | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         if(uuid.empty()) | ||||||
|  |             return true; | ||||||
|  |         if(!DB.Exists("id",uuid)) { | ||||||
|  |             H.BadRequest(Error); | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     inline bool ValidSubscriberId( const Types::UUID_t & uuid, bool AllowEmpty, RESTAPIHandler &H ) { | ||||||
|  |         if(!AllowEmpty && uuid.empty()) { | ||||||
|  |             H.BadRequest(RESTAPI::Errors::InvalidSubscriberId); | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         if(uuid.empty()) | ||||||
|  |             return true; | ||||||
|  |         SecurityObjects::UserInfo   NewSubInfo; | ||||||
|  |         if(!SDK::Sec::Subscriber::Get(&H, uuid, NewSubInfo)) { | ||||||
|  |             H.BadRequest(RESTAPI::Errors::InvalidSubscriberId); | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     inline bool ValidSubscriberId( const Types::UUID_t & uuid, bool AllowEmpty, std::string & email, RESTAPIHandler &H ) { | ||||||
|  |         if(!AllowEmpty && uuid.empty()) { | ||||||
|  |             H.BadRequest(RESTAPI::Errors::InvalidSubscriberId); | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         if(uuid.empty()) | ||||||
|  |             return true; | ||||||
|  |         SecurityObjects::UserInfo   NewSubInfo; | ||||||
|  |         if(!SDK::Sec::Subscriber::Get(&H, uuid, NewSubInfo)) { | ||||||
|  |             H.BadRequest(RESTAPI::Errors::InvalidSubscriberId); | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         email = NewSubInfo.email; | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     inline bool ValidSerialNumber(const std::string &serialNumber, bool AllowEmpty, RESTAPIHandler &H) { | ||||||
|  |         if(!AllowEmpty && serialNumber.empty()) { | ||||||
|  |             H.BadRequest(RESTAPI::Errors::InvalidSerialNumber); | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(!Utils::ValidSerialNumber(serialNumber)) { | ||||||
|  |             H.BadRequest(RESTAPI::Errors::InvalidSerialNumber); | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     template <typename DBType, typename DBRecordType> void ReturnUpdatedObject( DBType & DB, const DBRecordType & R, RESTAPIHandler &H) { | ||||||
|  |         if(DB.UpdateRecord("id",R.info.id,R)) { | ||||||
|  |             DBRecordType    Updated; | ||||||
|  |             DB.GetRecord("id",R.info.id,Updated); | ||||||
|  |             Poco::JSON::Object  Answer; | ||||||
|  |             Updated.to_json(Answer); | ||||||
|  |             return H.ReturnObject(Answer); | ||||||
|  |         } else { | ||||||
|  |             H.InternalError(RESTAPI::Errors::RecordNotUpdated); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     template <typename DBType, typename DBRecordType> void ReturnCreatedObject( DBType & DB, const DBRecordType & R, RESTAPIHandler &H) { | ||||||
|  |         if(DB.CreateRecord(R)) { | ||||||
|  |             DBRecordType    Updated; | ||||||
|  |             DB.GetRecord("id",R.info.id,Updated); | ||||||
|  |             Poco::JSON::Object  Answer; | ||||||
|  |             Updated.to_json(Answer); | ||||||
|  |             return H.ReturnObject(Answer); | ||||||
|  |         } else { | ||||||
|  |             H.InternalError(RESTAPI::Errors::RecordNotCreated); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     template <typename DBType> void ReturnFieldList(DBType & DB, RESTAPIHandler &H) { | ||||||
|  |         Types::StringVec Fields; | ||||||
|  |         DB.GetFieldNames(Fields); | ||||||
|  |         Poco::JSON::Object  Answer; | ||||||
|  |         RESTAPI_utils::field_to_json(Answer,"list",Fields); | ||||||
|  |         return H.ReturnObject(Answer); | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -42,21 +42,15 @@ namespace OpenWifi{ | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         if( !Existing.children.empty() || !Existing.devices.empty() || !Existing.venues.empty() || !Existing.locations.empty() |         if( !Existing.children.empty() || !Existing.devices.empty() || !Existing.venues.empty() || !Existing.locations.empty() | ||||||
|             || !Existing.contacts.empty()) { |             || !Existing.contacts.empty() || !Existing.configurations.empty()) { | ||||||
|             return BadRequest(RESTAPI::Errors::StillInUse); |             return BadRequest(RESTAPI::Errors::StillInUse); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(!Existing.deviceConfiguration.empty()) { |         MoveUsage(StorageService()->PolicyDB(),DB_,Existing.managementPolicy,"",Existing.info.id); | ||||||
|             for(auto &i:Existing.deviceConfiguration) |         DB_.DeleteRecord("id",UUID); | ||||||
|                 StorageService()->ConfigurationDB().DeleteInUse("id", i, DB_.Prefix(), Existing.info.id); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if(DB_.DeleteRecord("id",UUID)) { |  | ||||||
|         DB_.DeleteChild("id",Existing.parent,UUID); |         DB_.DeleteChild("id",Existing.parent,UUID); | ||||||
|         return OK(); |         return OK(); | ||||||
|     } |     } | ||||||
|         InternalError(RESTAPI::Errors::CouldNotBeDeleted); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void RESTAPI_entity_handler::DoPost() { |     void RESTAPI_entity_handler::DoPost() { | ||||||
|         std::string UUID = GetBinding("uuid", ""); |         std::string UUID = GetBinding("uuid", ""); | ||||||
| @@ -64,17 +58,21 @@ namespace OpenWifi{ | |||||||
|             return BadRequest(RESTAPI::Errors::MissingUUID); |             return BadRequest(RESTAPI::Errors::MissingUUID); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(!DB_.RootExists() && UUID != EntityDB::RootUUID()) { |         if(UUID==EntityDB::RootUUID()) { | ||||||
|             return BadRequest(RESTAPI::Errors::MustCreateRootFirst); |             return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         auto Obj = ParseStream(); |         const auto & RawObject = ParsedBody_; | ||||||
|         ProvObjects::Entity NewEntity; |         ProvObjects::Entity NewEntity; | ||||||
|         if (!NewEntity.from_json(Obj)) { |         if (!NewEntity.from_json(RawObject)) { | ||||||
|             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); |             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(!ProvObjects::CreateObjectInfo(Obj,UserInfo_.userinfo,NewEntity.info)) { |         if((RawObject->has("deviceRules") && !ValidDeviceRules(NewEntity.deviceRules,*this))) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(!ProvObjects::CreateObjectInfo(RawObject,UserInfo_.userinfo,NewEntity.info)) { | ||||||
|             return BadRequest(RESTAPI::Errors::NameMustBeSet); |             return BadRequest(RESTAPI::Errors::NameMustBeSet); | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -88,13 +86,6 @@ namespace OpenWifi{ | |||||||
|             return BadRequest(RESTAPI::Errors::ParentUUIDMustExist); |             return BadRequest(RESTAPI::Errors::ParentUUIDMustExist); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(!NewEntity.deviceConfiguration.empty()) { |  | ||||||
|             for(auto &i:NewEntity.deviceConfiguration) |  | ||||||
|                 if(!StorageService()->ConfigurationDB().Exists("id",i)) { |  | ||||||
|                     return BadRequest(RESTAPI::Errors::ConfigurationMustExist); |  | ||||||
|                 } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if(!NewEntity.managementPolicy.empty() && !StorageService()->PolicyDB().Exists("id", NewEntity.managementPolicy)){ |         if(!NewEntity.managementPolicy.empty() && !StorageService()->PolicyDB().Exists("id", NewEntity.managementPolicy)){ | ||||||
|             return BadRequest(RESTAPI::Errors::UnknownManagementPolicyUUID); |             return BadRequest(RESTAPI::Errors::UnknownManagementPolicyUUID); | ||||||
|         } |         } | ||||||
| @@ -107,13 +98,12 @@ namespace OpenWifi{ | |||||||
|         NewEntity.children.clear(); |         NewEntity.children.clear(); | ||||||
|         NewEntity.contacts.clear(); |         NewEntity.contacts.clear(); | ||||||
|         NewEntity.locations.clear(); |         NewEntity.locations.clear(); | ||||||
|  |         NewEntity.deviceConfiguration.clear(); | ||||||
|  |         NewEntity.managementRoles.clear(); | ||||||
|  |  | ||||||
|         if(DB_.CreateShortCut(NewEntity)) { |         if(DB_.CreateRecord(NewEntity)) { | ||||||
|             if(UUID==EntityDB::RootUUID()) { |             MoveUsage(StorageService()->PolicyDB(),DB_,"",NewEntity.managementPolicy,NewEntity.info.id); | ||||||
|                 DB_.CheckForRoot(); |  | ||||||
|             } else { |  | ||||||
|             DB_.AddChild("id",NewEntity.parent,NewEntity.info.id); |             DB_.AddChild("id",NewEntity.parent,NewEntity.info.id); | ||||||
|             } |  | ||||||
|  |  | ||||||
|             Poco::JSON::Object  Answer; |             Poco::JSON::Object  Answer; | ||||||
|             NewEntity.to_json(Answer); |             NewEntity.to_json(Answer); | ||||||
| @@ -138,37 +128,23 @@ namespace OpenWifi{ | |||||||
|             return NotFound(); |             return NotFound(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         auto RawObject = ParseStream(); |         const auto & RawObject = ParsedBody_; | ||||||
|         ProvObjects::Entity NewEntity; |         ProvObjects::Entity NewEntity; | ||||||
|         if(!NewEntity.from_json(RawObject)) { |         if(!NewEntity.from_json(RawObject)) { | ||||||
|             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); |             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         if((RawObject->has("deviceRules") && !ValidDeviceRules(NewEntity.deviceRules,*this))) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|         if(!UpdateObjectInfo(RawObject, UserInfo_.userinfo, Existing.info)) { |         if(!UpdateObjectInfo(RawObject, UserInfo_.userinfo, Existing.info)) { | ||||||
|             return BadRequest(RESTAPI::Errors::NameMustBeSet); |             return BadRequest(RESTAPI::Errors::NameMustBeSet); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         std::string NewManagementPolicy; |         std::string FromPolicy, ToPolicy; | ||||||
|         Types::UUIDvec_t NewConfiguration; |         if(!CreateMove(RawObject,"managementPolicy",&EntityDB::RecordName::managementPolicy, Existing, FromPolicy, ToPolicy, StorageService()->PolicyDB())) | ||||||
|         bool        MovingConfiguration=false, |  | ||||||
|                     MovingManagementPolicy=false; |  | ||||||
|         if(RawObject->has("deviceConfiguration")) { |  | ||||||
|             if(!NewEntity.deviceConfiguration.empty()) { |  | ||||||
|                 for(auto &i:NewEntity.deviceConfiguration) { |  | ||||||
|                     if(!StorageService()->ConfigurationDB().Exists("id",i)) { |  | ||||||
|                         return BadRequest(RESTAPI::Errors::ConfigurationMustExist); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|                 NewConfiguration = NewEntity.deviceConfiguration; |  | ||||||
|             } |  | ||||||
|             MovingConfiguration = Existing.deviceConfiguration != NewConfiguration; |  | ||||||
|         } |  | ||||||
|         if(AssignIfPresent(RawObject,"managementPolicy",NewManagementPolicy)) { |  | ||||||
|             if(!NewManagementPolicy.empty() && !StorageService()->PolicyDB().Exists("id",NewManagementPolicy)) { |  | ||||||
|             return BadRequest(RESTAPI::Errors::UnknownManagementPolicyUUID); |             return BadRequest(RESTAPI::Errors::UnknownManagementPolicyUUID); | ||||||
|             } |  | ||||||
|             MovingManagementPolicy = Existing.managementPolicy != NewManagementPolicy; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if(RawObject->has("sourceIP")) { |         if(RawObject->has("sourceIP")) { | ||||||
|             if(!NewEntity.sourceIP.empty() && !CIDR::ValidateIpRanges(NewEntity.sourceIP)) { |             if(!NewEntity.sourceIP.empty() && !CIDR::ValidateIpRanges(NewEntity.sourceIP)) { | ||||||
| @@ -177,51 +153,16 @@ namespace OpenWifi{ | |||||||
|             Existing.sourceIP = NewEntity.sourceIP; |             Existing.sourceIP = NewEntity.sourceIP; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         std::string Error; |         RESTAPI::Errors::msg    Error; | ||||||
|         if(!StorageService()->Validate(Parameters_,Error)) { |         if(!StorageService()->Validate(Parameters_,Error)) { | ||||||
|             return BadRequest(Error); |             return BadRequest(Error); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         AssignIfPresent(RawObject, "rrm", Existing.rrm); |         if(RawObject->has("deviceRules")) | ||||||
|  |             Existing.deviceRules = NewEntity.deviceRules; | ||||||
|  |  | ||||||
|         if(DB_.UpdateRecord("id",UUID,Existing)) { |         if(DB_.UpdateRecord("id",UUID,Existing)) { | ||||||
|             for(const auto &i:*Request) { |             MoveUsage(StorageService()->PolicyDB(),DB_,FromPolicy,ToPolicy,Existing.info.id); | ||||||
|                 std::string Child{i.second}; |  | ||||||
|                 auto UUID_parts = Utils::Split(Child,':'); |  | ||||||
|                 if(i.first=="add" && UUID_parts[0] == "con") { |  | ||||||
|                     DB_.AddContact("id", UUID, UUID_parts[1]); |  | ||||||
|                     StorageService()->ContactDB().AddInUse("id",UUID_parts[1],DB_.Prefix(), UUID); |  | ||||||
|                 } else if (i.first == "del" && UUID_parts[0] == "con") { |  | ||||||
|                     DB_.DeleteContact("id", UUID, UUID_parts[1]); |  | ||||||
|                     StorageService()->ContactDB().DeleteInUse("id",UUID_parts[1],DB_.Prefix(),UUID); |  | ||||||
|                 } else if (i.first == "add" && UUID_parts[0] == "loc") { |  | ||||||
|                     DB_.AddLocation("id", UUID, UUID_parts[1]); |  | ||||||
|                     StorageService()->LocationDB().AddInUse("id",UUID_parts[1],DB_.Prefix(),UUID); |  | ||||||
|                 } else if (i.first == "del" && UUID_parts[0] == "loc") { |  | ||||||
|                     DB_.DeleteLocation("id", UUID, UUID_parts[1]); |  | ||||||
|                     StorageService()->LocationDB().DeleteInUse("id",UUID_parts[1],DB_.Prefix(),UUID); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             if(MovingConfiguration) { |  | ||||||
|                 if(!Existing.deviceConfiguration.empty()) |  | ||||||
|                     for(auto &i:Existing.deviceConfiguration) |  | ||||||
|                         StorageService()->ConfigurationDB().DeleteInUse("id",i,DB_.Prefix(),Existing.info.id); |  | ||||||
|                 if(!NewConfiguration.empty()) |  | ||||||
|                     for(auto &i:NewConfiguration) |  | ||||||
|                         StorageService()->ConfigurationDB().AddInUse("id",i,DB_.Prefix(),Existing.info.id); |  | ||||||
|                 Existing.deviceConfiguration = NewConfiguration; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             if(MovingManagementPolicy) { |  | ||||||
|                 if(!Existing.managementPolicy.empty()) |  | ||||||
|                     StorageService()->PolicyDB().DeleteInUse("id",Existing.managementPolicy, DB_.Prefix(), Existing.info.id); |  | ||||||
|                 if(!NewManagementPolicy.empty()) |  | ||||||
|                     StorageService()->PolicyDB().AddInUse("id", NewManagementPolicy, DB_.Prefix(), Existing.info.id); |  | ||||||
|                 Existing.managementPolicy = NewManagementPolicy; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             DB_.UpdateRecord("id", Existing.info.id, Existing); |  | ||||||
|  |  | ||||||
|             Poco::JSON::Object  Answer; |             Poco::JSON::Object  Answer; | ||||||
|             ProvObjects::Entity NewRecord; |             ProvObjects::Entity NewRecord; | ||||||
|   | |||||||
| @@ -24,12 +24,11 @@ namespace OpenWifi { | |||||||
|                                 Poco::Net::HTTPRequest::HTTP_OPTIONS}, |                                 Poco::Net::HTTPRequest::HTTP_OPTIONS}, | ||||||
|                                 Server, |                                 Server, | ||||||
|                                 TransactionId, |                                 TransactionId, | ||||||
|                                 Internal), |                                 Internal){} | ||||||
|                                 DB_(StorageService()->EntityDB()){} |         static auto PathName() { return std::list<std::string>{"/api/v1/entity/{uuid}"}; }; | ||||||
|         static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/entity/{uuid}"}; }; |  | ||||||
|  |  | ||||||
|     private: |     private: | ||||||
|         EntityDB        & DB_; |         EntityDB        & DB_=StorageService()->EntityDB(); | ||||||
|         void DoGet() final; |         void DoGet() final; | ||||||
|         void DoPost() final ; |         void DoPost() final ; | ||||||
|         void DoPut() final; |         void DoPut() final; | ||||||
|   | |||||||
| @@ -15,26 +15,26 @@ namespace OpenWifi{ | |||||||
|  |  | ||||||
|     void RESTAPI_entity_list_handler::DoGet() { |     void RESTAPI_entity_list_handler::DoGet() { | ||||||
|         if(!QB_.Select.empty()) { |         if(!QB_.Select.empty()) { | ||||||
|             return ReturnRecordList<decltype(StorageService()->EntityDB()), |             return ReturnRecordList<decltype(DB_), | ||||||
|             ProvObjects::Entity>("entities",StorageService()->EntityDB(),*this ); |             ProvObjects::Entity>("entities",DB_,*this ); | ||||||
|         } else if(QB_.CountOnly) { |         } else if(QB_.CountOnly) { | ||||||
|             auto C = StorageService()->EntityDB().Count(); |             auto C = DB_.Count(); | ||||||
|             return ReturnCountOnly(C); |             return ReturnCountOnly(C); | ||||||
|         } else if (GetBoolParameter("getTree",false)) { |         } else if (GetBoolParameter("getTree",false)) { | ||||||
|             Poco::JSON::Object  FullTree; |             Poco::JSON::Object  FullTree; | ||||||
|             StorageService()->EntityDB().BuildTree(FullTree); |             DB_.BuildTree(FullTree); | ||||||
|             return ReturnObject(FullTree); |             return ReturnObject(FullTree); | ||||||
|         } else { |         } else { | ||||||
|             ProvObjects::EntityVec Entities; |             EntityDB::RecordVec Entities; | ||||||
|             StorageService()->EntityDB().GetRecords(QB_.Offset, QB_.Limit,Entities); |             DB_.GetRecords(QB_.Offset, QB_.Limit,Entities); | ||||||
|             return MakeJSONObjectArray("entities", Entities, *this); |             return MakeJSONObjectArray("entities", Entities, *this); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void RESTAPI_entity_list_handler::DoPost() { |     void RESTAPI_entity_list_handler::DoPost() { | ||||||
|         if (GetBoolParameter("setTree",false)) { |         if (GetBoolParameter("setTree",false)) { | ||||||
|             auto FullTree = ParseStream(); |             const auto & FullTree = ParsedBody_; | ||||||
|             StorageService()->EntityDB().ImportTree(FullTree); |             DB_.ImportTree(FullTree); | ||||||
|             return OK(); |             return OK(); | ||||||
|         } |         } | ||||||
|         BadRequest(RESTAPI::Errors::MissingOrInvalidParameters); |         BadRequest(RESTAPI::Errors::MissingOrInvalidParameters); | ||||||
|   | |||||||
| @@ -10,6 +10,7 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include "framework/MicroService.h" | #include "framework/MicroService.h" | ||||||
|  | #include "StorageService.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace OpenWifi { | ||||||
|     class RESTAPI_entity_list_handler : public RESTAPIHandler { |     class RESTAPI_entity_list_handler : public RESTAPIHandler { | ||||||
| @@ -22,9 +23,10 @@ namespace OpenWifi { | |||||||
|             Poco::Net::HTTPRequest::HTTP_OPTIONS}, |             Poco::Net::HTTPRequest::HTTP_OPTIONS}, | ||||||
|             Server, |             Server, | ||||||
|             TransactionId, |             TransactionId, | ||||||
|             Internal) {} |             Internal){} | ||||||
|         static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/entity"}; }; |         static auto PathName() { return std::list<std::string>{"/api/v1/entity"}; }; | ||||||
|  |     private: | ||||||
|  |         EntityDB    &DB_=StorageService()->EntityDB(); | ||||||
|         void DoGet() final; |         void DoGet() final; | ||||||
|         void DoPost() final ; |         void DoPost() final ; | ||||||
|         void DoPut() final {}; |         void DoPut() final {}; | ||||||
|   | |||||||
| @@ -8,15 +8,14 @@ | |||||||
|  |  | ||||||
| #include "RESTAPI_inventory_handler.h" | #include "RESTAPI_inventory_handler.h" | ||||||
|  |  | ||||||
| #include "framework/RESTAPI_protocol.h" |  | ||||||
| #include "StorageService.h" | #include "StorageService.h" | ||||||
| #include "APConfig.h" | #include "APConfig.h" | ||||||
| #include "framework/RESTAPI_errors.h" |  | ||||||
| #include "AutoDiscovery.h" | #include "AutoDiscovery.h" | ||||||
| #include "sdks/SDK_gw.h" | #include "sdks/SDK_gw.h" | ||||||
| #include "sdks/SDK_sec.h" | #include "sdks/SDK_sec.h" | ||||||
| #include "RESTAPI/RESTAPI_db_helpers.h" | #include "RESTAPI/RESTAPI_db_helpers.h" | ||||||
| #include "SerialNumberCache.h" | #include "SerialNumberCache.h" | ||||||
|  | #include "DeviceTypeCache.h" | ||||||
|  |  | ||||||
| namespace OpenWifi{ | namespace OpenWifi{ | ||||||
|  |  | ||||||
| @@ -35,70 +34,92 @@ namespace OpenWifi{ | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     void RESTAPI_inventory_handler::DoGet() { |     void RESTAPI_inventory_handler::DoGet() { | ||||||
|  |  | ||||||
|         ProvObjects::InventoryTag Existing; |         ProvObjects::InventoryTag Existing; | ||||||
|         std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER,""); |         std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER, ""); | ||||||
|         if(SerialNumber.empty() || !DB_.GetRecord(RESTAPI::Protocol::SERIALNUMBER,SerialNumber,Existing)) { |         Logger().debug(Poco::format("%s: Retrieving inventory information.", SerialNumber)); | ||||||
|  |         if (SerialNumber.empty() || !DB_.GetRecord(RESTAPI::Protocol::SERIALNUMBER, SerialNumber, Existing)) { | ||||||
|             return NotFound(); |             return NotFound(); | ||||||
|         } |         } | ||||||
|  |         Logger().debug( | ||||||
|  |                 Poco::format("%s,%s: Retrieving inventory information.", Existing.serialNumber, Existing.info.id)); | ||||||
|  |  | ||||||
|         Poco::JSON::Object Answer; |         Poco::JSON::Object Answer; | ||||||
|         std::string Arg; |         std::string Arg; | ||||||
|         if(HasParameter("config",Arg) && Arg=="true") { |         if (HasParameter("config", Arg) && Arg == "true") { | ||||||
|             bool Explain = (HasParameter("explain",Arg) && Arg == "true"); |             bool Explain = (HasParameter("explain", Arg) && Arg == "true"); | ||||||
|             APConfig    Device(SerialNumber,Existing.deviceType,Logger(), Explain); |             APConfig Device(SerialNumber, Existing.deviceType, Logger(), Explain); | ||||||
|  |  | ||||||
|             Poco::JSON::Object::Ptr  Configuration; |             auto Configuration = Poco::makeShared<Poco::JSON::Object>(); | ||||||
|             if(Device.Get(Configuration)) { |             if (Device.Get(Configuration)) { | ||||||
|                 Answer.set("config", Configuration); |                 Answer.set("config", Configuration); | ||||||
|                 if(Explain) |                 if (Explain) | ||||||
|                     Answer.set("explanation", Device.Explanation()); |                     Answer.set("explanation", Device.Explanation()); | ||||||
|             } else { |             } else { | ||||||
|                 Answer.set("config","none"); |                 Answer.set("config", "none"); | ||||||
|             } |             } | ||||||
|             return ReturnObject(Answer); |             return ReturnObject(Answer); | ||||||
|         } else if(HasParameter("firmwareOptions", Arg) && Arg=="true") { |         } else if (GetBoolParameter("firmwareOptions", false)) { | ||||||
|             ProvObjects::FIRMWARE_UPGRADE_RULES Rules; |             ProvObjects::DeviceRules Rules; | ||||||
|  |             StorageService()->InventoryDB().EvaluateDeviceSerialNumberRules(SerialNumber, Rules); | ||||||
|             StorageService()->InventoryDB().FindFirmwareOptions(SerialNumber,Rules); |             Answer.set("firmwareUpgrade", Rules.firmwareUpgrade); | ||||||
|  |             Answer.set("firmwareRCOnly", Rules.rcOnly == "yes"); | ||||||
|             if(Rules == ProvObjects::dont_upgrade) { |             return ReturnObject(Answer); | ||||||
|                 Answer.set("firmwareUpgrade","no"); |         } else if(GetBoolParameter("rrmSettings",false)) { | ||||||
|  |             ProvObjects::DeviceRules Rules; | ||||||
|  |             StorageService()->InventoryDB().EvaluateDeviceSerialNumberRules(SerialNumber, Rules); | ||||||
|  |             if(Rules.rrm=="no" || Rules.rrm=="inherit") { | ||||||
|  |                 Answer.set("rrm", Rules.rrm); | ||||||
|             } else { |             } else { | ||||||
|                 Answer.set("firmwareUpgrade","yes"); |                 ProvObjects::RRMDetails D; | ||||||
|                 if(Rules == ProvObjects::upgrade_release_only) |                 Poco::JSON::Parser  P; | ||||||
|                     Answer.set("firmwareRCOnly", Rules == ProvObjects::upgrade_release_only ); |                 try { | ||||||
|  |                     auto Obj = P.parse(Rules.rrm).extract<Poco::JSON::Object::Ptr>(); | ||||||
|  |                     Answer.set("rrm", Obj); | ||||||
|  |                 } catch (...) { | ||||||
|  |                     Answer.set("rrm", "invalid"); | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|             return ReturnObject(Answer); |             return ReturnObject(Answer); | ||||||
|         } else if(HasParameter("applyConfiguration",Arg) && Arg=="true") { |         } else if(GetBoolParameter("applyConfiguration", false)) { | ||||||
|             APConfig Device(SerialNumber, Existing.deviceType, Logger(), false); |             Logger().debug(Poco::format("%s: Retrieving configuration.",Existing.serialNumber)); | ||||||
|             Poco::JSON::Object::Ptr Configuration; |             auto Device = std::make_shared<APConfig>(SerialNumber, Existing.deviceType, Logger(), false); | ||||||
|  |             auto Configuration = Poco::makeShared<Poco::JSON::Object>(); | ||||||
|             Types::StringVec Errors, Warnings; |  | ||||||
|             Poco::JSON::Object ErrorsObj, WarningsObj; |             Poco::JSON::Object ErrorsObj, WarningsObj; | ||||||
|             int ErrorCode; |             ProvObjects::InventoryConfigApplyResult Results; | ||||||
|             if (Device.Get(Configuration)) { |             Logger().debug(Poco::format("%s: Computing configuration.",Existing.serialNumber)); | ||||||
|                 Poco::JSON::Object::Ptr Response; |             if (Device->Get(Configuration)) { | ||||||
|  |                 std::ostringstream OS; | ||||||
|  |                 Configuration->stringify(OS); | ||||||
|  |                 Results.appliedConfiguration = OS.str(); | ||||||
|  |                 auto Response=Poco::makeShared<Poco::JSON::Object>(); | ||||||
|  |                 Logger().debug(Poco::format("%s: Sending configuration push.",Existing.serialNumber)); | ||||||
|                 if (SDK::GW::Device::Configure(this, SerialNumber, Configuration, Response)) { |                 if (SDK::GW::Device::Configure(this, SerialNumber, Configuration, Response)) { | ||||||
|                     std::ostringstream os; |                     Logger().debug(Poco::format("%s: Sending configuration pushed.",Existing.serialNumber)); | ||||||
|                     Response->stringify(os); |                     GetRejectedLines(Response, Results.warnings); | ||||||
|                     // std::cout << "Success: " << os.str() << std::endl; |                     Results.errorCode = 0; | ||||||
|                     GetRejectedLines(Response, Warnings); |  | ||||||
|                     ErrorCode = 0; |  | ||||||
|                 } else { |                 } else { | ||||||
|                     std::ostringstream os; |                     Logger().debug(Poco::format("%s: Sending configuration failed.",Existing.serialNumber)); | ||||||
|                     Response->stringify(os); |                     Results.errorCode = 1; | ||||||
|                     ErrorCode = 1; |  | ||||||
|                     // std::cout << "Failure: " << os.str() << std::endl; |  | ||||||
|                 } |                 } | ||||||
|                 Answer.set("appliedConfiguration", Configuration); |  | ||||||
|                 Answer.set("response", Response); |  | ||||||
|             } else { |             } else { | ||||||
|                 Answer.set("appliedConfiguration", ""); |                 Logger().debug(Poco::format("%s: Configuration is bad.",Existing.serialNumber)); | ||||||
|                 ErrorCode = 1; |                 Results.errorCode = 1; | ||||||
|  |             } | ||||||
|  |             Results.to_json(Answer); | ||||||
|  |             return ReturnObject(Answer); | ||||||
|  |         } else if(GetBoolParameter("resolveConfig", false)) { | ||||||
|  |             Logger().debug(Poco::format("%s: Retrieving configuration.",Existing.serialNumber)); | ||||||
|  |             auto Device = std::make_shared<APConfig>(SerialNumber, Existing.deviceType, Logger(), false); | ||||||
|  |             auto Configuration = Poco::makeShared<Poco::JSON::Object>(); | ||||||
|  |             Poco::JSON::Object ErrorsObj, WarningsObj; | ||||||
|  |             ProvObjects::InventoryConfigApplyResult Results; | ||||||
|  |             Logger().debug(Poco::format("%s: Computing configuration.",Existing.serialNumber)); | ||||||
|  |             if (Device->Get(Configuration)) { | ||||||
|  |                 Answer.set("configuration", Configuration); | ||||||
|  |             } else { | ||||||
|  |                 Answer.set("error", 1); | ||||||
|             } |             } | ||||||
|             Answer.set("errorCode", ErrorCode); |  | ||||||
|             RESTAPI_utils::field_to_json(Answer, "errors", Errors); |  | ||||||
|             RESTAPI_utils::field_to_json(Answer, "warnings", Warnings); |  | ||||||
|             return ReturnObject(Answer); |             return ReturnObject(Answer); | ||||||
|         }   else if(QB_.AdditionalInfo) { |         }   else if(QB_.AdditionalInfo) { | ||||||
|             AddExtendedInfo(Existing,Answer); |             AddExtendedInfo(Existing,Answer); | ||||||
| @@ -114,36 +135,38 @@ namespace OpenWifi{ | |||||||
|             return NotFound(); |             return NotFound(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(!Existing.venue.empty()) |         MoveUsage(StorageService()->PolicyDB(),DB_,Existing.managementPolicy,"",Existing.info.id); | ||||||
|             StorageService()->VenueDB().DeleteDevice("id",Existing.venue,Existing.info.id); |         RemoveMembership(StorageService()->VenueDB(),&ProvObjects::Venue::configurations,Existing.venue,Existing.info.id); | ||||||
|  |         RemoveMembership(StorageService()->EntityDB(),&ProvObjects::Entity::configurations,Existing.entity,Existing.info.id); | ||||||
|  |         MoveUsage(StorageService()->LocationDB(),DB_,Existing.location,"",Existing.info.id); | ||||||
|  |         MoveUsage(StorageService()->ContactDB(),DB_,Existing.contact,"",Existing.info.id); | ||||||
|  |  | ||||||
|         if(!Existing.entity.empty()) |         if(!Existing.deviceConfiguration.empty()) { | ||||||
|             StorageService()->EntityDB().DeleteDevice("id",Existing.entity,Existing.info.id); |             ProvObjects::DeviceConfiguration    DC; | ||||||
|  |             if(StorageService()->ConfigurationDB().GetRecord("id", Existing.deviceConfiguration, DC)) { | ||||||
|  |                 if(DC.subscriberOnly) | ||||||
|  |                     StorageService()->ConfigurationDB().DeleteRecord("id", Existing.deviceConfiguration); | ||||||
|  |                 else | ||||||
|  |                     StorageService()->ConfigurationDB().DeleteInUse("id", Existing.deviceConfiguration, DB_.Prefix(), | ||||||
|  |                                                                     Existing.info.id); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|         if(!Existing.location.empty()) |         MoveUsage(StorageService()->PolicyDB(),DB_,Existing.managementPolicy,"",Existing.info.id); | ||||||
|             StorageService()->LocationDB().DeleteInUse("id",Existing.location,DB_.Prefix(),Existing.info.id); |         MoveUsage(StorageService()->LocationDB(),DB_,Existing.location,"",Existing.info.id); | ||||||
|  |         MoveUsage(StorageService()->ContactDB(),DB_,Existing.contact,"",Existing.info.id); | ||||||
|         if(!Existing.contact.empty()) |         MoveUsage(StorageService()->ConfigurationDB(),DB_,Existing.deviceConfiguration,"",Existing.info.id); | ||||||
|             StorageService()->ContactDB().DeleteInUse("id",Existing.contact,DB_.Prefix(),Existing.info.id); |         ManageMembership(StorageService()->EntityDB(),&ProvObjects::Entity::devices,Existing.entity,"",Existing.info.id); | ||||||
|  |         ManageMembership(StorageService()->VenueDB(),&ProvObjects::Venue::devices,Existing.venue,"",Existing.info.id); | ||||||
|         if(!Existing.deviceConfiguration.empty()) |         DB_.DeleteRecord("id", Existing.info.id); | ||||||
|             StorageService()->ConfigurationDB().DeleteInUse("id", Existing.deviceConfiguration, DB_.Prefix(), Existing.info.id); |  | ||||||
|  |  | ||||||
|         if(DB_.DeleteRecord("id", Existing.info.id)) { |  | ||||||
|             DB_.DeleteRecord(RESTAPI::Protocol::ID, Existing.info.id); |  | ||||||
|         SerialNumberCache()->DeleteSerialNumber(SerialNumber); |         SerialNumberCache()->DeleteSerialNumber(SerialNumber); | ||||||
|         return OK(); |         return OK(); | ||||||
|     } |     } | ||||||
|         InternalError(RESTAPI::Errors::CouldNotBeDeleted); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     static bool ValidDevClass(const std::string &D) { |  | ||||||
|         const static std::vector<std::string> Classes{ "any", "entity", "subscriber" , "venue" }; |  | ||||||
|         return std::find(cbegin(Classes), cend(Classes), D)!=cend(Classes); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void RESTAPI_inventory_handler::DoPost() { |     void RESTAPI_inventory_handler::DoPost() { | ||||||
|         std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER,""); |         std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER,""); | ||||||
|  |         Poco::toLowerInPlace(SerialNumber); | ||||||
|         if(SerialNumber.empty()) { |         if(SerialNumber.empty()) { | ||||||
|             return BadRequest(RESTAPI::Errors::MissingSerialNumber); |             return BadRequest(RESTAPI::Errors::MissingSerialNumber); | ||||||
|         } |         } | ||||||
| @@ -153,24 +176,37 @@ namespace OpenWifi{ | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(DB_.Exists(RESTAPI::Protocol::SERIALNUMBER,SerialNumber)) { |         if(DB_.Exists(RESTAPI::Protocol::SERIALNUMBER,SerialNumber)) { | ||||||
|             return BadRequest(RESTAPI::Errors::SerialNumberExists + " (" + SerialNumber + ")"); |             return BadRequest(RESTAPI::Errors::SerialNumberExists); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         auto Obj = ParseStream(); |         const auto & RawObject = ParsedBody_; | ||||||
|         ProvObjects::InventoryTag NewObject; |         ProvObjects::InventoryTag NewObject; | ||||||
|         if (!NewObject.from_json(Obj)) { |         if (!NewObject.from_json(RawObject)) { | ||||||
|             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); |             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(!ValidDevClass(NewObject.devClass)) { |         NormalizeMac(NewObject.serialNumber); | ||||||
|  |         if(SerialNumber!=NewObject.serialNumber) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::SerialNumberMismatch); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if((RawObject->has("deviceRules") && !ValidDeviceRules(NewObject.deviceRules,*this))) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(!Provisioning::DeviceClass::Validate(NewObject.devClass.c_str())) { | ||||||
|             return BadRequest(RESTAPI::Errors::InvalidDeviceClass); |             return BadRequest(RESTAPI::Errors::InvalidDeviceClass); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(!ProvObjects::CreateObjectInfo(Obj, UserInfo_.userinfo, NewObject.info)) { |         if(NewObject.devClass.empty()) { | ||||||
|  |             NewObject.devClass = Provisioning::DeviceClass::ANY; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(!ProvObjects::CreateObjectInfo(RawObject, UserInfo_.userinfo, NewObject.info)) { | ||||||
|             return BadRequest( RESTAPI::Errors::NameMustBeSet); |             return BadRequest( RESTAPI::Errors::NameMustBeSet); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(NewObject.deviceType.empty() || !StorageService()->IsAcceptableDeviceType(NewObject.deviceType)) { |         if(NewObject.deviceType.empty() || !DeviceTypeCache()->IsAcceptableDeviceType(NewObject.deviceType)) { | ||||||
|             return BadRequest(RESTAPI::Errors::InvalidDeviceTypes); |             return BadRequest(RESTAPI::Errors::InvalidDeviceTypes); | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -202,39 +238,21 @@ namespace OpenWifi{ | |||||||
|             return BadRequest(RESTAPI::Errors::UnknownManagementPolicyUUID); |             return BadRequest(RESTAPI::Errors::UnknownManagementPolicyUUID); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(!NewObject.venue.empty()) { |         RESTAPI::Errors::msg Error=RESTAPI::Errors::SUCCESS; | ||||||
|             nlohmann::json state; |         auto ObjectsCreated = CreateObjects(NewObject,*this,Error); | ||||||
|             state["method"] = "assignedTo"; |         if(Error.err_num != 0) { | ||||||
|             state["venue"] = NewObject.venue; |             return BadRequest(Error); | ||||||
|             state["date"] = std::time(nullptr); |  | ||||||
|             NewObject.state = to_string(state); |  | ||||||
|         } else if (!NewObject.entity.empty()) { |  | ||||||
|             nlohmann::json state; |  | ||||||
|             state["method"] = "assignedTo"; |  | ||||||
|             state["entity"] = NewObject.entity; |  | ||||||
|             state["date"] = std::time(nullptr); |  | ||||||
|             NewObject.state = to_string(state); |  | ||||||
|         } else { |  | ||||||
|             nlohmann::json state; |  | ||||||
|             state["method"] = "created"; |  | ||||||
|             state["date"] = std::time(nullptr); |  | ||||||
|             NewObject.state = to_string(state); |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(DB_.CreateRecord(NewObject)) { |         if(DB_.CreateRecord(NewObject)) { | ||||||
|  |             SDK::GW::Device::SetOwnerShip(this, SerialNumber, NewObject.entity, NewObject.venue, NewObject.subscriber); | ||||||
|             SerialNumberCache()->AddSerialNumber(SerialNumber,NewObject.deviceType); |             SerialNumberCache()->AddSerialNumber(SerialNumber,NewObject.deviceType); | ||||||
|             if (!NewObject.venue.empty()) |             MoveUsage(StorageService()->PolicyDB(),DB_,"",NewObject.managementPolicy,NewObject.info.id); | ||||||
|                 StorageService()->VenueDB().AddDevice("id",NewObject.venue,NewObject.info.id); |             MoveUsage(StorageService()->LocationDB(),DB_,"",NewObject.location,NewObject.info.id); | ||||||
|             if (!NewObject.entity.empty()) |             MoveUsage(StorageService()->ContactDB(),DB_,"",NewObject.contact,NewObject.info.id); | ||||||
|                 StorageService()->EntityDB().AddDevice("id",NewObject.entity,NewObject.info.id); |             MoveUsage(StorageService()->ConfigurationDB(),DB_,"",NewObject.deviceConfiguration,NewObject.info.id); | ||||||
|             if (!NewObject.location.empty()) |             ManageMembership(StorageService()->EntityDB(),&ProvObjects::Entity::devices,"",NewObject.entity,NewObject.info.id); | ||||||
|                 StorageService()->LocationDB().AddInUse("id",NewObject.location,DB_.Prefix(),NewObject.info.id); |             ManageMembership(StorageService()->VenueDB(),&ProvObjects::Venue::devices,"",NewObject.venue,NewObject.info.id); | ||||||
|             if (!NewObject.contact.empty()) |  | ||||||
|                 StorageService()->ContactDB().AddInUse("id",NewObject.contact,DB_.Prefix(),NewObject.info.id); |  | ||||||
|             if (!NewObject.deviceConfiguration.empty()) |  | ||||||
|                 StorageService()->ConfigurationDB().AddInUse("id",NewObject.deviceConfiguration,DB_.Prefix(),NewObject.info.id); |  | ||||||
|             if (!NewObject.managementPolicy.empty()) |  | ||||||
|                 StorageService()->PolicyDB().AddInUse("id",NewObject.managementPolicy,DB_.Prefix(),NewObject.info.id); |  | ||||||
|  |  | ||||||
|             ProvObjects::InventoryTag   NewTag; |             ProvObjects::InventoryTag   NewTag; | ||||||
|             DB_.GetRecord("id",NewObject.info.id,NewTag); |             DB_.GetRecord("id",NewObject.info.id,NewTag); | ||||||
| @@ -245,163 +263,71 @@ namespace OpenWifi{ | |||||||
|         InternalError(RESTAPI::Errors::RecordNotCreated); |         InternalError(RESTAPI::Errors::RecordNotCreated); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void RESTAPI_inventory_handler::PerformClaim(const std::string &SerialNumber, const std::string &Claimer, std::string & ClaimId, uint64_t &ErrorCode, Poco::JSON::Object &Answer ) { |  | ||||||
|  |  | ||||||
|         if(UserInfo_.userinfo.userRole==SecurityObjects::SUBSCRIBER && Claimer!=UserInfo_.userinfo.id) { |  | ||||||
|             return UnAuthorized(RESTAPI::Errors::InsufficientAccessRights, ACCESS_DENIED); |  | ||||||
|         } else if(UserInfo_.userinfo.userRole==SecurityObjects::ROOT && !SDK::Sec::Subscriber::Exists(this, Claimer)) { |  | ||||||
|             return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters); |  | ||||||
|         } else if(UserInfo_.userinfo.userRole!=SecurityObjects::ROOT && UserInfo_.userinfo.userRole!=SecurityObjects::SUBSCRIBER) { |  | ||||||
|             return UnAuthorized(RESTAPI::Errors::InsufficientAccessRights,ACCESS_DENIED); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         uint64_t Now = std::time(nullptr); |  | ||||||
|  |  | ||||||
|         // if the device exists, check the status to see if we would follow this claim. |  | ||||||
|         ProvObjects::InventoryTag   ExistingDevice; |  | ||||||
|         if(DB_.GetRecord("serialNumber",SerialNumber,ExistingDevice)) { |  | ||||||
|             // Device is already in there... so we could have claimed that device before, or someone else uses it |  | ||||||
|             // or, it is free and clear: it connected but nobody has ever used it... |  | ||||||
|             if(!ExistingDevice.state.empty()) { |  | ||||||
|                 try { |  | ||||||
|                     Poco::JSON::Parser P; |  | ||||||
|                     auto StateDoc = P.parse(ExistingDevice.state).extract<Poco::JSON::Object::Ptr>(); |  | ||||||
|                     if (StateDoc->has("method")) { |  | ||||||
|                         auto Method = StateDoc->get("method").toString(); |  | ||||||
|                         if(Method=="claiming") { |  | ||||||
|                             auto RecordedClaimer = StateDoc->get("claimer").toString(); |  | ||||||
|                             auto RecordedClaimId = StateDoc->get("claimId").toString(); |  | ||||||
|                             if(Claimer==RecordedClaimer) { |  | ||||||
|                                 ErrorCode = 3; |  | ||||||
|                                 ClaimId = RecordedClaimId; |  | ||||||
|                                 Answer.set("claimer", Claimer); |  | ||||||
|                                 Answer.set("claimId", RecordedClaimId); |  | ||||||
|                                 Answer.set("errorCode",ErrorCode); |  | ||||||
|                                 Answer.set("date", Now); |  | ||||||
|                                 Answer.set("reason", "Claim already in progress"); |  | ||||||
|                                 return; |  | ||||||
|                             } |  | ||||||
|                             ErrorCode = 1; |  | ||||||
|                             ClaimId = RecordedClaimId; |  | ||||||
|                             Answer.set("claimer", Claimer); |  | ||||||
|                             Answer.set("claimId", RecordedClaimId); |  | ||||||
|                             Answer.set("errorCode",ErrorCode); |  | ||||||
|                             Answer.set("date", Now); |  | ||||||
|                             Answer.set("reason", "Claimed by another user: "+ RecordedClaimer); |  | ||||||
|                             return; |  | ||||||
|                         } else if(Method=="claimed") { |  | ||||||
|                             //  We already own this one... |  | ||||||
|                             if(Claimer==ExistingDevice.subscriber) { |  | ||||||
|                                 auto RecordedClaimer = StateDoc->get("claimer").toString(); |  | ||||||
|                                 auto RecordedClaimId = StateDoc->get("claimId").toString(); |  | ||||||
|                                 ErrorCode = 0; |  | ||||||
|                                 ClaimId = RecordedClaimId; |  | ||||||
|                                 Answer.set("claimer", Claimer); |  | ||||||
|                                 Answer.set("claimId", RecordedClaimId); |  | ||||||
|                                 Answer.set("errorCode",ErrorCode); |  | ||||||
|                                 Answer.set("date", Now); |  | ||||||
|                                 Answer.set("reason", "Success"); |  | ||||||
|                                 return; |  | ||||||
|                             } else { |  | ||||||
|                             //  Someone else has claimed this device. |  | ||||||
|                                 ErrorCode = 1; |  | ||||||
|                                 ClaimId = ""; |  | ||||||
|                                 Answer.set("claimer", Claimer); |  | ||||||
|                                 Answer.set("claimId", ""); |  | ||||||
|                                 Answer.set("errorCode",ErrorCode); |  | ||||||
|                                 Answer.set("date", Now); |  | ||||||
|                                 Answer.set("reason", "Claimed by another user: "+ ExistingDevice.subscriber); |  | ||||||
|                                 return; |  | ||||||
|                             } |  | ||||||
|                        } else if(Method=="auto-discovery") { |  | ||||||
|                             if(StateDoc->has("assignedTo")) { |  | ||||||
|                                 auto AssignedTo = StateDoc->get("assignedTo").toString(); |  | ||||||
|                                 ErrorCode = 1; |  | ||||||
|                                 ClaimId = ""; |  | ||||||
|                                 Answer.set("claimer", Claimer); |  | ||||||
|                                 Answer.set("claimId", ""); |  | ||||||
|                                 Answer.set("errorCode",ErrorCode); |  | ||||||
|                                 Answer.set("date", Now); |  | ||||||
|                                 Answer.set("reason", "Claimed by venue: '" + ExistingDevice.venue + "' or entity: '" + ExistingDevice.entity + "'"); |  | ||||||
|                                 return; |  | ||||||
|                             } |  | ||||||
|  |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
|                 } catch (...) { |  | ||||||
|  |  | ||||||
|                 } |  | ||||||
|             } else { |  | ||||||
|  |  | ||||||
|             } |  | ||||||
|         } else { |  | ||||||
|             //  Device does not exist, so claim it for now. |  | ||||||
|             ProvObjects::InventoryTag   NewDevice; |  | ||||||
|             NewDevice.info.created = NewDevice.info.modified = Now; |  | ||||||
|             NewDevice.info.id = MicroService::instance().CreateUUID(); |  | ||||||
|             NewDevice.info.name = SerialNumber; |  | ||||||
|             NewDevice.info.notes.push_back(SecurityObjects::NoteInfo{ .created=Now, |  | ||||||
|                                                                       .createdBy=UserInfo_.userinfo.email, |  | ||||||
|                                                                       .note="Claim started for device"}); |  | ||||||
|             NewDevice.info.description = "Subscriber device"; |  | ||||||
|             NewDevice.subscriber = UserInfo_.userinfo.id; |  | ||||||
|             NewDevice.deviceType = "unknown"; |  | ||||||
|             nlohmann::json StateDoc; |  | ||||||
|  |  | ||||||
|             ClaimId = MicroService::instance().CreateUUID(); |  | ||||||
|  |  | ||||||
|             StateDoc["method"] = "claiming"; |  | ||||||
|             StateDoc["date"] = Now; |  | ||||||
|             StateDoc["claimer"] = Claimer; |  | ||||||
|             StateDoc["claimId"] = ClaimId; |  | ||||||
|             NewDevice.state = StateDoc; |  | ||||||
|             ErrorCode = 0 ; |  | ||||||
|             DB_.CreateRecord(NewDevice); |  | ||||||
|  |  | ||||||
|             Answer.set("claimer", Claimer); |  | ||||||
|             Answer.set("claimId", ClaimId); |  | ||||||
|             Answer.set("errorCode",0); |  | ||||||
|             Answer.set("date", Now); |  | ||||||
|             Answer.set("reason", "Success"); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void RESTAPI_inventory_handler::DoPut() { |     void RESTAPI_inventory_handler::DoPut() { | ||||||
|  |  | ||||||
|         std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER,""); |         std::string SerialNumber = GetBinding(RESTAPI::Protocol::SERIALNUMBER,""); | ||||||
|  |  | ||||||
|         if(SerialNumber.empty() || !Utils::ValidSerialNumber(SerialNumber)) { |         if(SerialNumber.empty() || !Utils::ValidSerialNumber(SerialNumber)) { | ||||||
|             return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters); |             return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         std::string Claimer; |  | ||||||
|         if(HasParameter("claimer",Claimer) && !Claimer.empty()) { |  | ||||||
|             uint64_t ErrorCode; |  | ||||||
|             Poco::JSON::Object  Answer; |  | ||||||
|             std::string ClaimId; |  | ||||||
|             PerformClaim(SerialNumber, Claimer, ClaimId, ErrorCode, Answer); |  | ||||||
|             return ReturnObject(Answer); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         ProvObjects::InventoryTag   Existing; |         ProvObjects::InventoryTag   Existing; | ||||||
|         if(SerialNumber.empty() || !DB_.GetRecord(RESTAPI::Protocol::SERIALNUMBER,SerialNumber,Existing)) { |         if(SerialNumber.empty() || !DB_.GetRecord(RESTAPI::Protocol::SERIALNUMBER,SerialNumber,Existing)) { | ||||||
|             return NotFound(); |             return NotFound(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         auto RawObject = ParseStream(); |         auto RemoveSubscriber = GetParameter("removeSubscriber"); | ||||||
|  |         if(!RemoveSubscriber.empty()) { | ||||||
|  |             if(Existing.subscriber == RemoveSubscriber) { | ||||||
|  |                 Logger().information(Poco::format("%s: removing subscriber (%s)", SerialNumber, RemoveSubscriber)); | ||||||
|  |                 ProvObjects::DeviceConfiguration    DC; | ||||||
|  |                 if(StorageService()->ConfigurationDB().GetRecord("id",Existing.deviceConfiguration,DC)) { | ||||||
|  |                     Logger().information(Poco::format("%s: removing configuration for subscriber (%s)", SerialNumber, RemoveSubscriber)); | ||||||
|  |                     if(DC.subscriberOnly) { | ||||||
|  |                         if(!StorageService()->ConfigurationDB().DeleteRecord("id", Existing.deviceConfiguration)) { | ||||||
|  |                             Logger().debug("Could not delete the subscriber configuration"); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                     else { | ||||||
|  |                         Logger().debug("Configurations is not for a subscriber."); | ||||||
|  |                     } | ||||||
|  |                     Existing.deviceConfiguration = ""; | ||||||
|  |                 } | ||||||
|  |                 Existing.subscriber = ""; | ||||||
|  |                 Poco::JSON::Object state; | ||||||
|  |                 state.set("date",OpenWifi::Now()); | ||||||
|  |                 state.set("method","auto-discovery"); | ||||||
|  |                 state.set("last-operation", "returned to inventory"); | ||||||
|  |                 std::ostringstream OO; | ||||||
|  |                 state.stringify(OO); | ||||||
|  |                 Existing.state = OO.str(); | ||||||
|  |                 StorageService()->InventoryDB().UpdateRecord("id",Existing.info.id,Existing); | ||||||
|  |                 RemoveMembership(StorageService()->EntityDB(),&ProvObjects::Entity::devices,"id",Existing.info.id); | ||||||
|  |                 Poco::JSON::Object  Answer; | ||||||
|  |                 Existing.to_json(Answer); | ||||||
|  |                 SDK::GW::Device::SetSubscriber(nullptr, SerialNumber, ""); | ||||||
|  |                 return ReturnObject(Answer); | ||||||
|  |             } else { | ||||||
|  |                 Logger().information(Poco::format("%s: wrong subscriber (%s)", SerialNumber, RemoveSubscriber)); | ||||||
|  |             } | ||||||
|  |             return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         const auto & RawObject = ParsedBody_; | ||||||
|         ProvObjects::InventoryTag   NewObject; |         ProvObjects::InventoryTag   NewObject; | ||||||
|         if(!NewObject.from_json(RawObject)) { |         if(!NewObject.from_json(RawObject)) { | ||||||
|             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); |             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(!ValidDevClass(NewObject.devClass)) { |         if((RawObject->has("deviceRules") && !ValidDeviceRules(NewObject.deviceRules,*this))) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(!Provisioning::DeviceClass::Validate(NewObject.devClass.c_str())) { | ||||||
|             return BadRequest(RESTAPI::Errors::InvalidDeviceClass); |             return BadRequest(RESTAPI::Errors::InvalidDeviceClass); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(!NewObject.deviceType.empty()) { |         if(!NewObject.deviceType.empty()) { | ||||||
|             if(!StorageService()->IsAcceptableDeviceType(NewObject.deviceType)) { |             if(!DeviceTypeCache()->IsAcceptableDeviceType(NewObject.deviceType)) { | ||||||
|                 return BadRequest(RESTAPI::Errors::InvalidDeviceTypes); |                 return BadRequest(RESTAPI::Errors::InvalidDeviceTypes); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @@ -410,61 +336,38 @@ namespace OpenWifi{ | |||||||
|             return BadRequest(RESTAPI::Errors::NameMustBeSet); |             return BadRequest(RESTAPI::Errors::NameMustBeSet); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         std::string NewVenue, NewEntity, NewLocation, NewContact, NewConfiguration, NewPolicy; |         if(RawObject->has("deviceRules")) | ||||||
|         bool    MovingVenue=false, |             Existing.deviceRules = NewObject.deviceRules; | ||||||
|                 MovingEntity=false, |  | ||||||
|                 MovingLocation=false, |  | ||||||
|                 MovingContact=false, |  | ||||||
|                 MovingConfiguration=false, |  | ||||||
|                 MovingPolicy=false; |  | ||||||
|  |  | ||||||
|         AssignIfPresent(RawObject, "rrm",Existing.rrm); |         std::string FromPolicy, ToPolicy; | ||||||
|  |         if(!CreateMove(RawObject,"managementPolicy",&InventoryDB::RecordName::managementPolicy, Existing, FromPolicy, | ||||||
|         if(AssignIfPresent(RawObject, "venue",NewVenue)) { |                        ToPolicy, StorageService()->PolicyDB())) | ||||||
|             if(!NewVenue.empty() && !StorageService()->VenueDB().Exists("id",NewVenue)) { |  | ||||||
|                 return BadRequest(RESTAPI::Errors::VenueMustExist); |  | ||||||
|             } |  | ||||||
|             MovingVenue = Existing.venue != NewVenue; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if(AssignIfPresent(RawObject, "entity",NewEntity)) { |  | ||||||
|             if(!NewEntity.empty() && !StorageService()->EntityDB().Exists("id",NewEntity)) { |  | ||||||
|             return BadRequest(RESTAPI::Errors::EntityMustExist); |             return BadRequest(RESTAPI::Errors::EntityMustExist); | ||||||
|             } |  | ||||||
|             MovingEntity = Existing.entity != NewEntity; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if(!NewEntity.empty() && !NewVenue.empty()) { |         std::string FromEntity, ToEntity; | ||||||
|             return BadRequest(RESTAPI::Errors::NotBoth); |         if(!CreateMove(RawObject,"entity",&InventoryDB::RecordName::entity, Existing, FromEntity, ToEntity, | ||||||
|         } |                        StorageService()->EntityDB())) | ||||||
|  |             return BadRequest(RESTAPI::Errors::EntityMustExist); | ||||||
|  |  | ||||||
|         if(AssignIfPresent(RawObject, "location",NewLocation)) { |         std::string FromVenue, ToVenue; | ||||||
|             if(!NewLocation.empty() && !StorageService()->LocationDB().Exists("id",NewLocation)) { |         if(!CreateMove(RawObject,"venue",&InventoryDB::RecordName::venue, Existing, FromVenue, ToVenue, | ||||||
|                 return BadRequest(RESTAPI::Errors::LocationMustExist); |                        StorageService()->VenueDB())) | ||||||
|             } |             return BadRequest(RESTAPI::Errors::VenueMustExist); | ||||||
|             MovingLocation = Existing.location != NewLocation; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if(AssignIfPresent(RawObject, "contact",NewContact)) { |         std::string FromLocation, ToLocation; | ||||||
|             if(!NewContact.empty() && !StorageService()->ContactDB().Exists("id",NewContact)) { |         if(!CreateMove(RawObject,"location",&InventoryDB::RecordName::location, Existing, FromLocation, ToLocation, | ||||||
|                 return BadRequest(RESTAPI::Errors::ContactMustExist); |                        StorageService()->LocationDB())) | ||||||
|             } |             return BadRequest(RESTAPI::Errors::VenueMustExist); | ||||||
|             MovingContact = Existing.contact != NewContact; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if(AssignIfPresent(RawObject, "deviceConfiguration",NewConfiguration)) { |         std::string FromContact, ToContact; | ||||||
|             if(!NewConfiguration.empty() && !StorageService()->ConfigurationDB().Exists("id",NewConfiguration)) { |         if(!CreateMove(RawObject,"contact",&InventoryDB::RecordName::contact, Existing, FromContact, ToContact, | ||||||
|  |                        StorageService()->ContactDB())) | ||||||
|  |             return BadRequest(RESTAPI::Errors::VenueMustExist); | ||||||
|  |  | ||||||
|  |         std::string FromConfiguration, ToConfiguration; | ||||||
|  |         if(!CreateMove(RawObject,"deviceConfiguration",&InventoryDB::RecordName::deviceConfiguration, Existing, | ||||||
|  |                        FromConfiguration, ToConfiguration, StorageService()->ConfigurationDB())) | ||||||
|             return BadRequest(RESTAPI::Errors::ConfigurationMustExist); |             return BadRequest(RESTAPI::Errors::ConfigurationMustExist); | ||||||
|             } |  | ||||||
|             MovingConfiguration = Existing.deviceConfiguration != NewConfiguration; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if(AssignIfPresent(RawObject, "managementPolicy",NewPolicy)) { |  | ||||||
|             if(!NewPolicy.empty() && !StorageService()->PolicyDB().Exists("id",NewPolicy)) { |  | ||||||
|                 return BadRequest(RESTAPI::Errors::UnknownManagementPolicyUUID); |  | ||||||
|             } |  | ||||||
|             MovingPolicy = Existing.managementPolicy != NewPolicy; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         std::string NewSubScriber; |         std::string NewSubScriber; | ||||||
|         if(AssignIfPresent(RawObject, "subscriber", NewSubScriber)) { |         if(AssignIfPresent(RawObject, "subscriber", NewSubScriber)) { | ||||||
| @@ -490,77 +393,30 @@ namespace OpenWifi{ | |||||||
|             Existing.state = NewObject.state; |             Existing.state = NewObject.state; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         std::string Arg; |         RESTAPI::Errors::msg Error=RESTAPI::Errors::SUCCESS; | ||||||
|         bool UnAssign=false; |         auto ObjectsCreated = CreateObjects(NewObject,*this,Error); | ||||||
|         if(HasParameter("unassign", Arg) && Arg=="true") { |         if(Error.err_num != 0) { | ||||||
|             UnAssign=true; |             return BadRequest(Error); | ||||||
|             if(!Existing.venue.empty()) { |         } | ||||||
|                 StorageService()->VenueDB().DeleteDevice("id",Existing.venue,Existing.info.id); |  | ||||||
|             } else if(!Existing.entity.empty()) { |         if(!ObjectsCreated.empty()) { | ||||||
|                 StorageService()->EntityDB().DeleteDevice("id",Existing.entity,Existing.info.id); |             auto it = ObjectsCreated.find("configuration"); | ||||||
|  |             if(it!=ObjectsCreated.end()) { | ||||||
|  |                 FromConfiguration=""; | ||||||
|  |                 ToConfiguration=it->second; | ||||||
|  |                 Existing.deviceConfiguration=ToConfiguration; | ||||||
|             } |             } | ||||||
|             if(!Existing.location.empty()) |  | ||||||
|                 StorageService()->LocationDB().DeleteInUse("id",Existing.location,DB_.Prefix(),Existing.info.id); |  | ||||||
|             if(!Existing.contact.empty()) |  | ||||||
|                 StorageService()->ContactDB().DeleteInUse("id",Existing.contact,DB_.Prefix(),Existing.info.id); |  | ||||||
|             if(!Existing.deviceConfiguration.empty()) |  | ||||||
|                 StorageService()->ConfigurationDB().DeleteInUse("id",Existing.deviceConfiguration,DB_.Prefix(),Existing.info.id); |  | ||||||
|             if(!Existing.managementPolicy.empty()) |  | ||||||
|                 StorageService()->PolicyDB().DeleteInUse("id",Existing.managementPolicy,DB_.Prefix(),Existing.info.id); |  | ||||||
|             Existing.venue.clear(); |  | ||||||
|             Existing.entity.clear(); |  | ||||||
|             Existing.deviceConfiguration.clear(); |  | ||||||
|             Existing.contact.clear(); |  | ||||||
|             Existing.location.clear(); |  | ||||||
|             Existing.managementPolicy.clear(); |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(StorageService()->InventoryDB().UpdateRecord("id", Existing.info.id, Existing)) { |         if(StorageService()->InventoryDB().UpdateRecord("id", Existing.info.id, Existing)) { | ||||||
|             if(!UnAssign) { |             MoveUsage(StorageService()->PolicyDB(),DB_,FromPolicy,ToPolicy,Existing.info.id); | ||||||
|                 if(MovingEntity) { |             MoveUsage(StorageService()->LocationDB(),DB_,FromLocation,ToLocation,Existing.info.id); | ||||||
|                     if(!Existing.entity.empty()) |             MoveUsage(StorageService()->ContactDB(),DB_,FromContact,ToContact,Existing.info.id); | ||||||
|                         StorageService()->EntityDB().DeleteDevice("id",Existing.entity,Existing.info.id); |             MoveUsage(StorageService()->ConfigurationDB(),DB_,FromConfiguration,ToConfiguration,Existing.info.id); | ||||||
|                     if(!NewEntity.empty()) |             ManageMembership(StorageService()->EntityDB(),&ProvObjects::Entity::devices,FromEntity,ToEntity,Existing.info.id); | ||||||
|                         StorageService()->EntityDB().AddDevice("id", NewEntity, Existing.info.id); |             ManageMembership(StorageService()->VenueDB(),&ProvObjects::Venue::devices,FromVenue,ToVenue,Existing.info.id); | ||||||
|                     Existing.entity = NewEntity; |  | ||||||
|                 } |             SDK::GW::Device::SetOwnerShip(this, SerialNumber, Existing.entity, Existing.venue, Existing.subscriber); | ||||||
|                 if(MovingVenue) { |  | ||||||
|                     if(!Existing.venue.empty()) |  | ||||||
|                         StorageService()->VenueDB().DeleteDevice("id",Existing.venue,Existing.info.id); |  | ||||||
|                     if(!NewVenue.empty()) |  | ||||||
|                         StorageService()->VenueDB().AddDevice("id", NewVenue, Existing.info.id); |  | ||||||
|                     Existing.venue = NewVenue; |  | ||||||
|                 } |  | ||||||
|                 if(MovingConfiguration) { |  | ||||||
|                     if(!Existing.deviceConfiguration.empty()) |  | ||||||
|                         StorageService()->ConfigurationDB().DeleteInUse("id",Existing.deviceConfiguration,DB_.Prefix(),Existing.info.id); |  | ||||||
|                     if(!NewConfiguration.empty()) |  | ||||||
|                         StorageService()->ConfigurationDB().AddInUse("id",NewConfiguration,DB_.Prefix(),Existing.info.id); |  | ||||||
|                     Existing.deviceConfiguration = NewConfiguration; |  | ||||||
|                 } |  | ||||||
|                 if(MovingContact) { |  | ||||||
|                     if(!Existing.contact.empty()) |  | ||||||
|                         StorageService()->ContactDB().DeleteInUse("id",Existing.contact,DB_.Prefix(),Existing.info.id); |  | ||||||
|                     if(!NewContact.empty()) |  | ||||||
|                         StorageService()->ContactDB().AddInUse("id",NewContact,DB_.Prefix(),Existing.info.id); |  | ||||||
|                     Existing.contact = NewContact; |  | ||||||
|                 } |  | ||||||
|                 if(MovingLocation) { |  | ||||||
|                     if(!Existing.location.empty()) |  | ||||||
|                         StorageService()->LocationDB().DeleteInUse("id",Existing.location,DB_.Prefix(),Existing.info.id); |  | ||||||
|                     if(!NewLocation.empty()) |  | ||||||
|                         StorageService()->LocationDB().AddInUse("id",NewLocation,DB_.Prefix(),Existing.info.id); |  | ||||||
|                     Existing.location = NewLocation; |  | ||||||
|                 } |  | ||||||
|                 if(MovingPolicy) { |  | ||||||
|                     if(!Existing.managementPolicy.empty()) |  | ||||||
|                         StorageService()->PolicyDB().DeleteInUse("id",Existing.managementPolicy,DB_.Prefix(),Existing.info.id); |  | ||||||
|                     if(!NewPolicy.empty()) |  | ||||||
|                         StorageService()->PolicyDB().AddInUse("id",NewPolicy,DB_.Prefix(),Existing.info.id); |  | ||||||
|                     Existing.managementPolicy = NewPolicy; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             DB_.UpdateRecord("id", Existing.info.id, Existing); |  | ||||||
|  |  | ||||||
|             ProvObjects::InventoryTag   NewObjectCreated; |             ProvObjects::InventoryTag   NewObjectCreated; | ||||||
|             DB_.GetRecord("id", Existing.info.id, NewObjectCreated); |             DB_.GetRecord("id", Existing.info.id, NewObjectCreated); | ||||||
|   | |||||||
| @@ -22,17 +22,16 @@ namespace OpenWifi { | |||||||
|             Poco::Net::HTTPRequest::HTTP_OPTIONS}, |             Poco::Net::HTTPRequest::HTTP_OPTIONS}, | ||||||
|             Server, |             Server, | ||||||
|             TransactionId, |             TransactionId, | ||||||
|             Internal), |             Internal){} | ||||||
|             DB_(StorageService()->InventoryDB()){} |         static auto PathName() { return std::list<std::string>{"/api/v1/inventory/{serialNumber}"}; }; | ||||||
|         static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/inventory/{serialNumber}"}; }; |  | ||||||
|  |  | ||||||
|     private: |     private: | ||||||
|  |         InventoryDB     &DB_=StorageService()->InventoryDB(); | ||||||
|         void DoGet() final; |         void DoGet() final; | ||||||
|         void DoPost() final; |         void DoPost() final; | ||||||
|         void DoPut() final; |         void DoPut() final; | ||||||
|         void DoDelete() final; |         void DoDelete() final; | ||||||
|         void PerformClaim(const std::string &SerialNumber, const std::string & Claimer , |         void PerformClaim(const std::string &SerialNumber, const std::string & Claimer , | ||||||
|                           std::string & ClaimId, uint64_t &ErrorCode, Poco::JSON::Object &Answer); |                           std::string & ClaimId, uint64_t &ErrorCode, Poco::JSON::Object &Answer); | ||||||
|         InventoryDB     &DB_; |  | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -9,7 +9,6 @@ | |||||||
|  |  | ||||||
| #include "RESTAPI_inventory_list_handler.h" | #include "RESTAPI_inventory_list_handler.h" | ||||||
| #include "StorageService.h" | #include "StorageService.h" | ||||||
| #include "framework/RESTAPI_errors.h" |  | ||||||
| #include "RESTAPI/RESTAPI_db_helpers.h" | #include "RESTAPI/RESTAPI_db_helpers.h" | ||||||
|  |  | ||||||
| namespace OpenWifi{ | namespace OpenWifi{ | ||||||
| @@ -35,54 +34,77 @@ namespace OpenWifi{ | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     void RESTAPI_inventory_list_handler::DoGet() { |     void RESTAPI_inventory_list_handler::DoGet() { | ||||||
|         std::string UUID; |  | ||||||
|         std::string Arg; |  | ||||||
|  |  | ||||||
|         bool SerialOnly=false; |         if(GetBoolParameter("orderSpec")) { | ||||||
|         if(HasParameter("serialOnly",Arg) && Arg=="true") |             return ReturnFieldList(DB_,*this); | ||||||
|             SerialOnly=true; |         } | ||||||
|  |  | ||||||
|  |         bool SerialOnly=GetBoolParameter("serialOnly"); | ||||||
|  |  | ||||||
|  |         std::string UUID; | ||||||
|  |         std::string Arg,Arg2; | ||||||
|  |  | ||||||
|         std::string OrderBy{" ORDER BY serialNumber ASC "}; |         std::string OrderBy{" ORDER BY serialNumber ASC "}; | ||||||
|         if(HasParameter("orderBy",Arg)) { |         if(HasParameter("orderBy",Arg)) { | ||||||
|             if(!StorageService()->InventoryDB().PrepareOrderBy(Arg,OrderBy)) { |             if(!DB_.PrepareOrderBy(Arg,OrderBy)) { | ||||||
|                 return BadRequest(RESTAPI::Errors::InvalidLOrderBy); |                 return BadRequest(RESTAPI::Errors::InvalidLOrderBy); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(!QB_.Select.empty()) { |         if(!QB_.Select.empty()) { | ||||||
|             return ReturnRecordList<decltype(StorageService()->InventoryDB())>("taglist",StorageService()->InventoryDB(),*this ); |             return ReturnRecordList<decltype(DB_)>("taglist",DB_,*this ); | ||||||
|         } else if(HasParameter("entity",UUID)) { |         } else if(HasParameter("entity",UUID)) { | ||||||
|             if(QB_.CountOnly) { |             if(QB_.CountOnly) { | ||||||
|                 auto C = StorageService()->InventoryDB().Count( StorageService()->InventoryDB().OP("entity",ORM::EQ,UUID)); |                 auto C = DB_.Count( StorageService()->InventoryDB().OP("entity",ORM::EQ,UUID)); | ||||||
|                 return ReturnCountOnly( C); |                 return ReturnCountOnly( C); | ||||||
|             } |             } | ||||||
|             ProvObjects::InventoryTagVec Tags; |             ProvObjects::InventoryTagVec Tags; | ||||||
|             StorageService()->InventoryDB().GetRecords(QB_.Offset, QB_.Limit, Tags, StorageService()->InventoryDB().OP("entity",ORM::EQ,UUID), OrderBy); |             DB_.GetRecords(QB_.Offset, QB_.Limit, Tags, DB_.OP("entity",ORM::EQ,UUID), OrderBy); | ||||||
|             return SendList(Tags, SerialOnly); |             return SendList(Tags, SerialOnly); | ||||||
|         } else if(HasParameter("venue",UUID)) { |         } else if(HasParameter("venue",UUID)) { | ||||||
|             if(QB_.CountOnly) { |             if(QB_.CountOnly) { | ||||||
|                 auto C = StorageService()->InventoryDB().Count(StorageService()->InventoryDB().OP("venue",ORM::EQ,UUID)); |                 auto C = DB_.Count(DB_.OP("venue",ORM::EQ,UUID)); | ||||||
|                 return ReturnCountOnly( C); |                 return ReturnCountOnly( C); | ||||||
|             } |             } | ||||||
|             ProvObjects::InventoryTagVec Tags; |             ProvObjects::InventoryTagVec Tags; | ||||||
|             StorageService()->InventoryDB().GetRecords(QB_.Offset, QB_.Limit, Tags, StorageService()->InventoryDB().OP("venue",ORM::EQ,UUID), OrderBy); |             DB_.GetRecords(QB_.Offset, QB_.Limit, Tags, DB_.OP("venue",ORM::EQ,UUID), OrderBy); | ||||||
|             return SendList( Tags, SerialOnly); |             return SendList( Tags, SerialOnly); | ||||||
|         } else if(HasParameter("unassigned",Arg) && Arg=="true") { |         } else if(GetBoolParameter("subscribersOnly") && GetBoolParameter("unassigned")) { | ||||||
|  |             if(QB_.CountOnly) { | ||||||
|  |                 auto C = DB_.Count(" devClass='subscriber' and subscriber='' "); | ||||||
|  |                 return ReturnCountOnly( C); | ||||||
|  |             } | ||||||
|  |             ProvObjects::InventoryTagVec Tags; | ||||||
|  |             DB_.GetRecords(QB_.Offset, QB_.Limit, Tags, " devClass='subscriber' and subscriber='' ", OrderBy); | ||||||
|  |             if(QB_.CountOnly) { | ||||||
|  |                 auto C = DB_.Count(DB_.OP("venue",ORM::EQ,UUID)); | ||||||
|  |                 return ReturnCountOnly( C); | ||||||
|  |             } | ||||||
|  |             return SendList(Tags, SerialOnly); | ||||||
|  |         } else if(GetBoolParameter("subscribersOnly")) { | ||||||
|  |             if(QB_.CountOnly) { | ||||||
|  |                 auto C = DB_.Count(" devClass='subscriber' and subscriber!='' "); | ||||||
|  |                 return ReturnCountOnly( C); | ||||||
|  |             } | ||||||
|  |             ProvObjects::InventoryTagVec Tags; | ||||||
|  |             DB_.GetRecords(QB_.Offset, QB_.Limit, Tags," devClass='subscriber' and subscriber!='' ", OrderBy); | ||||||
|  |             return SendList(Tags, SerialOnly); | ||||||
|  |         } else if(GetBoolParameter("unassigned")) { | ||||||
|             if(QB_.CountOnly) { |             if(QB_.CountOnly) { | ||||||
|                 std::string Empty; |                 std::string Empty; | ||||||
|                 auto C = StorageService()->InventoryDB().Count( InventoryDB::OP( StorageService()->InventoryDB().OP("venue",ORM::EQ,Empty), |                 auto C = DB_.Count( InventoryDB::OP( DB_.OP("venue",ORM::EQ,Empty), | ||||||
|                                                                           ORM::AND, StorageService()->InventoryDB().OP("entity",ORM::EQ,Empty) )); |                                                                           ORM::AND, DB_.OP("entity",ORM::EQ,Empty) )); | ||||||
|                 return ReturnCountOnly(C); |                 return ReturnCountOnly(C); | ||||||
|             } |             } | ||||||
|             ProvObjects::InventoryTagVec Tags; |             ProvObjects::InventoryTagVec Tags; | ||||||
|             std::string Empty; |             std::string Empty; | ||||||
|             StorageService()->InventoryDB().GetRecords(QB_.Offset, QB_.Limit, Tags, InventoryDB::OP( StorageService()->InventoryDB().OP("venue",ORM::EQ,Empty), |             DB_.GetRecords(QB_.Offset, QB_.Limit, Tags, InventoryDB::OP( DB_.OP("venue",ORM::EQ,Empty), | ||||||
|                                                                                               ORM::AND, StorageService()->InventoryDB().OP("entity",ORM::EQ,Empty) ) , OrderBy ); |                                                                          ORM::AND, DB_.OP("entity",ORM::EQ,Empty) ) , OrderBy ); | ||||||
|             return SendList(Tags, SerialOnly); |             return SendList(Tags, SerialOnly); | ||||||
|         } else if (HasParameter("subscriber",Arg) && !Arg.empty()) { |         } else if (HasParameter("subscriber",Arg) && !Arg.empty()) { | ||||||
|             // looking for device(s) for a specific subscriber... |             // looking for device(s) for a specific subscriber... | ||||||
|             ProvObjects::InventoryTagVec Tags; |             ProvObjects::InventoryTagVec Tags; | ||||||
|             StorageService()->InventoryDB().GetRecords(0,100,Tags," subscriber='" + Arg + "'"); |             DB_.GetRecords(0,100,Tags," subscriber='" + Arg + "'"); | ||||||
|             if(SerialOnly) { |             if(SerialOnly) { | ||||||
|                 std::vector<std::string>    SerialNumbers; |                 std::vector<std::string>    SerialNumbers; | ||||||
|                 std::transform(cbegin(Tags), cend(Tags), std::back_inserter(SerialNumbers), [](const auto &T) { return T.serialNumber; }); |                 std::transform(cbegin(Tags), cend(Tags), std::back_inserter(SerialNumbers), [](const auto &T) { return T.serialNumber; }); | ||||||
| @@ -91,11 +113,11 @@ namespace OpenWifi{ | |||||||
|                 return MakeJSONObjectArray("taglist", Tags, *this); |                 return MakeJSONObjectArray("taglist", Tags, *this); | ||||||
|             } |             } | ||||||
|         } else if (QB_.CountOnly) { |         } else if (QB_.CountOnly) { | ||||||
|             auto C = StorageService()->InventoryDB().Count(); |             auto C = DB_.Count(); | ||||||
|             return ReturnCountOnly(C); |             return ReturnCountOnly(C); | ||||||
|         } else if (GetBoolParameter("rrmOnly",false)) { |         } else if (GetBoolParameter("rrmOnly")) { | ||||||
|             Types::UUIDvec_t   DeviceList; |             Types::UUIDvec_t   DeviceList; | ||||||
|             StorageService()->InventoryDB().GetRRMDeviceList(DeviceList); |             DB_.GetRRMDeviceList(DeviceList); | ||||||
|             if(QB_.CountOnly) |             if(QB_.CountOnly) | ||||||
|                 return ReturnCountOnly(DeviceList.size()); |                 return ReturnCountOnly(DeviceList.size()); | ||||||
|             else { |             else { | ||||||
| @@ -103,7 +125,7 @@ namespace OpenWifi{ | |||||||
|             } |             } | ||||||
|         } else { |         } else { | ||||||
|             ProvObjects::InventoryTagVec Tags; |             ProvObjects::InventoryTagVec Tags; | ||||||
|             StorageService()->InventoryDB().GetRecords(QB_.Offset,QB_.Limit,Tags,"",OrderBy); |             DB_.GetRecords(QB_.Offset,QB_.Limit,Tags,"",OrderBy); | ||||||
|             return MakeJSONObjectArray("taglist", Tags, *this); |             return MakeJSONObjectArray("taglist", Tags, *this); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -8,8 +8,8 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
|  | #include "StorageService.h" | ||||||
| #include "framework/MicroService.h" | #include "framework/MicroService.h" | ||||||
| #include "RESTObjects/RESTAPI_ProvObjects.h" |  | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace OpenWifi { | ||||||
|  |  | ||||||
| @@ -22,9 +22,10 @@ namespace OpenWifi { | |||||||
|             Poco::Net::HTTPRequest::HTTP_OPTIONS}, |             Poco::Net::HTTPRequest::HTTP_OPTIONS}, | ||||||
|             Server, |             Server, | ||||||
|             TransactionId, |             TransactionId, | ||||||
|             Internal) {} |             Internal){} | ||||||
|         static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/inventory"}; }; |         static auto PathName() { return std::list<std::string>{"/api/v1/inventory"}; }; | ||||||
|  |     private: | ||||||
|  |         InventoryDB     &DB_=StorageService()->InventoryDB(); | ||||||
|         void DoGet() final; |         void DoGet() final; | ||||||
|         void DoPost() final {}; |         void DoPost() final {}; | ||||||
|         void DoPut() final {}; |         void DoPut() final {}; | ||||||
|   | |||||||
| @@ -16,7 +16,7 @@ class RESTAPI_iptocountry_handler : public RESTAPIHandler { | |||||||
| 						 Server, | 						 Server, | ||||||
| 						 TransactionId, | 						 TransactionId, | ||||||
| 						 Internal){}; | 						 Internal){}; | ||||||
| 	static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/iptocountry"}; }; |     static auto PathName() { return std::list<std::string>{"/api/v1/iptocountry"}; }; | ||||||
| 	void DoGet() final; | 	void DoGet() final; | ||||||
| 	void DoDelete() final {}; | 	void DoDelete() final {}; | ||||||
| 	void DoPost() final {}; | 	void DoPost() final {}; | ||||||
|   | |||||||
| @@ -8,11 +8,8 @@ | |||||||
|  |  | ||||||
|  |  | ||||||
| #include "RESTAPI_location_handler.h" | #include "RESTAPI_location_handler.h" | ||||||
| #include "framework/RESTAPI_errors.h" |  | ||||||
|  |  | ||||||
| #include "RESTObjects/RESTAPI_ProvObjects.h" | #include "RESTObjects/RESTAPI_ProvObjects.h" | ||||||
| #include "StorageService.h" | #include "StorageService.h" | ||||||
| #include "framework/RESTAPI_protocol.h" |  | ||||||
| #include "Daemon.h" | #include "Daemon.h" | ||||||
| #include "RESTAPI/RESTAPI_db_helpers.h" | #include "RESTAPI/RESTAPI_db_helpers.h" | ||||||
|  |  | ||||||
| @@ -67,14 +64,11 @@ namespace OpenWifi{ | |||||||
|             return BadRequest(RESTAPI::Errors::StillInUse); |             return BadRequest(RESTAPI::Errors::StillInUse); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(DB_.DeleteRecord("id",UUID)) { |         DB_.DeleteRecord("id",UUID); | ||||||
|             if(!Existing.entity.empty()) |         RemoveMembership(StorageService()->EntityDB(),&ProvObjects::Entity::locations,Existing.entity,Existing.info.id); | ||||||
|                 StorageService()->EntityDB().DeleteLocation("id",Existing.entity,UUID); |         MoveUsage(StorageService()->PolicyDB(),DB_,Existing.info.id,"",Existing.info.id); | ||||||
|  |  | ||||||
|         return OK(); |         return OK(); | ||||||
|     } |     } | ||||||
|         InternalError(RESTAPI::Errors::CouldNotBeDeleted); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void RESTAPI_location_handler::DoPost() { |     void RESTAPI_location_handler::DoPost() { | ||||||
|         std::string UUID = GetBinding(RESTAPI::Protocol::UUID,""); |         std::string UUID = GetBinding(RESTAPI::Protocol::UUID,""); | ||||||
| @@ -82,7 +76,7 @@ namespace OpenWifi{ | |||||||
|             return BadRequest(RESTAPI::Errors::MissingUUID); |             return BadRequest(RESTAPI::Errors::MissingUUID); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         auto Obj = ParseStream(); |         const auto & Obj = ParsedBody_; | ||||||
|         ProvObjects::Location NewObject; |         ProvObjects::Location NewObject; | ||||||
|         if (!NewObject.from_json(Obj)) { |         if (!NewObject.from_json(Obj)) { | ||||||
|             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); |             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); | ||||||
| @@ -103,11 +97,11 @@ namespace OpenWifi{ | |||||||
|         NewObject.inUse.clear(); |         NewObject.inUse.clear(); | ||||||
|  |  | ||||||
|         if(DB_.CreateRecord(NewObject)) { |         if(DB_.CreateRecord(NewObject)) { | ||||||
|             if(!NewObject.managementPolicy.empty()) |             MoveUsage(StorageService()->PolicyDB(),DB_,"",NewObject.managementPolicy,NewObject.info.id); | ||||||
|                 StorageService()->PolicyDB().AddInUse("id",NewObject.managementPolicy,DB_.Prefix(),NewObject.info.id); |             AddMembership(StorageService()->EntityDB(),&ProvObjects::Entity::locations,NewObject.entity,NewObject.info.id); | ||||||
|  |  | ||||||
|             StorageService()->EntityDB().AddLocation("id",NewObject.entity,NewObject.info.id); |  | ||||||
|  |  | ||||||
|  |             LocationDB::RecordName AddedRecord; | ||||||
|  |             DB_.GetRecord("id", NewObject.info.id,AddedRecord); | ||||||
|             Poco::JSON::Object Answer; |             Poco::JSON::Object Answer; | ||||||
|             NewObject.to_json(Answer); |             NewObject.to_json(Answer); | ||||||
|             return ReturnObject(Answer); |             return ReturnObject(Answer); | ||||||
| @@ -116,13 +110,14 @@ namespace OpenWifi{ | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     void RESTAPI_location_handler::DoPut() { |     void RESTAPI_location_handler::DoPut() { | ||||||
|         std::string UUID = GetBinding(RESTAPI::Protocol::UUID,""); |  | ||||||
|  |         std::string UUID = GetBinding(RESTAPI::Protocol::UUID); | ||||||
|         ProvObjects::Location   Existing; |         ProvObjects::Location   Existing; | ||||||
|         if(UUID.empty() || !DB_.GetRecord("id", UUID, Existing)) { |         if(UUID.empty() || !DB_.GetRecord("id", UUID, Existing)) { | ||||||
|             return NotFound(); |             return NotFound(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         auto RawObject = ParseStream(); |         const auto & RawObject = ParsedBody_; | ||||||
|         ProvObjects::Location NewObject; |         ProvObjects::Location NewObject; | ||||||
|         if (!NewObject.from_json(RawObject)) { |         if (!NewObject.from_json(RawObject)) { | ||||||
|             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); |             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); | ||||||
| @@ -132,27 +127,13 @@ namespace OpenWifi{ | |||||||
|             return BadRequest( RESTAPI::Errors::NameMustBeSet); |             return BadRequest( RESTAPI::Errors::NameMustBeSet); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         std::string MoveFromPolicy,MoveToPolicy; |         std::string FromPolicy, ToPolicy; | ||||||
|         bool MovingPolicy=false; |         if(!CreateMove(RawObject,"managementPolicy",&LocationDB::RecordName::managementPolicy, Existing, FromPolicy, ToPolicy, StorageService()->PolicyDB())) | ||||||
|         if(AssignIfPresent(RawObject,"managementPolicy",MoveToPolicy)) { |             return BadRequest(RESTAPI::Errors::EntityMustExist); | ||||||
|             if(!MoveToPolicy.empty() && !StorageService()->PolicyDB().Exists("id",MoveToPolicy)) { |  | ||||||
|                 return BadRequest(RESTAPI::Errors::UnknownManagementPolicyUUID); |         std::string FromEntity, ToEntity; | ||||||
|             } |         if(!CreateMove(RawObject,"entity",&LocationDB::RecordName::entity, Existing, FromEntity, ToEntity, StorageService()->EntityDB())) | ||||||
|             MoveFromPolicy = Existing.managementPolicy; |  | ||||||
|             MovingPolicy = MoveToPolicy != MoveFromPolicy; |  | ||||||
|             Existing.managementPolicy = MoveToPolicy; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         std::string MoveFromEntity,MoveToEntity; |  | ||||||
|         bool MovingEntity=false; |  | ||||||
|         if(AssignIfPresent(RawObject,"entity",MoveToEntity)) { |  | ||||||
|             if(!MoveToEntity.empty() && !StorageService()->EntityDB().Exists("id",MoveToEntity)) { |  | ||||||
|             return BadRequest(RESTAPI::Errors::EntityMustExist); |             return BadRequest(RESTAPI::Errors::EntityMustExist); | ||||||
|             } |  | ||||||
|             MoveFromEntity = Existing.entity; |  | ||||||
|             MovingEntity = MoveToEntity != Existing.entity; |  | ||||||
|             Existing.entity = MoveToEntity; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         AssignIfPresent(RawObject, "buildingName", Existing.buildingName); |         AssignIfPresent(RawObject, "buildingName", Existing.buildingName); | ||||||
|         AssignIfPresent(RawObject, "city", Existing.city); |         AssignIfPresent(RawObject, "city", Existing.city); | ||||||
| @@ -166,27 +147,16 @@ namespace OpenWifi{ | |||||||
|             Existing.phones = NewObject.phones; |             Existing.phones = NewObject.phones; | ||||||
|         if(RawObject->has("mobiles")) |         if(RawObject->has("mobiles")) | ||||||
|             Existing.mobiles = NewObject.mobiles; |             Existing.mobiles = NewObject.mobiles; | ||||||
|         Existing.info.modified = std::time(nullptr); |         Existing.info.modified = OpenWifi::Now(); | ||||||
|         if(RawObject->has("type")) |         if(RawObject->has("type")) | ||||||
|             Existing.type = NewObject.type; |             Existing.type = NewObject.type; | ||||||
|  |  | ||||||
|         if(DB_.UpdateRecord("id", UUID, Existing)) { |         if(DB_.UpdateRecord("id", UUID, Existing)) { | ||||||
|             if(MovingPolicy) { |             MoveUsage(StorageService()->PolicyDB(), DB_, FromPolicy, ToPolicy, Existing.info.id); | ||||||
|                 if(!MoveFromPolicy.empty()) |             ManageMembership(StorageService()->EntityDB(),&ProvObjects::Entity::locations,FromEntity, ToEntity, Existing.info.id); | ||||||
|                     StorageService()->PolicyDB().DeleteInUse("id",MoveFromPolicy,DB_.Prefix(),Existing.info.id); |  | ||||||
|                 if(!MoveToPolicy.empty()) |  | ||||||
|                     StorageService()->PolicyDB().AddInUse("id", MoveToPolicy, DB_.Prefix(), Existing.info.id); |  | ||||||
|             } |  | ||||||
|             if(MovingEntity) { |  | ||||||
|                 if(!MoveFromEntity.empty()) |  | ||||||
|                     StorageService()->EntityDB().DeleteLocation("id",MoveFromEntity,Existing.info.id); |  | ||||||
|                 if(!MoveToEntity.empty()) |  | ||||||
|                     StorageService()->EntityDB().AddLocation("id", MoveToEntity, Existing.info.id); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             ProvObjects::Location    NewObjectAdded; |             ProvObjects::Location    NewObjectAdded; | ||||||
|             DB_.GetRecord("id", UUID, NewObjectAdded); |             DB_.GetRecord("id", UUID, NewObjectAdded); | ||||||
|  |  | ||||||
|             Poco::JSON::Object  Answer; |             Poco::JSON::Object  Answer; | ||||||
|             NewObjectAdded.to_json(Answer); |             NewObjectAdded.to_json(Answer); | ||||||
|             return ReturnObject(Answer); |             return ReturnObject(Answer); | ||||||
|   | |||||||
| @@ -22,15 +22,14 @@ namespace OpenWifi { | |||||||
|             Poco::Net::HTTPRequest::HTTP_OPTIONS}, |             Poco::Net::HTTPRequest::HTTP_OPTIONS}, | ||||||
|             Server, |             Server, | ||||||
|             TransactionId, |             TransactionId, | ||||||
|             Internal), |             Internal){} | ||||||
|             DB_(StorageService()->LocationDB()){} |         static auto PathName() { return std::list<std::string>{"/api/v1/location/{uuid}"}; }; | ||||||
|         static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/location/{uuid}"}; }; |  | ||||||
|  |  | ||||||
|  |     private: | ||||||
|  |         LocationDB      & DB_ = StorageService()->LocationDB(); | ||||||
|         void DoGet() final ; |         void DoGet() final ; | ||||||
|         void DoPost() final ; |         void DoPost() final ; | ||||||
|         void DoPut() final ; |         void DoPut() final ; | ||||||
|         void DoDelete() final ; |         void DoDelete() final ; | ||||||
|     private: |  | ||||||
|         LocationDB  &DB_; |  | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -11,17 +11,6 @@ | |||||||
| namespace OpenWifi{ | namespace OpenWifi{ | ||||||
|  |  | ||||||
|     void RESTAPI_location_list_handler::DoGet() { |     void RESTAPI_location_list_handler::DoGet() { | ||||||
|         if(!QB_.Select.empty()) { |         return ListHandler<LocationDB>("locations", DB_, *this); | ||||||
|             return ReturnRecordList<decltype(StorageService()->LocationDB()), |  | ||||||
|             ProvObjects::Location>("locations",StorageService()->LocationDB(),*this ); |  | ||||||
|         } else if(QB_.CountOnly) { |  | ||||||
|             Poco::JSON::Object  Answer; |  | ||||||
|             auto C = StorageService()->LocationDB().Count(); |  | ||||||
|             return ReturnCountOnly(C); |  | ||||||
|         } else { |  | ||||||
|             ProvObjects::LocationVec Locations; |  | ||||||
|             StorageService()->LocationDB().GetRecords(QB_.Offset,QB_.Limit,Locations); |  | ||||||
|             return MakeJSONObjectArray("locations", Locations, *this); |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -5,6 +5,7 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include "framework/MicroService.h" | #include "framework/MicroService.h" | ||||||
|  | #include "StorageService.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace OpenWifi { | ||||||
|  |  | ||||||
| @@ -17,9 +18,10 @@ namespace OpenWifi { | |||||||
|             Poco::Net::HTTPRequest::HTTP_OPTIONS}, |             Poco::Net::HTTPRequest::HTTP_OPTIONS}, | ||||||
|             Server, |             Server, | ||||||
|             TransactionId, |             TransactionId, | ||||||
|             Internal) {} |             Internal){} | ||||||
|         static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/location"}; }; |         static auto PathName() { return std::list<std::string>{"/api/v1/location"}; }; | ||||||
|  |     private: | ||||||
|  |         LocationDB  & DB_=StorageService()->LocationDB(); | ||||||
|         void DoGet() final; |         void DoGet() final; | ||||||
|         void DoPost() final {}; |         void DoPost() final {}; | ||||||
|         void DoPut() final {}; |         void DoPut() final {}; | ||||||
|   | |||||||
| @@ -12,7 +12,6 @@ | |||||||
| #include "StorageService.h" | #include "StorageService.h" | ||||||
| #include "Poco/JSON/Parser.h" | #include "Poco/JSON/Parser.h" | ||||||
| #include "Daemon.h" | #include "Daemon.h" | ||||||
| #include "framework/RESTAPI_errors.h" |  | ||||||
| #include "RESTAPI/RESTAPI_db_helpers.h" | #include "RESTAPI/RESTAPI_db_helpers.h" | ||||||
|  |  | ||||||
| namespace OpenWifi{ | namespace OpenWifi{ | ||||||
| @@ -64,36 +63,44 @@ namespace OpenWifi{ | |||||||
|             return BadRequest(RESTAPI::Errors::StillInUse); |             return BadRequest(RESTAPI::Errors::StillInUse); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(StorageService()->PolicyDB().DeleteRecord("id", UUID)) { |         StorageService()->PolicyDB().DeleteRecord("id", UUID); | ||||||
|  |         ManageMembership(StorageService()->EntityDB(),&ProvObjects::Entity::managementPolicies,Existing.entity,"",Existing.info.id); | ||||||
|  |         ManageMembership(StorageService()->VenueDB(),&ProvObjects::Venue::managementPolicies,Existing.venue,"",Existing.info.id); | ||||||
|         return OK(); |         return OK(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|         InternalError(RESTAPI::Errors::CouldNotBeDeleted); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void RESTAPI_managementPolicy_handler::DoPost() { |     void RESTAPI_managementPolicy_handler::DoPost() { | ||||||
|         std::string UUID = GetBinding("uuid",""); |         std::string UUID = GetBinding("uuid",""); | ||||||
|         if(UUID.empty()) { |         if(UUID.empty()) { | ||||||
|             return BadRequest(RESTAPI::Errors::MissingUUID); |             return BadRequest(RESTAPI::Errors::MissingUUID); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         ProvObjects::ManagementPolicy   NewPolicy; |         ProvObjects::ManagementPolicy   NewObject; | ||||||
|         auto NewObject = ParseStream(); |         const auto & RawObject = ParsedBody_; | ||||||
|         if(!NewPolicy.from_json(NewObject)) { |         if(!NewObject.from_json(RawObject)) { | ||||||
|             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); |             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(!CreateObjectInfo(NewObject, UserInfo_.userinfo, NewPolicy.info)) { |         if(!CreateObjectInfo(RawObject, UserInfo_.userinfo, NewObject.info)) { | ||||||
|             return BadRequest( RESTAPI::Errors::NameMustBeSet); |             return BadRequest( RESTAPI::Errors::NameMustBeSet); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         NewPolicy.inUse.clear(); |         if(NewObject.entity.empty() || !StorageService()->EntityDB().Exists("id", NewObject.entity)) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::EntityMustExist); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         if(DB_.CreateRecord(NewPolicy)) { |         if(NewObject.venue.empty() || !StorageService()->VenueDB().Exists("id", NewObject.venue)) { | ||||||
|             ProvObjects::ManagementPolicy   Policy; |             return BadRequest(RESTAPI::Errors::VenueMustExist); | ||||||
|             DB_.GetRecord("id",NewPolicy.info.id,Policy); |         } | ||||||
|  |  | ||||||
|  |         NewObject.inUse.clear(); | ||||||
|  |         if(DB_.CreateRecord(NewObject)) { | ||||||
|  |             AddMembership(StorageService()->EntityDB(),&ProvObjects::Entity::managementPolicies,NewObject.entity,NewObject.info.id); | ||||||
|  |             AddMembership(StorageService()->VenueDB(),&ProvObjects::Venue::managementPolicies,NewObject.venue,NewObject.info.id); | ||||||
|  |             PolicyDB::RecordName  AddedObject; | ||||||
|  |             DB_.GetRecord("id",NewObject.info.id,AddedObject); | ||||||
|             Poco::JSON::Object  Answer; |             Poco::JSON::Object  Answer; | ||||||
|             Policy.to_json(Answer); |             AddedObject.to_json(Answer); | ||||||
|             return ReturnObject(Answer); |             return ReturnObject(Answer); | ||||||
|         } |         } | ||||||
|         InternalError(RESTAPI::Errors::RecordNotCreated); |         InternalError(RESTAPI::Errors::RecordNotCreated); | ||||||
| @@ -107,19 +114,30 @@ namespace OpenWifi{ | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         ProvObjects::ManagementPolicy   NewPolicy; |         ProvObjects::ManagementPolicy   NewPolicy; | ||||||
|         auto NewObject = ParseStream(); |         const auto & RawObject = ParsedBody_; | ||||||
|         if(!NewPolicy.from_json(NewObject)) { |         if(!NewPolicy.from_json(RawObject)) { | ||||||
|             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); |             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(!UpdateObjectInfo(NewObject, UserInfo_.userinfo, Existing.info)) { |         if(!UpdateObjectInfo(RawObject, UserInfo_.userinfo, Existing.info)) { | ||||||
|             return BadRequest( RESTAPI::Errors::NameMustBeSet); |             return BadRequest( RESTAPI::Errors::NameMustBeSet); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         std::string FromEntity, ToEntity; | ||||||
|  |         if(!CreateMove(RawObject,"entity",&PolicyDB::RecordName::entity, Existing, FromEntity, ToEntity, StorageService()->EntityDB())) | ||||||
|  |             return BadRequest(RESTAPI::Errors::EntityMustExist); | ||||||
|  |  | ||||||
|  |         std::string FromVenue, ToVenue; | ||||||
|  |         if(!CreateMove(RawObject,"venue",&PolicyDB::RecordName::venue, Existing, FromVenue, ToVenue, StorageService()->VenueDB())) | ||||||
|  |             return BadRequest(RESTAPI::Errors::EntityMustExist); | ||||||
|  |  | ||||||
|         if(!NewPolicy.entries.empty()) |         if(!NewPolicy.entries.empty()) | ||||||
|             Existing.entries = NewPolicy.entries; |             Existing.entries = NewPolicy.entries; | ||||||
|  |  | ||||||
|         if(DB_.UpdateRecord("id", Existing.info.id, Existing)) { |         if(DB_.UpdateRecord("id", Existing.info.id, Existing)) { | ||||||
|  |             ManageMembership(StorageService()->EntityDB(),&ProvObjects::Entity::managementPolicies, FromEntity,ToEntity,Existing.info.id); | ||||||
|  |             ManageMembership(StorageService()->VenueDB(),&ProvObjects::Venue::managementPolicies, FromVenue,ToVenue,Existing.info.id); | ||||||
|  |  | ||||||
|             ProvObjects::ManagementPolicy   P; |             ProvObjects::ManagementPolicy   P; | ||||||
|             DB_.GetRecord("id",Existing.info.id,P); |             DB_.GetRecord("id",Existing.info.id,P); | ||||||
|             Poco::JSON::Object  Answer; |             Poco::JSON::Object  Answer; | ||||||
|   | |||||||
| @@ -21,12 +21,11 @@ namespace OpenWifi { | |||||||
|             Poco::Net::HTTPRequest::HTTP_OPTIONS}, |             Poco::Net::HTTPRequest::HTTP_OPTIONS}, | ||||||
|             Server, |             Server, | ||||||
|             TransactionId, |             TransactionId, | ||||||
|             Internal), |             Internal){} | ||||||
|             DB_(StorageService()->PolicyDB()){} |         static auto PathName() { return std::list<std::string>{"/api/v1/managementPolicy/{uuid}"}; }; | ||||||
|         static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/managementPolicy/{uuid}"}; }; |  | ||||||
|  |  | ||||||
|     private: |     private: | ||||||
|         PolicyDB        &DB_; |         PolicyDB        &DB_=StorageService()->PolicyDB(); | ||||||
|         void DoGet() final; |         void DoGet() final; | ||||||
|         void DoPost() final ; |         void DoPost() final ; | ||||||
|         void DoPut() final ; |         void DoPut() final ; | ||||||
|   | |||||||
| @@ -6,22 +6,10 @@ | |||||||
|  |  | ||||||
| #include "RESTObjects/RESTAPI_ProvObjects.h" | #include "RESTObjects/RESTAPI_ProvObjects.h" | ||||||
| #include "StorageService.h" | #include "StorageService.h" | ||||||
| #include "framework/RESTAPI_errors.h" |  | ||||||
| #include "RESTAPI/RESTAPI_db_helpers.h" | #include "RESTAPI/RESTAPI_db_helpers.h" | ||||||
|  |  | ||||||
| namespace OpenWifi{ | namespace OpenWifi{ | ||||||
|     void RESTAPI_managementPolicy_list_handler::DoGet() { |     void RESTAPI_managementPolicy_list_handler::DoGet() { | ||||||
|         if(!QB_.Select.empty()) { |         return ListHandler<PolicyDB>("managementPolicies", DB_, *this); | ||||||
|             return ReturnRecordList<decltype(StorageService()->PolicyDB()), |  | ||||||
|             ProvObjects::ManagementPolicy>("managementPolicies",StorageService()->PolicyDB(),*this ); |  | ||||||
|         } else if(QB_.CountOnly) { |  | ||||||
|             Poco::JSON::Object  Answer; |  | ||||||
|             auto C = StorageService()->ContactDB().Count(); |  | ||||||
|             return ReturnCountOnly(C); |  | ||||||
|         } else { |  | ||||||
|             ProvObjects::ManagementPolicyVec Policies; |  | ||||||
|             StorageService()->PolicyDB().GetRecords(QB_.Offset,QB_.Limit,Policies); |  | ||||||
|             return MakeJSONObjectArray("managementPolicies", Policies, *this); |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -3,6 +3,7 @@ | |||||||
| // | // | ||||||
|  |  | ||||||
| #include "framework/MicroService.h" | #include "framework/MicroService.h" | ||||||
|  | #include "StorageService.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace OpenWifi { | ||||||
|  |  | ||||||
| @@ -15,9 +16,10 @@ namespace OpenWifi { | |||||||
|             Poco::Net::HTTPRequest::HTTP_OPTIONS}, |             Poco::Net::HTTPRequest::HTTP_OPTIONS}, | ||||||
|             Server, |             Server, | ||||||
|             TransactionId, |             TransactionId, | ||||||
|             Internal) {} |             Internal){} | ||||||
|         static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/managementPolicy"}; }; |         static auto PathName() { return std::list<std::string>{"/api/v1/managementPolicy"}; }; | ||||||
|  |     private: | ||||||
|  |         PolicyDB        &DB_=StorageService()->PolicyDB(); | ||||||
|         void DoGet() final ; |         void DoGet() final ; | ||||||
|         void DoPost() final {}; |         void DoPost() final {}; | ||||||
|         void DoPut() final {}; |         void DoPut() final {}; | ||||||
|   | |||||||
| @@ -4,12 +4,10 @@ | |||||||
|  |  | ||||||
| #include "RESTAPI_managementRole_handler.h" | #include "RESTAPI_managementRole_handler.h" | ||||||
|  |  | ||||||
| #include "framework/RESTAPI_protocol.h" |  | ||||||
| #include "RESTObjects/RESTAPI_ProvObjects.h" | #include "RESTObjects/RESTAPI_ProvObjects.h" | ||||||
| #include "StorageService.h" | #include "StorageService.h" | ||||||
| #include "Poco/JSON/Parser.h" | #include "Poco/JSON/Parser.h" | ||||||
| #include "Poco/StringTokenizer.h" | #include "Poco/StringTokenizer.h" | ||||||
| #include "framework/RESTAPI_errors.h" |  | ||||||
| #include "RESTAPI/RESTAPI_db_helpers.h" | #include "RESTAPI/RESTAPI_db_helpers.h" | ||||||
|  |  | ||||||
| namespace OpenWifi{ | namespace OpenWifi{ | ||||||
| @@ -64,14 +62,12 @@ namespace OpenWifi{ | |||||||
|             return BadRequest(RESTAPI::Errors::StillInUse); |             return BadRequest(RESTAPI::Errors::StillInUse); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(!Existing.managementPolicy.empty()) |         DB_.DeleteRecord("id", Existing.info.id); | ||||||
|             StorageService()->PolicyDB().DeleteInUse("id",Existing.managementPolicy,DB_.Prefix(),Existing.info.id); |         MoveUsage(StorageService()->PolicyDB(),DB_,Existing.managementPolicy,"",Existing.info.id); | ||||||
|  |         RemoveMembership(StorageService()->EntityDB(),&ProvObjects::Entity::managementRoles,Existing.entity,Existing.info.id); | ||||||
|         if(StorageService()->RolesDB().DeleteRecord("id", Existing.info.id)) { |         RemoveMembership(StorageService()->VenueDB(),&ProvObjects::Venue::managementRoles,Existing.venue,Existing.info.id); | ||||||
|         return OK(); |         return OK(); | ||||||
|     } |     } | ||||||
|         InternalError(RESTAPI::Errors::CouldNotBeDeleted); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     void RESTAPI_managementRole_handler::DoPost() { |     void RESTAPI_managementRole_handler::DoPost() { | ||||||
|         std::string UUID = GetBinding(RESTAPI::Protocol::ID,""); |         std::string UUID = GetBinding(RESTAPI::Protocol::ID,""); | ||||||
| @@ -79,23 +75,29 @@ namespace OpenWifi{ | |||||||
|             return BadRequest(RESTAPI::Errors::MissingUUID); |             return BadRequest(RESTAPI::Errors::MissingUUID); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         auto Obj = ParseStream(); |         const auto & RawObj = ParsedBody_; | ||||||
|         ProvObjects::ManagementRole NewObject; |         ProvObjects::ManagementRole NewObject; | ||||||
|         if (!NewObject.from_json(Obj)) { |         if (!NewObject.from_json(RawObj)) { | ||||||
|             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); |             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(!CreateObjectInfo(Obj, UserInfo_.userinfo, NewObject.info)) { |         if(!CreateObjectInfo(RawObj, UserInfo_.userinfo, NewObject.info)) { | ||||||
|             return BadRequest( RESTAPI::Errors::NameMustBeSet); |             return BadRequest( RESTAPI::Errors::NameMustBeSet); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         if(NewObject.entity.empty() || !StorageService()->EntityDB().Exists("id",NewObject.entity)) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::EntityMustExist); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         if(!NewObject.managementPolicy.empty() && !StorageService()->PolicyDB().Exists("id",NewObject.managementPolicy)) { |         if(!NewObject.managementPolicy.empty() && !StorageService()->PolicyDB().Exists("id",NewObject.managementPolicy)) { | ||||||
|             return BadRequest(RESTAPI::Errors::UnknownManagementPolicyUUID); |             return BadRequest(RESTAPI::Errors::UnknownManagementPolicyUUID); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(DB_.CreateRecord(NewObject)) { |         if(DB_.CreateRecord(NewObject)) { | ||||||
|             if(!NewObject.managementPolicy.empty()) |             AddMembership(StorageService()->EntityDB(),&ProvObjects::Entity::managementRoles,NewObject.entity,NewObject.info.id); | ||||||
|                 StorageService()->PolicyDB().AddInUse("id", NewObject.managementPolicy, DB_.Prefix(), NewObject.info.id); |             AddMembership(StorageService()->VenueDB(),&ProvObjects::Venue::managementRoles,NewObject.venue,NewObject.info.id); | ||||||
|  |             MoveUsage(StorageService()->PolicyDB(), DB_, "", NewObject.managementPolicy, NewObject.info.id); | ||||||
|  |  | ||||||
|             Poco::JSON::Object Answer; |             Poco::JSON::Object Answer; | ||||||
|             ProvObjects::ManagementRole Role; |             ProvObjects::ManagementRole Role; | ||||||
|             DB_.GetRecord("id", NewObject.info.id,Role); |             DB_.GetRecord("id", NewObject.info.id,Role); | ||||||
| @@ -112,7 +114,7 @@ namespace OpenWifi{ | |||||||
|             return NotFound(); |             return NotFound(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         auto RawObject = ParseStream(); |         const auto & RawObject = ParsedBody_; | ||||||
|         ProvObjects::ManagementRole NewObject; |         ProvObjects::ManagementRole NewObject; | ||||||
|         if(!NewObject.from_json(RawObject)) { |         if(!NewObject.from_json(RawObject)) { | ||||||
|             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); |             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); | ||||||
| @@ -122,20 +124,22 @@ namespace OpenWifi{ | |||||||
|             return BadRequest( RESTAPI::Errors::NameMustBeSet); |             return BadRequest( RESTAPI::Errors::NameMustBeSet); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         std::string NewPolicy,OldPolicy = Existing.managementPolicy; |         std::string FromPolicy, ToPolicy; | ||||||
|         AssignIfPresent(RawObject, "managementPolicy", NewPolicy); |         if(!CreateMove(RawObject,"managementPolicy",&ManagementRoleDB::RecordName::managementPolicy, Existing, FromPolicy, ToPolicy, StorageService()->PolicyDB())) | ||||||
|         if(!NewPolicy.empty() && !StorageService()->PolicyDB().Exists("id",NewPolicy)) { |             return BadRequest(RESTAPI::Errors::EntityMustExist); | ||||||
|             return BadRequest(RESTAPI::Errors::UnknownManagementPolicyUUID); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         if(!NewPolicy.empty()) |         std::string FromEntity, ToEntity; | ||||||
|             Existing.managementPolicy = NewPolicy; |         if(!CreateMove(RawObject,"entity",&ManagementRoleDB::RecordName::entity, Existing, FromEntity, ToEntity, StorageService()->EntityDB())) | ||||||
|  |             return BadRequest(RESTAPI::Errors::EntityMustExist); | ||||||
|  |  | ||||||
|  |         std::string FromVenue, ToVenue; | ||||||
|  |         if(!CreateMove(RawObject,"venue",&ManagementRoleDB::RecordName::venue, Existing, FromVenue, ToVenue, StorageService()->VenueDB())) | ||||||
|  |             return BadRequest(RESTAPI::Errors::EntityMustExist); | ||||||
|  |  | ||||||
|         if(DB_.UpdateRecord("id",UUID,Existing)) { |         if(DB_.UpdateRecord("id",UUID,Existing)) { | ||||||
|             if(!OldPolicy.empty()) |             MoveUsage(StorageService()->PolicyDB(),DB_, FromPolicy, ToPolicy, Existing.info.id); | ||||||
|                 StorageService()->PolicyDB().DeleteInUse("id",OldPolicy,DB_.Prefix(),UUID); |             ManageMembership(StorageService()->EntityDB(),&ProvObjects::Entity::managementRoles, FromEntity, ToEntity, Existing.info.id); | ||||||
|             if(!NewPolicy.empty()) |             ManageMembership(StorageService()->VenueDB(),&ProvObjects::Venue::managementRoles, FromVenue, ToVenue, Existing.info.id); | ||||||
|                 StorageService()->PolicyDB().AddInUse("id",NewPolicy,DB_.Prefix(),UUID); |  | ||||||
|  |  | ||||||
|             ProvObjects::ManagementRole NewRecord; |             ProvObjects::ManagementRole NewRecord; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -16,11 +16,10 @@ namespace OpenWifi { | |||||||
|             Poco::Net::HTTPRequest::HTTP_OPTIONS}, |             Poco::Net::HTTPRequest::HTTP_OPTIONS}, | ||||||
|             Server, |             Server, | ||||||
|             TransactionId, |             TransactionId, | ||||||
|             Internal), |             Internal){} | ||||||
|             DB_(StorageService()->RolesDB()){} |         static auto PathName() { return std::list<std::string>{"/api/v1/managementRole/{uuid}"}; }; | ||||||
|         static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/managementRole/{uuid}"}; }; |  | ||||||
|     private: |     private: | ||||||
|         ManagementRoleDB    &DB_; |         ManagementRoleDB    &DB_=StorageService()->RolesDB(); | ||||||
|         void DoGet() final ; |         void DoGet() final ; | ||||||
|         void DoPost() final ; |         void DoPost() final ; | ||||||
|         void DoPut() final ; |         void DoPut() final ; | ||||||
|   | |||||||
| @@ -7,22 +7,10 @@ | |||||||
| #include "RESTAPI_managementRole_list_handler.h" | #include "RESTAPI_managementRole_list_handler.h" | ||||||
| #include "RESTObjects/RESTAPI_ProvObjects.h" | #include "RESTObjects/RESTAPI_ProvObjects.h" | ||||||
| #include "StorageService.h" | #include "StorageService.h" | ||||||
| #include "framework/RESTAPI_errors.h" |  | ||||||
| #include "RESTAPI/RESTAPI_db_helpers.h" | #include "RESTAPI/RESTAPI_db_helpers.h" | ||||||
|  |  | ||||||
| namespace OpenWifi{ | namespace OpenWifi{ | ||||||
|     void RESTAPI_managementRole_list_handler::DoGet() { |     void RESTAPI_managementRole_list_handler::DoGet() { | ||||||
|         if(!QB_.Select.empty()) { |         return ListHandler<ManagementRoleDB>("roles", DB_, *this); | ||||||
|             return ReturnRecordList<decltype(StorageService()->RolesDB()), |  | ||||||
|             ProvObjects::ManagementRole>("roles",StorageService()->RolesDB(),*this ); |  | ||||||
|         } else if(QB_.CountOnly) { |  | ||||||
|             Poco::JSON::Object  Answer; |  | ||||||
|             auto C = StorageService()->RolesDB().Count(); |  | ||||||
|             return ReturnCountOnly(C); |  | ||||||
|         } else { |  | ||||||
|             ProvObjects::ManagementRoleVec Roles; |  | ||||||
|             StorageService()->RolesDB().GetRecords(QB_.Offset,QB_.Limit,Roles); |  | ||||||
|             return MakeJSONObjectArray("roles", Roles, *this); |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -4,6 +4,7 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include "framework/MicroService.h" | #include "framework/MicroService.h" | ||||||
|  | #include "StorageService.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace OpenWifi { | ||||||
|  |  | ||||||
| @@ -16,9 +17,11 @@ namespace OpenWifi { | |||||||
|             Poco::Net::HTTPRequest::HTTP_OPTIONS}, |             Poco::Net::HTTPRequest::HTTP_OPTIONS}, | ||||||
|             Server, |             Server, | ||||||
|             TransactionId, |             TransactionId, | ||||||
|             Internal) {} |             Internal) { | ||||||
|         static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/managementRole"}; }; |         } | ||||||
|  |         static auto PathName() { return std::list<std::string>{"/api/v1/managementRole"}; }; | ||||||
|  |     private: | ||||||
|  |         ManagementRoleDB    &DB_=StorageService()->RolesDB(); | ||||||
|         void DoGet() final; |         void DoGet() final; | ||||||
|         void DoPost() final {}; |         void DoPost() final {}; | ||||||
|         void DoPut() final {}; |         void DoPut() final {}; | ||||||
|   | |||||||
| @@ -4,12 +4,10 @@ | |||||||
|  |  | ||||||
| #include "RESTAPI_map_handler.h" | #include "RESTAPI_map_handler.h" | ||||||
|  |  | ||||||
| #include "framework/RESTAPI_protocol.h" |  | ||||||
| #include "RESTObjects/RESTAPI_ProvObjects.h" | #include "RESTObjects/RESTAPI_ProvObjects.h" | ||||||
| #include "StorageService.h" | #include "StorageService.h" | ||||||
| #include "Poco/JSON/Parser.h" | #include "Poco/JSON/Parser.h" | ||||||
| #include "Poco/StringTokenizer.h" | #include "Poco/StringTokenizer.h" | ||||||
| #include "framework/RESTAPI_errors.h" |  | ||||||
| #include "RESTAPI/RESTAPI_db_helpers.h" | #include "RESTAPI/RESTAPI_db_helpers.h" | ||||||
|  |  | ||||||
| namespace OpenWifi{ | namespace OpenWifi{ | ||||||
| @@ -36,17 +34,20 @@ namespace OpenWifi{ | |||||||
|             return NotFound(); |             return NotFound(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(UserInfo_.userinfo.id!=Existing.creator) { |         if( UserInfo_.userinfo.userRole!=SecurityObjects::ROOT && | ||||||
|             return UnAuthorized("You must be the creator of the map to delete it"); |             UserInfo_.userinfo.userRole!=SecurityObjects::ADMIN && | ||||||
|  |             UserInfo_.userinfo.id!=Existing.creator) { | ||||||
|  |             return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(DB_.DeleteRecord("id", Existing.info.id)) { |         DB_.DeleteRecord("id", Existing.info.id); | ||||||
|  |         MoveUsage(StorageService()->PolicyDB(),DB_,Existing.managementPolicy,"",Existing.info.id); | ||||||
|  |         RemoveMembership(StorageService()->EntityDB(),&ProvObjects::Entity::maps,Existing.entity,Existing.info.id); | ||||||
|  |         RemoveMembership(StorageService()->VenueDB(),&ProvObjects::Venue::maps,Existing.venue,Existing.info.id); | ||||||
|         return OK(); |         return OK(); | ||||||
|     } |     } | ||||||
|         InternalError(RESTAPI::Errors::CouldNotBeDeleted); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     static auto ValidateVisibility(const std::string &V) { |     static bool ValidateVisibility(const std::string &V) { | ||||||
|         return (V=="private" || V=="public" || V=="select"); |         return (V=="private" || V=="public" || V=="select"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -56,20 +57,36 @@ namespace OpenWifi{ | |||||||
|             return BadRequest(RESTAPI::Errors::MissingUUID); |             return BadRequest(RESTAPI::Errors::MissingUUID); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         auto Obj = ParseStream(); |         const auto & RawObject = ParsedBody_; | ||||||
|         ProvObjects::Map NewObject; |         ProvObjects::Map NewObject; | ||||||
|         if (!NewObject.from_json(Obj)) { |         if (!NewObject.from_json(RawObject)) { | ||||||
|             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); |             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(!CreateObjectInfo(Obj, UserInfo_.userinfo, NewObject.info)) { |         if(!CreateObjectInfo(RawObject, UserInfo_.userinfo, NewObject.info)) { | ||||||
|             return BadRequest( RESTAPI::Errors::NameMustBeSet); |             return BadRequest( RESTAPI::Errors::NameMustBeSet); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         if(!ValidateVisibility(NewObject.visibility)) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::InvalidVisibilityAttribute); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(RawObject->has("entity")) { | ||||||
|  |             if(!NewObject.entity.empty() && !StorageService()->EntityDB().Exists("id",NewObject.entity)) | ||||||
|  |                 return BadRequest(RESTAPI::Errors::EntityMustExist); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(RawObject->has("managementPolicy")) { | ||||||
|  |             if(!NewObject.managementPolicy.empty() && !StorageService()->PolicyDB().Exists("id",NewObject.managementPolicy)) | ||||||
|  |                 return BadRequest(RESTAPI::Errors::UnknownManagementPolicyUUID); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         NewObject.creator = UserInfo_.userinfo.id; |         NewObject.creator = UserInfo_.userinfo.id; | ||||||
|  |  | ||||||
|         if(DB_.CreateRecord(NewObject)) { |         if(DB_.CreateRecord(NewObject)) { | ||||||
|  |             AddMembership(StorageService()->EntityDB(),&ProvObjects::Entity::maps,NewObject.entity,NewObject.info.id); | ||||||
|  |             AddMembership(StorageService()->VenueDB(),&ProvObjects::Venue::maps,NewObject.venue,NewObject.info.id); | ||||||
|  |             MoveUsage(StorageService()->PolicyDB(),DB_,"",NewObject.managementPolicy,NewObject.info.id); | ||||||
|             Poco::JSON::Object  Answer; |             Poco::JSON::Object  Answer; | ||||||
|             ProvObjects::Map    M; |             ProvObjects::Map    M; | ||||||
|             DB_.GetRecord("id", NewObject.info.id,M); |             DB_.GetRecord("id", NewObject.info.id,M); | ||||||
| @@ -86,7 +103,7 @@ namespace OpenWifi{ | |||||||
|             return NotFound(); |             return NotFound(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         auto RawObject = ParseStream(); |         const auto & RawObject = ParsedBody_; | ||||||
|         ProvObjects::Map NewObject; |         ProvObjects::Map NewObject; | ||||||
|         if(!NewObject.from_json(RawObject)) { |         if(!NewObject.from_json(RawObject)) { | ||||||
|             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); |             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); | ||||||
| @@ -96,33 +113,56 @@ namespace OpenWifi{ | |||||||
|             return BadRequest( RESTAPI::Errors::NameMustBeSet); |             return BadRequest( RESTAPI::Errors::NameMustBeSet); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(Existing.creator != UserInfo_.userinfo.id) { |         if( UserInfo_.userinfo.userRole!=SecurityObjects::ROOT && | ||||||
|             if(Existing.visibility == ProvObjects::PRIVATE) { |             UserInfo_.userinfo.userRole!=SecurityObjects::ADMIN && | ||||||
|                 return UnAuthorized(RESTAPI::Errors::InsufficientAccessRights, ACCESS_DENIED); |             UserInfo_.userinfo.id!=Existing.creator) { | ||||||
|  |             return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED); | ||||||
|         } |         } | ||||||
|             if(Existing.visibility == ProvObjects::SELECT) { |  | ||||||
|  |         if( UserInfo_.userinfo.userRole==SecurityObjects::ROOT || | ||||||
|  |             UserInfo_.userinfo.userRole==SecurityObjects::ADMIN) { | ||||||
|  |  | ||||||
|  |         } else if(Existing.creator != UserInfo_.userinfo.id) { | ||||||
|  |             if(Existing.visibility == "private") { | ||||||
|  |                 return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED); | ||||||
|  |             } | ||||||
|  |             if(Existing.visibility == "select") { | ||||||
|  |                 bool allowed=false; | ||||||
|                 for(const auto &i:Existing.access.list) { |                 for(const auto &i:Existing.access.list) { | ||||||
|                     for(const auto &j:i.users.list) { |                     for(const auto &j:i.users.list) { | ||||||
|                         if(j==UserInfo_.userinfo.id) { |                         if(j==UserInfo_.userinfo.id) { | ||||||
|  |                             allowed=true; | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  |                 if(!allowed) { | ||||||
|  |                     return UnAuthorized(RESTAPI::Errors::ACCESS_DENIED); | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if(RawObject->has("entity") && !StorageService()->EntityDB().Exists("id",NewObject.entity)) { |         std::string FromPolicy, ToPolicy; | ||||||
|  |         if(!CreateMove(RawObject,"managementPolicy",&MapDB::RecordName::managementPolicy, Existing, FromPolicy, ToPolicy, StorageService()->PolicyDB())) | ||||||
|             return BadRequest(RESTAPI::Errors::EntityMustExist); |             return BadRequest(RESTAPI::Errors::EntityMustExist); | ||||||
|         } |  | ||||||
|  |  | ||||||
|         AssignIfPresent(RawObject,"entity",Existing.entity); |         std::string FromEntity, ToEntity; | ||||||
|  |         if(!CreateMove(RawObject,"entity",&MapDB::RecordName::entity, Existing, FromEntity, ToEntity, StorageService()->EntityDB())) | ||||||
|  |             return BadRequest(RESTAPI::Errors::EntityMustExist); | ||||||
|  |  | ||||||
|  |         std::string FromVenue, ToVenue; | ||||||
|  |         if(!CreateMove(RawObject,"venue",&MapDB::RecordName::venue, Existing, FromVenue, ToVenue, StorageService()->VenueDB())) | ||||||
|  |             return BadRequest(RESTAPI::Errors::VenueMustExist); | ||||||
|  |  | ||||||
|         AssignIfPresent(RawObject,"data", Existing.data); |         AssignIfPresent(RawObject,"data", Existing.data); | ||||||
|         if(RawObject->has("visibility")) |         if(RawObject->has("visibility")) | ||||||
|             Existing.visibility = NewObject.visibility; |             Existing.visibility = NewObject.visibility; | ||||||
|  |  | ||||||
|         if(DB_.UpdateRecord("id",UUID,Existing)) { |         if(DB_.UpdateRecord("id",UUID,Existing)) { | ||||||
|  |             MoveUsage(StorageService()->PolicyDB(),DB_,FromPolicy,ToPolicy,Existing.info.id); | ||||||
|  |             ManageMembership(StorageService()->EntityDB(),&ProvObjects::Entity::maps,FromEntity,ToEntity,Existing.info.id); | ||||||
|  |             ManageMembership(StorageService()->VenueDB(),&ProvObjects::Venue::maps,FromVenue,ToVenue,Existing.info.id); | ||||||
|  |  | ||||||
|             ProvObjects::Map NewRecord; |             ProvObjects::Map NewRecord; | ||||||
|  |  | ||||||
|             DB_.GetRecord("id", UUID, NewRecord); |             DB_.GetRecord("id", UUID, NewRecord); | ||||||
|             Poco::JSON::Object  Answer; |             Poco::JSON::Object  Answer; | ||||||
|             NewRecord.to_json(Answer); |             NewRecord.to_json(Answer); | ||||||
|   | |||||||
| @@ -17,11 +17,10 @@ namespace OpenWifi { | |||||||
|             Poco::Net::HTTPRequest::HTTP_OPTIONS}, |             Poco::Net::HTTPRequest::HTTP_OPTIONS}, | ||||||
|             Server, |             Server, | ||||||
|             TransactionId, |             TransactionId, | ||||||
|             Internal), |             Internal){} | ||||||
|             DB_(StorageService()->MapDB()){} |         static auto PathName() { return std::list<std::string>{"/api/v1/map/{uuid}"}; }; | ||||||
|             static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/map/{uuid}"}; }; |  | ||||||
|     private: |     private: | ||||||
|         MapDB    &DB_; |         MapDB    &DB_=StorageService()->MapDB(); | ||||||
|         void DoGet() final ; |         void DoGet() final ; | ||||||
|         void DoPost() final ; |         void DoPost() final ; | ||||||
|         void DoPut() final ; |         void DoPut() final ; | ||||||
|   | |||||||
| @@ -9,23 +9,16 @@ | |||||||
|  |  | ||||||
| namespace OpenWifi{ | namespace OpenWifi{ | ||||||
|     void RESTAPI_map_list_handler::DoGet() { |     void RESTAPI_map_list_handler::DoGet() { | ||||||
|  |         const char *BlockName{"list"}; | ||||||
|         if(GetBoolParameter("myMaps",false)) { |         if(GetBoolParameter("myMaps",false)) { | ||||||
|             auto where = StorageService()->MapDB().OP("creator",ORM::EQ,UserInfo_.userinfo.id); |             auto where = DB_.OP("creator",ORM::EQ,UserInfo_.userinfo.id); | ||||||
|             std::vector<ProvObjects::Map>   Maps; |             MapDB::RecordVec Maps; | ||||||
|             StorageService()->MapDB().GetRecords(QB_.Offset,QB_.Limit,Maps,where); |             DB_.GetRecords(QB_.Offset,QB_.Limit,Maps,where); | ||||||
|             return MakeJSONObjectArray("list", Maps, *this); |             return MakeJSONObjectArray(BlockName, Maps, *this); | ||||||
|         } else if(GetBoolParameter("sharedWithMe",false)) { |         } else if(GetBoolParameter("sharedWithMe",false)) { | ||||||
|  |  | ||||||
|         } else if(!QB_.Select.empty()) { |  | ||||||
|             return ReturnRecordList<decltype(StorageService()->MapDB()),ProvObjects::Map>("list",StorageService()->MapDB(),*this ); |  | ||||||
|         } else if(QB_.CountOnly) { |  | ||||||
|             Poco::JSON::Object  Answer; |  | ||||||
|             auto C = StorageService()->MapDB().Count(); |  | ||||||
|             return ReturnCountOnly(C); |  | ||||||
|         } else { |         } else { | ||||||
|             std::vector<ProvObjects::Map>   Maps; |             return ListHandler<MapDB>(BlockName, DB_, *this); | ||||||
|             StorageService()->MapDB().GetRecords(QB_.Offset,QB_.Limit,Maps); |  | ||||||
|             return MakeJSONObjectArray("list", Maps, *this); |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -4,6 +4,7 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include "framework/MicroService.h" | #include "framework/MicroService.h" | ||||||
|  | #include "StorageService.h" | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace OpenWifi { | ||||||
|  |  | ||||||
| @@ -16,9 +17,11 @@ namespace OpenWifi { | |||||||
|             Poco::Net::HTTPRequest::HTTP_OPTIONS}, |             Poco::Net::HTTPRequest::HTTP_OPTIONS}, | ||||||
|             Server, |             Server, | ||||||
|             TransactionId, |             TransactionId, | ||||||
|             Internal) {} |             Internal) { | ||||||
|             static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/map"}; }; |         } | ||||||
|  |         static auto PathName() { return std::list<std::string>{"/api/v1/map"}; }; | ||||||
|  |     private: | ||||||
|  |         MapDB    &DB_=StorageService()->MapDB(); | ||||||
|         void DoGet() final; |         void DoGet() final; | ||||||
|         void DoPost() final {}; |         void DoPost() final {}; | ||||||
|         void DoPut() final {}; |         void DoPut() final {}; | ||||||
|   | |||||||
							
								
								
									
										102
									
								
								src/RESTAPI/RESTAPI_op_contact_handler.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								src/RESTAPI/RESTAPI_op_contact_handler.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,102 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2022-04-07. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #include "RESTAPI_op_contact_handler.h" | ||||||
|  | #include "RESTAPI_db_helpers.h" | ||||||
|  | #include "sdks/SDK_sec.h" | ||||||
|  |  | ||||||
|  | namespace OpenWifi { | ||||||
|  |  | ||||||
|  |     void RESTAPI_op_contact_handler::DoGet() { | ||||||
|  |         auto uuid = GetBinding("uuid",""); | ||||||
|  |         if(uuid.empty()) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::MissingUUID); | ||||||
|  |         } | ||||||
|  |         OpContactDB::RecordName  Existing; | ||||||
|  |         if(!DB_.GetRecord("id",uuid,Existing)) { | ||||||
|  |             return NotFound(); | ||||||
|  |         } | ||||||
|  |         Poco::JSON::Object  Answer; | ||||||
|  |         Existing.to_json(Answer); | ||||||
|  |         return ReturnObject(Answer); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void RESTAPI_op_contact_handler::DoDelete() { | ||||||
|  |         auto uuid = GetBinding("uuid",""); | ||||||
|  |         if(uuid.empty()) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::MissingUUID); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         OpContactDB::RecordName  Existing; | ||||||
|  |         if(!DB_.GetRecord("id",uuid,Existing)) { | ||||||
|  |             return NotFound(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // see if anyone is still using this thing | ||||||
|  |         if(!Existing.subscriberDeviceId.empty()){ | ||||||
|  |             return BadRequest(RESTAPI::Errors::StillInUse); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         DB_.DeleteRecord("id", uuid); | ||||||
|  |         return OK(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void RESTAPI_op_contact_handler::DoPost() { | ||||||
|  |  | ||||||
|  |         const auto & RawObject = ParsedBody_; | ||||||
|  |         OpContactDB::RecordName   NewObject; | ||||||
|  |         if(!NewObject.from_json(RawObject)) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if( !ValidDbId(NewObject.operatorId,StorageService()->OperatorDB(), false, RESTAPI::Errors::InvalidOperatorId, *this ) || | ||||||
|  |             !ValidDbId(NewObject.managementPolicy,StorageService()->PolicyDB(), true, RESTAPI::Errors::UnknownManagementPolicyUUID, *this ) || | ||||||
|  |             !ValidDbId(NewObject.subscriberDeviceId,StorageService()->SubscriberDeviceDB(), true, RESTAPI::Errors::InvalidSubscriberDeviceId, *this ) || | ||||||
|  |             !ValidContactType(NewObject.type,*this) ) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         ProvObjects::CreateObjectInfo(RawObject, UserInfo_.userinfo, NewObject.info); | ||||||
|  |         return ReturnCreatedObject(DB_,NewObject,*this); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void RESTAPI_op_contact_handler::DoPut() { | ||||||
|  |         auto uuid = GetBinding("uuid"); | ||||||
|  |         OpContactDB::RecordName   Existing; | ||||||
|  |         if(uuid.empty() || !DB_.GetRecord("id",uuid,Existing)) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::MissingUUID); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         const auto & RawObject = ParsedBody_; | ||||||
|  |         OpContactDB::RecordName   UpdateObj; | ||||||
|  |         if(!UpdateObj.from_json(RawObject)) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if( !ValidContactType(UpdateObj.type,*this)     || | ||||||
|  |             !ValidDbId(UpdateObj.managementPolicy,StorageService()->PolicyDB(), true, RESTAPI::Errors::UnknownManagementPolicyUUID, *this ) || | ||||||
|  |             !ValidDbId(UpdateObj.subscriberDeviceId,StorageService()->SubscriberDeviceDB(), true, RESTAPI::Errors::InvalidSubscriberDeviceId, *this ) | ||||||
|  |                 ) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         ProvObjects::UpdateObjectInfo(RawObject, UserInfo_.userinfo, Existing.info); | ||||||
|  |         AssignIfPresent(RawObject,"type",Existing.type); | ||||||
|  |         AssignIfPresent(RawObject,"title",Existing.title); | ||||||
|  |         AssignIfPresent(RawObject,"salutation",Existing.salutation); | ||||||
|  |         AssignIfPresent(RawObject,"firstname",Existing.firstname); | ||||||
|  |         AssignIfPresent(RawObject,"lastname",Existing.lastname); | ||||||
|  |         AssignIfPresent(RawObject,"initials",Existing.initials); | ||||||
|  |         AssignIfPresent(RawObject,"visual",Existing.visual); | ||||||
|  |         AssignIfPresent(RawObject,"mobiles",Existing.mobiles); | ||||||
|  |         AssignIfPresent(RawObject,"phones",Existing.phones); | ||||||
|  |         AssignIfPresent(RawObject,"accessPIN",Existing.accessPIN); | ||||||
|  |         AssignIfPresent(RawObject,"secondaryEmail",Existing.secondaryEmail); | ||||||
|  |         AssignIfPresent(RawObject,"primaryEmail",Existing.primaryEmail); | ||||||
|  |         AssignIfPresent(RawObject,"subscriberDeviceId",Existing.subscriberDeviceId); | ||||||
|  |         AssignIfPresent(RawObject,"managementPolicy",Existing.managementPolicy); | ||||||
|  |  | ||||||
|  |         return ReturnUpdatedObject(DB_,Existing,*this); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										30
									
								
								src/RESTAPI/RESTAPI_op_contact_handler.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/RESTAPI/RESTAPI_op_contact_handler.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2022-04-07. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "framework/MicroService.h" | ||||||
|  | #include "StorageService.h" | ||||||
|  |  | ||||||
|  | namespace OpenWifi { | ||||||
|  |     class RESTAPI_op_contact_handler : public RESTAPIHandler { | ||||||
|  |     public: | ||||||
|  |         RESTAPI_op_contact_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_PUT, Poco::Net::HTTPRequest::HTTP_DELETE, | ||||||
|  |                                          Poco::Net::HTTPRequest::HTTP_OPTIONS}, | ||||||
|  |                                  Server, | ||||||
|  |                                  TransactionId, | ||||||
|  |                                  Internal){} | ||||||
|  |         static auto PathName() { return std::list<std::string>{"/api/v1/operatorContact/{uuid}"}; }; | ||||||
|  |     private: | ||||||
|  |         OpContactDB    &DB_=StorageService()->OpContactDB(); | ||||||
|  |         void DoGet() final ; | ||||||
|  |         void DoPost() final ; | ||||||
|  |         void DoPut() final ; | ||||||
|  |         void DoDelete() final ; | ||||||
|  |     }; | ||||||
|  | } | ||||||
							
								
								
									
										18
									
								
								src/RESTAPI/RESTAPI_op_contact_list_handler.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/RESTAPI/RESTAPI_op_contact_list_handler.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2022-04-07. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #include "RESTAPI_op_contact_list_handler.h" | ||||||
|  | #include "RESTAPI_db_helpers.h" | ||||||
|  |  | ||||||
|  | namespace OpenWifi { | ||||||
|  |     void RESTAPI_op_contact_list_handler::DoGet() { | ||||||
|  |         auto operatorId= GetParameter("operatorId"); | ||||||
|  |  | ||||||
|  |         if(operatorId.empty() || !StorageService()->OperatorDB().Exists("id",operatorId)) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::OperatorIdMustExist); | ||||||
|  |         } | ||||||
|  |         return ListHandlerForOperator<OpContactDB>("contacts", DB_, *this,operatorId); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										30
									
								
								src/RESTAPI/RESTAPI_op_contact_list_handler.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/RESTAPI/RESTAPI_op_contact_list_handler.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2022-04-07. | ||||||
|  | // | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "framework/MicroService.h" | ||||||
|  | #include "StorageService.h" | ||||||
|  |  | ||||||
|  | namespace OpenWifi { | ||||||
|  |  | ||||||
|  |     class RESTAPI_op_contact_list_handler : public RESTAPIHandler { | ||||||
|  |     public: | ||||||
|  |         RESTAPI_op_contact_list_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 auto PathName() { return std::list<std::string>{"/api/v1/operatorContact"}; }; | ||||||
|  |     private: | ||||||
|  |         OpContactDB    &DB_=StorageService()->OpContactDB(); | ||||||
|  |         void DoGet() final; | ||||||
|  |         void DoPost() final {}; | ||||||
|  |         void DoPut() final {}; | ||||||
|  |         void DoDelete() final {}; | ||||||
|  |     }; | ||||||
|  | } | ||||||
							
								
								
									
										99
									
								
								src/RESTAPI/RESTAPI_op_location_handler.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								src/RESTAPI/RESTAPI_op_location_handler.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,99 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2022-04-07. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #include "RESTAPI_op_location_handler.h" | ||||||
|  | #include "sdks/SDK_sec.h" | ||||||
|  | #include "RESTAPI/RESTAPI_db_helpers.h" | ||||||
|  |  | ||||||
|  | namespace OpenWifi { | ||||||
|  |  | ||||||
|  |     void RESTAPI_op_location_handler::DoGet() { | ||||||
|  |         auto uuid = GetBinding("uuid",""); | ||||||
|  |         if(uuid.empty()) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::MissingUUID); | ||||||
|  |         } | ||||||
|  |         OpLocationDB::RecordName  Existing; | ||||||
|  |         if(!DB_.GetRecord("id",uuid,Existing)) { | ||||||
|  |             return NotFound(); | ||||||
|  |         } | ||||||
|  |         Poco::JSON::Object  Answer; | ||||||
|  |         Existing.to_json(Answer); | ||||||
|  |         return ReturnObject(Answer); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void RESTAPI_op_location_handler::DoDelete() { | ||||||
|  |         auto uuid = GetBinding("uuid",""); | ||||||
|  |         if(uuid.empty()) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::MissingUUID); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         OpLocationDB::RecordName  Existing; | ||||||
|  |         if(!DB_.GetRecord("id",uuid,Existing)) { | ||||||
|  |             return NotFound(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // see if anyone is still using this thing | ||||||
|  |         if(!Existing.subscriberDeviceId.empty()){ | ||||||
|  |             return BadRequest(RESTAPI::Errors::StillInUse); | ||||||
|  |         } | ||||||
|  |         DB_.DeleteRecord("id", uuid); | ||||||
|  |         return OK(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void RESTAPI_op_location_handler::DoPost() { | ||||||
|  |  | ||||||
|  |         const auto & RawObject = ParsedBody_; | ||||||
|  |         OpLocationDB::RecordName   NewObject; | ||||||
|  |         if(!NewObject.from_json(RawObject)) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if( !ValidDbId(NewObject.operatorId,StorageService()->OperatorDB(), false, RESTAPI::Errors::InvalidOperatorId, *this ) || | ||||||
|  |             !ValidDbId(NewObject.managementPolicy,StorageService()->PolicyDB(), true, RESTAPI::Errors::UnknownManagementPolicyUUID, *this ) || | ||||||
|  |             !ValidDbId(NewObject.subscriberDeviceId,StorageService()->SubscriberDeviceDB(), true, RESTAPI::Errors::InvalidSubscriberDeviceId, *this ) || | ||||||
|  |             !ValidLocationType(NewObject.type,*this)) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         ProvObjects::CreateObjectInfo(RawObject, UserInfo_.userinfo, NewObject.info); | ||||||
|  |         return ReturnCreatedObject(DB_, NewObject, *this); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void RESTAPI_op_location_handler::DoPut() { | ||||||
|  |         auto uuid = GetBinding("uuid"); | ||||||
|  |         OpLocationDB::RecordName   Existing; | ||||||
|  |         if(uuid.empty() || !DB_.GetRecord("id",uuid,Existing)) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::MissingUUID); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         const auto RawObject = ParsedBody_; | ||||||
|  |         OpLocationDB::RecordName   UpdateObj; | ||||||
|  |         if(!UpdateObj.from_json(RawObject)) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if( !ValidLocationType(UpdateObj.type,*this)     || | ||||||
|  |             !ValidDbId(UpdateObj.managementPolicy,StorageService()->PolicyDB(), true, RESTAPI::Errors::UnknownManagementPolicyUUID, *this ) || | ||||||
|  |             !ValidDbId(UpdateObj.subscriberDeviceId,StorageService()->SubscriberDeviceDB(), true, RESTAPI::Errors::InvalidSubscriberDeviceId, *this ) | ||||||
|  |             ) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         ProvObjects::UpdateObjectInfo(RawObject, UserInfo_.userinfo, Existing.info); | ||||||
|  |         AssignIfPresent(RawObject,"type",Existing.type); | ||||||
|  |         AssignIfPresent(RawObject,"subscriberDeviceId", Existing.subscriberDeviceId); | ||||||
|  |         AssignIfPresent(RawObject,"managementPolicy", Existing.managementPolicy); | ||||||
|  |         AssignIfPresent(RawObject,"buildingName",Existing.buildingName); | ||||||
|  |         AssignIfPresent(RawObject,"addressLines",Existing.addressLines); | ||||||
|  |         AssignIfPresent(RawObject,"city",Existing.city); | ||||||
|  |         AssignIfPresent(RawObject,"state",Existing.state); | ||||||
|  |         AssignIfPresent(RawObject,"postal",Existing.postal); | ||||||
|  |         AssignIfPresent(RawObject,"country",Existing.country); | ||||||
|  |         AssignIfPresent(RawObject,"mobiles",Existing.mobiles); | ||||||
|  |         AssignIfPresent(RawObject,"phones",Existing.phones); | ||||||
|  |         AssignIfPresent(RawObject,"geoCode",Existing.geoCode); | ||||||
|  |  | ||||||
|  |         return ReturnUpdatedObject(DB_,Existing,*this); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										30
									
								
								src/RESTAPI/RESTAPI_op_location_handler.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/RESTAPI/RESTAPI_op_location_handler.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2022-04-07. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "framework/MicroService.h" | ||||||
|  | #include "StorageService.h" | ||||||
|  |  | ||||||
|  | namespace OpenWifi { | ||||||
|  |     class RESTAPI_op_location_handler : public RESTAPIHandler { | ||||||
|  |     public: | ||||||
|  |         RESTAPI_op_location_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_PUT, Poco::Net::HTTPRequest::HTTP_DELETE, | ||||||
|  |                                          Poco::Net::HTTPRequest::HTTP_OPTIONS}, | ||||||
|  |                                  Server, | ||||||
|  |                                  TransactionId, | ||||||
|  |                                  Internal){} | ||||||
|  |         static auto PathName() { return std::list<std::string>{"/api/v1/operatorLocation/{uuid}"}; }; | ||||||
|  |     private: | ||||||
|  |         OpLocationDB    &DB_=StorageService()->OpLocationDB(); | ||||||
|  |         void DoGet() final ; | ||||||
|  |         void DoPost() final ; | ||||||
|  |         void DoPut() final ; | ||||||
|  |         void DoDelete() final ; | ||||||
|  |     }; | ||||||
|  | } | ||||||
							
								
								
									
										18
									
								
								src/RESTAPI/RESTAPI_op_location_list_handler.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/RESTAPI/RESTAPI_op_location_list_handler.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2022-04-07. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #include "RESTAPI_op_location_list_handler.h" | ||||||
|  | #include "RESTAPI_db_helpers.h" | ||||||
|  |  | ||||||
|  | namespace OpenWifi { | ||||||
|  |     void RESTAPI_op_location_list_handler::DoGet() { | ||||||
|  |         auto operatorId= GetParameter("operatorId"); | ||||||
|  |  | ||||||
|  |         if(operatorId.empty() || !StorageService()->OperatorDB().Exists("id",operatorId)) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::OperatorIdMustExist); | ||||||
|  |         } | ||||||
|  |         return ListHandlerForOperator<OpLocationDB>("locations", DB_, *this,operatorId); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										31
									
								
								src/RESTAPI/RESTAPI_op_location_list_handler.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/RESTAPI/RESTAPI_op_location_list_handler.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2022-04-07. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "framework/MicroService.h" | ||||||
|  | #include "StorageService.h" | ||||||
|  |  | ||||||
|  | namespace OpenWifi { | ||||||
|  |  | ||||||
|  |     class RESTAPI_op_location_list_handler : public RESTAPIHandler { | ||||||
|  |     public: | ||||||
|  |         RESTAPI_op_location_list_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 auto PathName() { return std::list<std::string>{"/api/v1/operatorLocation"}; }; | ||||||
|  |     private: | ||||||
|  |         OpLocationDB    &DB_=StorageService()->OpLocationDB(); | ||||||
|  |         void DoGet() final; | ||||||
|  |         void DoPost() final {}; | ||||||
|  |         void DoPut() final {}; | ||||||
|  |         void DoDelete() final {}; | ||||||
|  |     }; | ||||||
|  | } | ||||||
							
								
								
									
										153
									
								
								src/RESTAPI/RESTAPI_operators_handler.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								src/RESTAPI/RESTAPI_operators_handler.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,153 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2022-04-06. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #include "RESTAPI_operators_handler.h" | ||||||
|  | #include "RESTAPI_db_helpers.h" | ||||||
|  |  | ||||||
|  | namespace OpenWifi { | ||||||
|  |  | ||||||
|  |     void RESTAPI_operators_handler::DoGet() { | ||||||
|  |         auto uuid = GetBinding("uuid",""); | ||||||
|  |         if(uuid.empty()) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::MissingUUID); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         OperatorDB::RecordName  Existing; | ||||||
|  |         if(!DB_.GetRecord("id",uuid,Existing)) { | ||||||
|  |             return NotFound(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         Poco::JSON::Object  Answer; | ||||||
|  |         Existing.to_json(Answer); | ||||||
|  |         return ReturnObject(Answer); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void RESTAPI_operators_handler::DoDelete() { | ||||||
|  |         auto uuid = GetBinding("uuid",""); | ||||||
|  |         if(uuid.empty()) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::MissingUUID); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         OperatorDB::RecordName  Existing; | ||||||
|  |         if(!DB_.GetRecord("id",uuid,Existing)) { | ||||||
|  |             return NotFound(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(Existing.defaultOperator) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::CannotDeleteDefaultOperator); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         //  Let's see if there are any subscribers in this operator | ||||||
|  |         auto Count = StorageService()->SubscriberDeviceDB().Count(fmt::format(" operatorId='{}'", uuid)); | ||||||
|  |         if(Count>0) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::StillInUse); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         DB_.DeleteRecord("id",uuid); | ||||||
|  |         StorageService()->ServiceClassDB().DeleteRecords(fmt::format(" operatorId='{}'", uuid)); | ||||||
|  |         return OK(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void RESTAPI_operators_handler::DoPost() { | ||||||
|  |  | ||||||
|  |         const auto & RawObject = ParsedBody_; | ||||||
|  |         ProvObjects::Operator   NewObject; | ||||||
|  |         if(!NewObject.from_json(RawObject)) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(NewObject.defaultOperator) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::CannotCreateDefaultOperator); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if((RawObject->has("deviceRules") && !ValidDeviceRules(NewObject.deviceRules,*this))) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(RawObject->has("managementPolicy") && !StorageService()->PolicyDB().Exists("id",NewObject.managementPolicy)) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::UnknownManagementPolicyUUID); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(!ValidSourceIP(NewObject.sourceIP)) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::InvalidIPAddresses); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         Poco::toLowerInPlace(NewObject.registrationId); | ||||||
|  |         if(NewObject.registrationId.empty() || DB_.Exists("registrationId",NewObject.registrationId)) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::InvalidRegistrationOperatorName); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         ProvObjects::CreateObjectInfo(RawObject, UserInfo_.userinfo, NewObject.info); | ||||||
|  |         if(DB_.CreateRecord(NewObject)) { | ||||||
|  |  | ||||||
|  |             // Create the default service... | ||||||
|  |             ProvObjects::ServiceClass DefSer; | ||||||
|  |             DefSer.info.id = MicroService::CreateUUID(); | ||||||
|  |             DefSer.info.name = "Default Service Class"; | ||||||
|  |             DefSer.defaultService = true; | ||||||
|  |             DefSer.info.created = DefSer.info.modified = OpenWifi::Now(); | ||||||
|  |             DefSer.operatorId = NewObject.info.id; | ||||||
|  |             DefSer.period = "monthly"; | ||||||
|  |             DefSer.billingCode = "basic"; | ||||||
|  |             DefSer.currency = "USD"; | ||||||
|  |             StorageService()->ServiceClassDB().CreateRecord(DefSer); | ||||||
|  |  | ||||||
|  |             ProvObjects::Operator   New; | ||||||
|  |             DB_.GetRecord("id",NewObject.info.id,New); | ||||||
|  |             Poco::JSON::Object  Answer; | ||||||
|  |             New.to_json(Answer); | ||||||
|  |             return ReturnObject(Answer); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return InternalError(RESTAPI::Errors::RecordNotCreated); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void RESTAPI_operators_handler::DoPut() { | ||||||
|  |         auto uuid = GetBinding("uuid",""); | ||||||
|  |         if(uuid.empty()) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::MissingUUID); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         ProvObjects::Operator   Existing; | ||||||
|  |         if(!DB_.GetRecord("id",uuid,Existing)) { | ||||||
|  |             return NotFound(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         const auto & RawObject = ParsedBody_; | ||||||
|  |         ProvObjects::Operator   UpdatedObj; | ||||||
|  |         if(!UpdatedObj.from_json(RawObject)) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if((RawObject->has("deviceRules") && !ValidDeviceRules(UpdatedObj.deviceRules,*this))) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(RawObject->has("managementPolicy")) { | ||||||
|  |             if(!StorageService()->PolicyDB().Exists("id",UpdatedObj.managementPolicy)) { | ||||||
|  |                 return BadRequest(RESTAPI::Errors::UnknownManagementPolicyUUID); | ||||||
|  |             } | ||||||
|  |             Existing.managementPolicy = UpdatedObj.managementPolicy; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         ProvObjects::UpdateObjectInfo(RawObject, UserInfo_.userinfo, Existing.info); | ||||||
|  |  | ||||||
|  |         if(RawObject->has("variables")) { | ||||||
|  |             Existing.variables = UpdatedObj.variables; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(RawObject->has("sourceIP")) { | ||||||
|  |             if(!UpdatedObj.sourceIP.empty() && !ValidSourceIP(UpdatedObj.sourceIP)) { | ||||||
|  |                 return BadRequest(RESTAPI::Errors::InvalidIPAddresses); | ||||||
|  |             } | ||||||
|  |             Existing.sourceIP = UpdatedObj.sourceIP; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(RawObject->has("deviceRules")) | ||||||
|  |             Existing.deviceRules = UpdatedObj.deviceRules; | ||||||
|  |  | ||||||
|  |         return ReturnUpdatedObject(DB_, Existing, *this); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										30
									
								
								src/RESTAPI/RESTAPI_operators_handler.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/RESTAPI/RESTAPI_operators_handler.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2022-04-06. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "framework/MicroService.h" | ||||||
|  | #include "StorageService.h" | ||||||
|  |  | ||||||
|  | namespace OpenWifi { | ||||||
|  |     class RESTAPI_operators_handler : public RESTAPIHandler { | ||||||
|  |     public: | ||||||
|  |         RESTAPI_operators_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_PUT, Poco::Net::HTTPRequest::HTTP_DELETE, | ||||||
|  |                                          Poco::Net::HTTPRequest::HTTP_OPTIONS}, | ||||||
|  |                                  Server, | ||||||
|  |                                  TransactionId, | ||||||
|  |                                  Internal){} | ||||||
|  |         static auto PathName() { return std::list<std::string>{"/api/v1/operator/{uuid}"}; }; | ||||||
|  |     private: | ||||||
|  |         OperatorDB    &DB_=StorageService()->OperatorDB(); | ||||||
|  |         void DoGet() final ; | ||||||
|  |         void DoPost() final ; | ||||||
|  |         void DoPut() final ; | ||||||
|  |         void DoDelete() final ; | ||||||
|  |     }; | ||||||
|  | } | ||||||
							
								
								
									
										25
									
								
								src/RESTAPI/RESTAPI_operators_list_handler.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/RESTAPI/RESTAPI_operators_list_handler.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2022-04-06. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #include "RESTAPI_operators_list_handler.h" | ||||||
|  | #include "RESTAPI/RESTAPI_db_helpers.h" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | namespace OpenWifi { | ||||||
|  |     void RESTAPI_operators_list_handler::DoGet() { | ||||||
|  |  | ||||||
|  |             if(QB_.CountOnly) { | ||||||
|  |                 auto Count = DB_.Count(); | ||||||
|  |                 return ReturnCountOnly(Count); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if(!QB_.Select.empty()) { | ||||||
|  |                 return ReturnRecordList<decltype(DB_), ProvObjects::Operator>("operators", DB_, *this); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             std::vector<ProvObjects::Operator>  Entries; | ||||||
|  |             DB_.GetRecords(QB_.Offset,QB_.Limit,Entries); | ||||||
|  |             return MakeJSONObjectArray("operators", Entries, *this); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										30
									
								
								src/RESTAPI/RESTAPI_operators_list_handler.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/RESTAPI/RESTAPI_operators_list_handler.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2022-04-06. | ||||||
|  | // | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "framework/MicroService.h" | ||||||
|  | #include "StorageService.h" | ||||||
|  |  | ||||||
|  | namespace OpenWifi { | ||||||
|  |  | ||||||
|  |     class RESTAPI_operators_list_handler : public RESTAPIHandler { | ||||||
|  |     public: | ||||||
|  |         RESTAPI_operators_list_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 auto PathName() { return std::list<std::string>{"/api/v1/operator"}; }; | ||||||
|  |     private: | ||||||
|  |         OperatorDB    &DB_=StorageService()->OperatorDB(); | ||||||
|  |         void DoGet() final; | ||||||
|  |         void DoPost() final {}; | ||||||
|  |         void DoPut() final {}; | ||||||
|  |         void DoDelete() final {}; | ||||||
|  |     }; | ||||||
|  | } | ||||||
| @@ -15,18 +15,32 @@ | |||||||
| #include "RESTAPI/RESTAPI_entity_list_handler.h" | #include "RESTAPI/RESTAPI_entity_list_handler.h" | ||||||
| #include "RESTAPI/RESTAPI_configurations_handler.h" | #include "RESTAPI/RESTAPI_configurations_handler.h" | ||||||
| #include "RESTAPI/RESTAPI_configurations_list_handler.h" | #include "RESTAPI/RESTAPI_configurations_list_handler.h" | ||||||
| #include "RESTAPI/RESTAPI_webSocketServer.h" |  | ||||||
| #include "RESTAPI/RESTAPI_contact_list_handler.h" | #include "RESTAPI/RESTAPI_contact_list_handler.h" | ||||||
| #include "RESTAPI/RESTAPI_location_list_handler.h" | #include "RESTAPI/RESTAPI_location_list_handler.h" | ||||||
| #include "RESTAPI/RESTAPI_venue_list_handler.h" | #include "RESTAPI/RESTAPI_venue_list_handler.h" | ||||||
| #include "RESTAPI/RESTAPI_managementRole_list_handler.h" | #include "RESTAPI/RESTAPI_managementRole_list_handler.h" | ||||||
| #include "RESTAPI/RESTAPI_map_handler.h" | #include "RESTAPI/RESTAPI_map_handler.h" | ||||||
| #include "RESTAPI/RESTAPI_map_list_handler.h" | #include "RESTAPI/RESTAPI_map_list_handler.h" | ||||||
| #include "RESTAPI_iptocountry_handler.h" | #include "RESTAPI/RESTAPI_iptocountry_handler.h" | ||||||
|  | #include "RESTAPI/RESTAPI_signup_handler.h" | ||||||
|  | #include "RESTAPI/RESTAPI_variables_handler.h" | ||||||
|  | #include "RESTAPI/RESTAPI_variables_list_handler.h" | ||||||
|  | #include "RESTAPI/RESTAPI_asset_server.h" | ||||||
|  | #include "RESTAPI/RESTAPI_service_class_handler.h" | ||||||
|  | #include "RESTAPI/RESTAPI_service_class_list_handler.h" | ||||||
|  | #include "RESTAPI/RESTAPI_operators_handler.h" | ||||||
|  | #include "RESTAPI/RESTAPI_operators_list_handler.h" | ||||||
|  | #include "RESTAPI/RESTAPI_sub_devices_handler.h" | ||||||
|  | #include "RESTAPI/RESTAPI_sub_devices_list_handler.h" | ||||||
|  | #include "RESTAPI/RESTAPI_op_contact_handler.h" | ||||||
|  | #include "RESTAPI/RESTAPI_op_contact_list_handler.h" | ||||||
|  | #include "RESTAPI/RESTAPI_op_location_handler.h" | ||||||
|  | #include "RESTAPI/RESTAPI_op_location_list_handler.h" | ||||||
|  |  | ||||||
|  |  | ||||||
| namespace OpenWifi { | namespace OpenWifi { | ||||||
|  |  | ||||||
|     Poco::Net::HTTPRequestHandler * RESTAPI_ExtRouter(const char *Path, RESTAPIHandler::BindingMap &Bindings, |     Poco::Net::HTTPRequestHandler * RESTAPI_ExtRouter(const std::string &Path, RESTAPIHandler::BindingMap &Bindings, | ||||||
|                                                             Poco::Logger & L, RESTAPI_GenericServer & S, uint64_t TransactionId) { |                                                             Poco::Logger & L, RESTAPI_GenericServer & S, uint64_t TransactionId) { | ||||||
|         return  RESTAPI_Router< |         return  RESTAPI_Router< | ||||||
|                     RESTAPI_system_command, |                     RESTAPI_system_command, | ||||||
| @@ -48,18 +62,60 @@ namespace OpenWifi { | |||||||
|                     RESTAPI_map_handler, |                     RESTAPI_map_handler, | ||||||
|                     RESTAPI_map_list_handler, |                     RESTAPI_map_list_handler, | ||||||
|                     RESTAPI_webSocketServer, |                     RESTAPI_webSocketServer, | ||||||
|                     RESTAPI_iptocountry_handler |                     RESTAPI_iptocountry_handler, | ||||||
|  |                     RESTAPI_signup_handler, | ||||||
|  |                     RESTAPI_variables_handler, | ||||||
|  |                     RESTAPI_variables_list_handler, | ||||||
|  |                     RESTAPI_sub_devices_handler, | ||||||
|  |                     RESTAPI_sub_devices_list_handler, | ||||||
|  |                     RESTAPI_operators_handler, | ||||||
|  |                     RESTAPI_operators_list_handler, | ||||||
|  |                     RESTAPI_service_class_handler, | ||||||
|  |                     RESTAPI_service_class_list_handler, | ||||||
|  |                     RESTAPI_op_contact_handler, | ||||||
|  |                     RESTAPI_op_contact_list_handler, | ||||||
|  |                     RESTAPI_op_location_handler, | ||||||
|  |                     RESTAPI_op_location_list_handler, | ||||||
|  |                     RESTAPI_asset_server | ||||||
|                 >(Path,Bindings,L, S, TransactionId); |                 >(Path,Bindings,L, S, TransactionId); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     Poco::Net::HTTPRequestHandler * RESTAPI_IntRouter(const char *Path, RESTAPIHandler::BindingMap &Bindings, |     Poco::Net::HTTPRequestHandler * RESTAPI_IntRouter(const std::string &Path, RESTAPIHandler::BindingMap &Bindings, | ||||||
|                                                             Poco::Logger & L, RESTAPI_GenericServer & S, uint64_t TransactionId) { |                                                             Poco::Logger & L, RESTAPI_GenericServer & S, uint64_t TransactionId) { | ||||||
|         return RESTAPI_Router_I< |         return RESTAPI_Router_I< | ||||||
|                 RESTAPI_system_command , |                 RESTAPI_system_command, | ||||||
|  |                 RESTAPI_entity_handler, | ||||||
|  |                 RESTAPI_entity_list_handler, | ||||||
|  |                 RESTAPI_contact_handler, | ||||||
|  |                 RESTAPI_contact_list_handler, | ||||||
|  |                 RESTAPI_location_handler, | ||||||
|  |                 RESTAPI_location_list_handler, | ||||||
|  |                 RESTAPI_venue_handler, | ||||||
|  |                 RESTAPI_venue_list_handler, | ||||||
|                 RESTAPI_inventory_handler, |                 RESTAPI_inventory_handler, | ||||||
|  |                 RESTAPI_inventory_list_handler, | ||||||
|  |                 RESTAPI_managementPolicy_handler, | ||||||
|  |                 RESTAPI_managementPolicy_list_handler, | ||||||
|  |                 RESTAPI_managementRole_list_handler, | ||||||
|                 RESTAPI_configurations_handler, |                 RESTAPI_configurations_handler, | ||||||
|                 RESTAPI_configurations_list_handler, |                 RESTAPI_configurations_list_handler, | ||||||
|                 RESTAPI_iptocountry_handler |                 RESTAPI_map_handler, | ||||||
|  |                 RESTAPI_map_list_handler, | ||||||
|  |                 RESTAPI_webSocketServer, | ||||||
|  |                 RESTAPI_iptocountry_handler, | ||||||
|  |                 RESTAPI_signup_handler, | ||||||
|  |                 RESTAPI_variables_handler, | ||||||
|  |                 RESTAPI_variables_list_handler, | ||||||
|  |                 RESTAPI_sub_devices_handler, | ||||||
|  |                 RESTAPI_sub_devices_list_handler, | ||||||
|  |                 RESTAPI_operators_handler, | ||||||
|  |                 RESTAPI_operators_list_handler, | ||||||
|  |                 RESTAPI_service_class_handler, | ||||||
|  |                 RESTAPI_service_class_list_handler, | ||||||
|  |                 RESTAPI_op_contact_handler, | ||||||
|  |                 RESTAPI_op_contact_list_handler, | ||||||
|  |                 RESTAPI_op_location_handler, | ||||||
|  |                 RESTAPI_op_location_list_handler | ||||||
|         >(Path, Bindings, L, S, TransactionId); |         >(Path, Bindings, L, S, TransactionId); | ||||||
|     } |     } | ||||||
| } | } | ||||||
							
								
								
									
										112
									
								
								src/RESTAPI/RESTAPI_service_class_handler.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								src/RESTAPI/RESTAPI_service_class_handler.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,112 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2022-04-06. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #include "RESTAPI_service_class_handler.h" | ||||||
|  | #include "RESTAPI_db_helpers.h" | ||||||
|  |  | ||||||
|  | namespace OpenWifi { | ||||||
|  |  | ||||||
|  |     void RESTAPI_service_class_handler::DoGet() { | ||||||
|  |         auto uuid = GetBinding("uuid",""); | ||||||
|  |         if(uuid.empty()) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::MissingUUID); | ||||||
|  |         } | ||||||
|  |         ServiceClassDB::RecordName  Existing; | ||||||
|  |         if(!DB_.GetRecord("id",uuid,Existing)) { | ||||||
|  |             return NotFound(); | ||||||
|  |         } | ||||||
|  |         Poco::JSON::Object  Answer; | ||||||
|  |         Existing.to_json(Answer); | ||||||
|  |         return ReturnObject(Answer); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void RESTAPI_service_class_handler::DoDelete() { | ||||||
|  |         auto uuid = GetBinding("uuid",""); | ||||||
|  |         if(uuid.empty()) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::MissingUUID); | ||||||
|  |         } | ||||||
|  |         ServiceClassDB::RecordName  Existing; | ||||||
|  |         if(!DB_.GetRecord("id",uuid,Existing)) { | ||||||
|  |             return NotFound(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // see if anyone is still using this thing | ||||||
|  |         auto Count = StorageService()->SubscriberDeviceDB().Count( fmt::format(" serviceClass='{}' ", uuid)); | ||||||
|  |         if(Count>0) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::StillInUse); | ||||||
|  |         } | ||||||
|  |         DB_.DeleteRecord("id", uuid); | ||||||
|  |         return OK(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void RESTAPI_service_class_handler::DoPost() { | ||||||
|  |         const auto & RawObject = ParsedBody_; | ||||||
|  |         ProvObjects::ServiceClass   NewObject; | ||||||
|  |         if(!NewObject.from_json(RawObject)) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(NewObject.operatorId.empty() || !StorageService()->OperatorDB().Exists("id",NewObject.operatorId)) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::MissingUUID); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         ProvObjects::CreateObjectInfo(RawObject, UserInfo_.userinfo, NewObject.info); | ||||||
|  |  | ||||||
|  |         if(RawObject->has("managementPolicy") && !StorageService()->PolicyDB().Exists("id",NewObject.managementPolicy)) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::UnknownManagementPolicyUUID); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(NewObject.billingCode.empty()) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::InvalidBillingCode); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         auto DefaultCount = DB_.Count( fmt::format(" defaultService=true and operatorId='{}' ", NewObject.operatorId)); | ||||||
|  |         if(DefaultCount==0) | ||||||
|  |             NewObject.defaultService=true; | ||||||
|  |         else | ||||||
|  |             NewObject.defaultService=false; | ||||||
|  |  | ||||||
|  |         if(NewObject.period.empty()) | ||||||
|  |             NewObject.period = "monthly"; | ||||||
|  |  | ||||||
|  |         if(!ValidPeriod(NewObject.period)) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::InvalidBillingPeriod); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return ReturnCreatedObject(DB_, NewObject, *this); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void RESTAPI_service_class_handler::DoPut() { | ||||||
|  |         auto uuid = GetBinding("uuid",""); | ||||||
|  |  | ||||||
|  |         ProvObjects::ServiceClass   Existing; | ||||||
|  |         if(uuid.empty() || !DB_.GetRecord("id",uuid,Existing)) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::MissingUUID); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         const auto & RawObject = ParsedBody_; | ||||||
|  |         ProvObjects::ServiceClass   UpdateObj; | ||||||
|  |         if(!UpdateObj.from_json(RawObject)) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(RawObject->has("managementPolicy") && !StorageService()->PolicyDB().Exists("id",UpdateObj.managementPolicy)) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::UnknownManagementPolicyUUID); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         ProvObjects::UpdateObjectInfo(RawObject, UserInfo_.userinfo, Existing.info); | ||||||
|  |         AssignIfPresent(RawObject,"cost",Existing.cost); | ||||||
|  |         AssignIfPresent(RawObject,"currency",Existing.currency); | ||||||
|  |         if(RawObject->has("billingCode") && UpdateObj.billingCode.empty()) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::InvalidBillingCode); | ||||||
|  |         } | ||||||
|  |         AssignIfPresent(RawObject,"billingCode",Existing.billingCode); | ||||||
|  |  | ||||||
|  |         if(RawObject->has("variables")) { | ||||||
|  |             Existing.variables = UpdateObj.variables; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return ReturnUpdatedObject(DB_, Existing, *this); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										30
									
								
								src/RESTAPI/RESTAPI_service_class_handler.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/RESTAPI/RESTAPI_service_class_handler.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2022-04-06. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "framework/MicroService.h" | ||||||
|  | #include "StorageService.h" | ||||||
|  |  | ||||||
|  | namespace OpenWifi { | ||||||
|  |     class RESTAPI_service_class_handler : public RESTAPIHandler { | ||||||
|  |     public: | ||||||
|  |         RESTAPI_service_class_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_PUT, Poco::Net::HTTPRequest::HTTP_DELETE, | ||||||
|  |                                          Poco::Net::HTTPRequest::HTTP_OPTIONS}, | ||||||
|  |                                  Server, | ||||||
|  |                                  TransactionId, | ||||||
|  |                                  Internal){} | ||||||
|  |         static auto PathName() { return std::list<std::string>{"/api/v1/serviceClass/{uuid}"}; }; | ||||||
|  |     private: | ||||||
|  |         ServiceClassDB    &DB_=StorageService()->ServiceClassDB(); | ||||||
|  |         void DoGet() final ; | ||||||
|  |         void DoPost() final ; | ||||||
|  |         void DoPut() final ; | ||||||
|  |         void DoDelete() final ; | ||||||
|  |     }; | ||||||
|  | } | ||||||
							
								
								
									
										19
									
								
								src/RESTAPI/RESTAPI_service_class_list_handler.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/RESTAPI/RESTAPI_service_class_list_handler.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2022-04-06. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #include "RESTAPI_service_class_list_handler.h" | ||||||
|  | #include "RESTAPI/RESTAPI_db_helpers.h" | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | namespace OpenWifi { | ||||||
|  |     void RESTAPI_service_class_list_handler::DoGet() { | ||||||
|  |         auto operatorId= GetParameter("operatorId"); | ||||||
|  |  | ||||||
|  |         if(operatorId.empty() || !StorageService()->OperatorDB().Exists("id",operatorId)) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::OperatorIdMustExist); | ||||||
|  |         } | ||||||
|  |         return ListHandlerForOperator<ServiceClassDB>("serviceClasses", DB_, *this,operatorId); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										31
									
								
								src/RESTAPI/RESTAPI_service_class_list_handler.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/RESTAPI/RESTAPI_service_class_list_handler.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2022-04-06. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "framework/MicroService.h" | ||||||
|  | #include "StorageService.h" | ||||||
|  |  | ||||||
|  | namespace OpenWifi { | ||||||
|  |  | ||||||
|  |     class RESTAPI_service_class_list_handler : public RESTAPIHandler { | ||||||
|  |     public: | ||||||
|  |         RESTAPI_service_class_list_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 auto PathName() { return std::list<std::string>{"/api/v1/serviceClass"}; }; | ||||||
|  |     private: | ||||||
|  |         ServiceClassDB    &DB_=StorageService()->ServiceClassDB(); | ||||||
|  |         void DoGet() final; | ||||||
|  |         void DoPost() final {}; | ||||||
|  |         void DoPut() final {}; | ||||||
|  |         void DoDelete() final {}; | ||||||
|  |     }; | ||||||
|  | } | ||||||
							
								
								
									
										257
									
								
								src/RESTAPI/RESTAPI_signup_handler.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										257
									
								
								src/RESTAPI/RESTAPI_signup_handler.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,257 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2022-02-20. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #include "RESTAPI_signup_handler.h" | ||||||
|  | #include "StorageService.h" | ||||||
|  | #include "Signup.h" | ||||||
|  |  | ||||||
|  | namespace OpenWifi { | ||||||
|  |  | ||||||
|  |     void RESTAPI_signup_handler::DoPost() { | ||||||
|  |         auto UserName = GetParameter("email"); | ||||||
|  |         Poco::toLowerInPlace(UserName); | ||||||
|  |         Poco::trimInPlace(UserName); | ||||||
|  |  | ||||||
|  |         auto macAddress = GetParameter("macAddress"); | ||||||
|  |         Poco::toLowerInPlace(macAddress); | ||||||
|  |         Poco::trimInPlace(macAddress); | ||||||
|  |  | ||||||
|  |         auto deviceID = GetParameter("deviceID"); | ||||||
|  |         Poco::toLowerInPlace(deviceID); | ||||||
|  |         Poco::trimInPlace(deviceID); | ||||||
|  |  | ||||||
|  |         auto registrationId = GetParameter("registrationId"); | ||||||
|  |         Poco::toLowerInPlace(registrationId); | ||||||
|  |         Poco::trimInPlace(registrationId); | ||||||
|  |  | ||||||
|  |         if(UserName.empty() || macAddress.empty() || registrationId.empty()) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(!Utils::ValidEMailAddress(UserName)) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::InvalidEmailAddress); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(!Utils::ValidSerialNumber(macAddress)) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::InvalidSerialNumber); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(registrationId.empty()) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::InvalidRegistrationOperatorName); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // find the operator id | ||||||
|  |         ProvObjects::Operator   SignupOperator; | ||||||
|  |         if(!StorageService()->OperatorDB().GetRecord("registrationId", registrationId, SignupOperator)) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::InvalidRegistrationOperatorName); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         //  if a signup already exists for this user, we should just return its value completion | ||||||
|  |         SignupDB::RecordVec SEs; | ||||||
|  |         if(StorageService()->SignupDB().GetRecords(0,100, SEs, " email='" + UserName + "' and serialNumber='"+macAddress+"' ")) { | ||||||
|  |             for(const auto &i:SEs) { | ||||||
|  |  | ||||||
|  |                 if(!i.deviceID.empty() && i.deviceID!=deviceID) { | ||||||
|  |                     return BadRequest(RESTAPI::Errors::InvalidDeviceID); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 if (i.statusCode == ProvObjects::SignupStatusCodes::SignupWaitingForEmail || | ||||||
|  |                     i.statusCode == ProvObjects::SignupStatusCodes::SignupWaitingForDevice || | ||||||
|  |                     i.statusCode == ProvObjects::SignupStatusCodes::SignupSuccess ) { | ||||||
|  |                     Logger().information(fmt::format("SIGNUP: Returning existing signup record for '{}'",i.email)); | ||||||
|  |                     Poco::JSON::Object Answer; | ||||||
|  |                     i.to_json(Answer); | ||||||
|  |                     return ReturnObject(Answer); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         //  So we do not have an outstanding signup... | ||||||
|  |         //  Can we actually claim this serial number??? if not, we need to return an error | ||||||
|  |         ProvObjects::InventoryTag   IT; | ||||||
|  |         std::string SerialNumber; | ||||||
|  |         bool FoundIT=false; | ||||||
|  |         for(int Index=0;Index<4;Index++) { | ||||||
|  |             auto TrySerialNumber = Utils::SerialNumberToInt(macAddress); | ||||||
|  |             for (uint i = 0; i < 4; ++i) { | ||||||
|  |                 SerialNumber = Utils::IntToSerialNumber(TrySerialNumber + i); | ||||||
|  |                 if (StorageService()->InventoryDB().GetRecord("serialNumber", SerialNumber, IT)) { | ||||||
|  |                     if (!IT.subscriber.empty()) { | ||||||
|  |                         return BadRequest(RESTAPI::Errors::SerialNumberAlreadyProvisioned); | ||||||
|  |                     } | ||||||
|  |  | ||||||
|  |                     if (!(IT.devClass.empty() || IT.devClass == "subscriber" || IT.devClass == "any")) { | ||||||
|  |                         return BadRequest(RESTAPI::Errors::SerialNumberNotTheProperClass); | ||||||
|  |                     } | ||||||
|  |                     FoundIT = true; | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         //  OK, we can claim this device, can we create a userid? | ||||||
|  |         //  Let's create one | ||||||
|  |         //  If sec.signup("email",uuid); | ||||||
|  |         auto SignupUUID = MicroService::instance().CreateUUID(); | ||||||
|  |         Logger().information(fmt::format("SIGNUP: Creating signup entry for '{}', uuid='{}'",UserName, SignupUUID)); | ||||||
|  |  | ||||||
|  |         Poco::JSON::Object  Body; | ||||||
|  |         OpenAPIRequestPost  CreateUser( uSERVICE_SECURITY, "/api/v1/signup", { | ||||||
|  |                 { "email", UserName }, | ||||||
|  |                 { "signupUUID" , SignupUUID }, | ||||||
|  |                 { "owner" , SignupOperator.info.id }, | ||||||
|  |                 { "operatorName", SignupOperator.registrationId } | ||||||
|  |         }, Body, 30000); | ||||||
|  |  | ||||||
|  |         Poco::JSON::Object::Ptr Answer; | ||||||
|  |         if(CreateUser.Do(Answer) == Poco::Net::HTTPServerResponse::HTTP_OK) { | ||||||
|  |             SecurityObjects::UserInfo   UI; | ||||||
|  |  | ||||||
|  |             UI.from_json(Answer); | ||||||
|  |             std::ostringstream os; | ||||||
|  |             Answer->stringify(os); | ||||||
|  |             Logger().information(fmt::format("SIGNUP: email: '{}' signupID: '{}' userId: '{}'", UserName, SignupUUID, UI.id)); | ||||||
|  |  | ||||||
|  |             //  so create the Signup entry and modify the inventory | ||||||
|  |             ProvObjects::SignupEntry    SE; | ||||||
|  |             SE.info.id = SignupUUID; | ||||||
|  |             SE.info.created = SE.info.modified = SE.submitted = OpenWifi::Now(); | ||||||
|  |             SE.completed = 0 ; | ||||||
|  |             SE.macAddress = macAddress; | ||||||
|  |             SE.error = 0 ; | ||||||
|  |             SE.userId = UI.id; | ||||||
|  |             SE.email = UserName; | ||||||
|  |             SE.deviceID = deviceID; | ||||||
|  |             SE.registrationId = registrationId; | ||||||
|  |             SE.status = "waiting-for-email-verification"; | ||||||
|  |             SE.operatorId = SignupOperator.info.id; | ||||||
|  |             SE.statusCode = ProvObjects::SignupStatusCodes::SignupWaitingForEmail; | ||||||
|  |             StorageService()->SignupDB().CreateRecord(SE); | ||||||
|  |             Signup()->AddOutstandingSignup(SE); | ||||||
|  |  | ||||||
|  |             if(FoundIT) { | ||||||
|  |                 Poco::JSON::Object StateDoc; | ||||||
|  |                 StateDoc.set("method", "signup"); | ||||||
|  |                 StateDoc.set("claimer", UserName); | ||||||
|  |                 StateDoc.set("claimerId", UI.id); | ||||||
|  |                 StateDoc.set("signupUUID", SignupUUID); | ||||||
|  |                 StateDoc.set("errorCode",0); | ||||||
|  |                 StateDoc.set("date", OpenWifi::Now()); | ||||||
|  |                 StateDoc.set("status", "waiting for email-verification"); | ||||||
|  |                 std::ostringstream os2; | ||||||
|  |                 StateDoc.stringify(os2); | ||||||
|  |                 IT.realMacAddress = macAddress; | ||||||
|  |                 IT.state = os2.str(); | ||||||
|  |                 IT.info.modified = OpenWifi::Now(); | ||||||
|  |                 std::cout << "Updating inventory entry: " << SE.macAddress << std::endl; | ||||||
|  |                 StorageService()->InventoryDB().UpdateRecord("id",IT.info.id,IT); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             Poco::JSON::Object  SEAnswer; | ||||||
|  |             SE.to_json(SEAnswer); | ||||||
|  |             return ReturnObject(SEAnswer); | ||||||
|  |         } | ||||||
|  |         return BadRequest(RESTAPI::Errors::UserAlreadyExists); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     //  this will be called by the SEC backend once the password has been verified. | ||||||
|  |     void RESTAPI_signup_handler::DoPut() { | ||||||
|  |         auto SignupUUID = GetParameter("signupUUID"); | ||||||
|  |         auto Operation = GetParameter("operation"); | ||||||
|  |  | ||||||
|  |         Logger().information(fmt::format("signup-progress: {} - {} ", SignupUUID, Operation)); | ||||||
|  |         if(SignupUUID.empty() || Operation.empty()) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         ProvObjects::SignupEntry    SE; | ||||||
|  |         Logger().information(fmt::format("signup-progress: {} - {} fetching entry", SignupUUID, Operation)); | ||||||
|  |         if(!StorageService()->SignupDB().GetRecord("id",SignupUUID,SE)) { | ||||||
|  |             return NotFound(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         Logger().information(fmt::format("signup-progress: {} - {} fetching entry", SignupUUID, Operation)); | ||||||
|  |         if(Operation == "emailVerified" && SE.statusCode==ProvObjects::SignupStatusCodes::SignupWaitingForEmail) { | ||||||
|  |             Logger().information(fmt::format("{}: email {} verified.",SE.info.id, SE.email)); | ||||||
|  |             std::cout << "Verified email for : " << SE.email << std::endl; | ||||||
|  |             SE.info.modified = OpenWifi::Now(); | ||||||
|  |             SE.status = "emailVerified"; | ||||||
|  |             SE.statusCode = ProvObjects::SignupStatusCodes::SignupWaitingForDevice; | ||||||
|  |             StorageService()->SignupDB().UpdateRecord("id", SE.info.id, SE); | ||||||
|  |             Signup()->AddOutstandingSignup(SE); | ||||||
|  |             Poco::JSON::Object  Answer; | ||||||
|  |             SE.to_json(Answer); | ||||||
|  |             return ReturnObject(Answer); | ||||||
|  |         } | ||||||
|  |         Logger().information(fmt::format("signup-progress: {} - {} something is bad", SignupUUID, Operation)); | ||||||
|  |  | ||||||
|  |         return BadRequest(RESTAPI::Errors::UnknownId); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void RESTAPI_signup_handler::DoGet() { | ||||||
|  |         auto EMail = GetParameter("email"); | ||||||
|  |         auto SignupUUID = GetParameter("signupUUID"); | ||||||
|  |         auto macAddress = GetParameter("macAddress"); | ||||||
|  |         auto List = GetBoolParameter("listOnly",false); | ||||||
|  |  | ||||||
|  |         Logger().information(fmt::format("Looking for signup for {}",EMail)); | ||||||
|  |         Poco::JSON::Object          Answer; | ||||||
|  |         ProvObjects::SignupEntry    SE; | ||||||
|  |         if(!SignupUUID.empty()) { | ||||||
|  |             Logger().information(fmt::format("Looking for signup for {}: Signup {}",EMail, SignupUUID)); | ||||||
|  |             if(StorageService()->SignupDB().GetRecord("id", SignupUUID, SE)) { | ||||||
|  |                 SE.to_json(Answer); | ||||||
|  |                 return ReturnObject(Answer); | ||||||
|  |             } | ||||||
|  |             return NotFound(); | ||||||
|  |         } else if(!EMail.empty()) { | ||||||
|  |             SignupDB::RecordVec SEs; | ||||||
|  |             Logger().information(fmt::format("Looking for signup for {}: Signup {}",EMail, SignupUUID)); | ||||||
|  |             if(StorageService()->SignupDB().GetRecords(0,100,SEs, " email='"+EMail+"' ")) { | ||||||
|  |                 return ReturnObject("signups",SEs); | ||||||
|  |             } | ||||||
|  |             return NotFound(); | ||||||
|  |         } else if(!macAddress.empty()) { | ||||||
|  |             SignupDB::RecordVec SEs; | ||||||
|  |             Logger().information(fmt::format("Looking for signup for {}: Mac {}",EMail, macAddress)); | ||||||
|  |             if(StorageService()->SignupDB().GetRecords(0,100,SEs, " serialNumber='"+macAddress+"' ")) { | ||||||
|  |                 return ReturnObject("signups",SEs); | ||||||
|  |             } | ||||||
|  |             return NotFound(); | ||||||
|  |         } else if(List) { | ||||||
|  |             Logger().information(fmt::format("Returning list of signups...",EMail, macAddress)); | ||||||
|  |             SignupDB::RecordVec SEs; | ||||||
|  |             StorageService()->SignupDB().GetRecords(0,100,SEs); | ||||||
|  |             return ReturnObject("signups",SEs); | ||||||
|  |         } | ||||||
|  |         Logger().information(fmt::format("Bad signup get",EMail, macAddress)); | ||||||
|  |         return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void RESTAPI_signup_handler::DoDelete() { | ||||||
|  |         auto EMail = GetParameter("email", ""); | ||||||
|  |         auto SignupUUID = GetParameter("signupUUID", ""); | ||||||
|  |         auto macAddress = GetParameter("macAddress", ""); | ||||||
|  |         auto deviceID = GetParameter("deviceID",""); | ||||||
|  |  | ||||||
|  |         if(!SignupUUID.empty()) { | ||||||
|  |             if(StorageService()->SignupDB().DeleteRecord("id", SignupUUID)) { | ||||||
|  |                 return OK(); | ||||||
|  |             } | ||||||
|  |             return NotFound(); | ||||||
|  |         } else if(!EMail.empty()) { | ||||||
|  |             if(StorageService()->SignupDB().DeleteRecord("email",EMail)) { | ||||||
|  |                 return OK(); | ||||||
|  |             } | ||||||
|  |             return NotFound(); | ||||||
|  |         } else if(!macAddress.empty()) { | ||||||
|  |             if(StorageService()->SignupDB().DeleteRecord("serialNumber", macAddress)) { | ||||||
|  |                 return OK(); | ||||||
|  |             } | ||||||
|  |             return NotFound(); | ||||||
|  |         } | ||||||
|  |         return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										41
									
								
								src/RESTAPI/RESTAPI_signup_handler.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/RESTAPI/RESTAPI_signup_handler.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2022-02-20. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "framework/MicroService.h" | ||||||
|  |  | ||||||
|  | namespace OpenWifi { | ||||||
|  |     class RESTAPI_signup_handler : public RESTAPIHandler { | ||||||
|  |     public: | ||||||
|  |         RESTAPI_signup_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_OPTIONS, | ||||||
|  |                                          Poco::Net::HTTPRequest::HTTP_PUT, | ||||||
|  |                                          Poco::Net::HTTPRequest::HTTP_GET, | ||||||
|  |                                          Poco::Net::HTTPRequest::HTTP_DELETE}, | ||||||
|  |                                  Server, | ||||||
|  |                                  TransactionId, | ||||||
|  |                                  Internal, false, true ){} | ||||||
|  |  | ||||||
|  |         static auto PathName() { return std::list<std::string>{"/api/v1/signup"}; }; | ||||||
|  |  | ||||||
|  | /*        inline bool RoleIsAuthorized(std::string & Reason) { | ||||||
|  |             if(UserInfo_.userinfo.userRole != SecurityObjects::USER_ROLE::SUBSCRIBER) { | ||||||
|  |                 Reason = "User must be a subscriber"; | ||||||
|  |                 return false; | ||||||
|  |             } | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  | */ | ||||||
|  |         void DoGet() final; | ||||||
|  |         void DoPost() final; | ||||||
|  |         void DoPut() final ; | ||||||
|  |         void DoDelete() final; | ||||||
|  |     private: | ||||||
|  |  | ||||||
|  |     }; | ||||||
|  | } | ||||||
							
								
								
									
										144
									
								
								src/RESTAPI/RESTAPI_sub_devices_handler.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								src/RESTAPI/RESTAPI_sub_devices_handler.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,144 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2022-04-06. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #include "RESTAPI_sub_devices_handler.h" | ||||||
|  | #include "RESTAPI/RESTAPI_db_helpers.h" | ||||||
|  | #include "sdks/SDK_sec.h" | ||||||
|  | #include "sdks/SDK_gw.h" | ||||||
|  | #include "APConfig.h" | ||||||
|  |  | ||||||
|  | namespace OpenWifi { | ||||||
|  |  | ||||||
|  |     void RESTAPI_sub_devices_handler::DoGet() { | ||||||
|  |         auto uuid = GetBinding("uuid"); | ||||||
|  |         if(uuid.empty()) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::MissingUUID); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         ProvObjects::SubscriberDevice   SD; | ||||||
|  |         if(Utils::ValidUUID(uuid)) { | ||||||
|  |             if (!DB_.GetRecord("id", uuid, SD)) { | ||||||
|  |                 return NotFound(); | ||||||
|  |             } | ||||||
|  |         } else if(Utils::ValidSerialNumber(uuid)) { | ||||||
|  |             if (!DB_.GetRecord("serialNumber", uuid, SD)) { | ||||||
|  |                 return NotFound(); | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         Poco::JSON::Object  Answer; | ||||||
|  |         SD.to_json(Answer); | ||||||
|  |         return ReturnObject(Answer); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void RESTAPI_sub_devices_handler::DoDelete() { | ||||||
|  |         auto uuid = GetBinding("uuid"); | ||||||
|  |         if(uuid.empty()) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::MissingUUID); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(!DB_.Exists("id",uuid)) { | ||||||
|  |             return NotFound(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         DB_.DeleteRecord("id",uuid); | ||||||
|  |         return OK(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void RESTAPI_sub_devices_handler::DoPost() { | ||||||
|  |  | ||||||
|  |         const auto & RawObject = ParsedBody_; | ||||||
|  |         SubscriberDeviceDB::RecordName NewObject; | ||||||
|  |         if(!NewObject.from_json(RawObject)) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if( !ValidDbId(NewObject.managementPolicy, StorageService()->PolicyDB(), true , RESTAPI::Errors::UnknownManagementPolicyUUID, *this) || | ||||||
|  |             !ValidDbId(NewObject.operatorId, StorageService()->OperatorDB(), true, RESTAPI::Errors::InvalidOperatorId, *this)                || | ||||||
|  |             !ValidDbId(NewObject.serviceClass, StorageService()->ServiceClassDB(), true, RESTAPI::Errors::InvalidServiceClassId, *this)      || | ||||||
|  |             !ValidSubscriberId(NewObject.subscriberId, true, *this) || | ||||||
|  |             (RawObject->has("deviceRules") && !ValidDeviceRules(NewObject.deviceRules,*this))  || | ||||||
|  |             !ValidSerialNumber(NewObject.serialNumber,false,*this) | ||||||
|  |                 ) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         ProvObjects::CreateObjectInfo(RawObject,UserInfo_.userinfo,NewObject.info); | ||||||
|  |         return ReturnCreatedObject(DB_,NewObject,*this); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void RESTAPI_sub_devices_handler::DoPut() { | ||||||
|  |         auto uuid = GetBinding("uuid"); | ||||||
|  |  | ||||||
|  |         const auto & RawObject = ParsedBody_; | ||||||
|  |         SubscriberDeviceDB::RecordName UpdateObj; | ||||||
|  |         if(!UpdateObj.from_json(RawObject)) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         SubscriberDeviceDB::RecordName  Existing; | ||||||
|  |         if(!DB_.GetRecord("id",uuid,Existing)) { | ||||||
|  |             return NotFound(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if( !ValidDbId(UpdateObj.managementPolicy, StorageService()->PolicyDB(), true , RESTAPI::Errors::UnknownManagementPolicyUUID, *this) || | ||||||
|  |             !ValidDbId(UpdateObj.operatorId, StorageService()->OperatorDB(), true, RESTAPI::Errors::InvalidOperatorId, *this)                || | ||||||
|  |             !ValidDbId(UpdateObj.serviceClass, StorageService()->ServiceClassDB(), true, RESTAPI::Errors::InvalidServiceClassId, *this)      || | ||||||
|  |             !ValidSubscriberId(UpdateObj.subscriberId, true, *this) || | ||||||
|  |             (RawObject->has("deviceRules") && !ValidDeviceRules(UpdateObj.deviceRules,*this))  || | ||||||
|  |             !ValidSerialNumber(UpdateObj.serialNumber,false,*this) | ||||||
|  |                 ) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         ProvObjects::UpdateObjectInfo(RawObject,UserInfo_.userinfo,Existing.info); | ||||||
|  |         AssignIfPresent(RawObject, "deviceType", Existing.deviceType); | ||||||
|  |         AssignIfPresent(RawObject, "subscriberId", Existing.subscriberId); | ||||||
|  |         AssignIfPresent(RawObject, "managementPolicy", Existing.managementPolicy); | ||||||
|  |         AssignIfPresent(RawObject, "serviceClass", Existing.serviceClass); | ||||||
|  |         AssignIfPresent(RawObject, "qrCode", Existing.qrCode); | ||||||
|  |         AssignIfPresent(RawObject, "geoCode", Existing.geoCode); | ||||||
|  |         if(RawObject->has("deviceRules")) | ||||||
|  |             Existing.deviceRules = UpdateObj.deviceRules; | ||||||
|  |         AssignIfPresent(RawObject, "state", Existing.state); | ||||||
|  |         AssignIfPresent(RawObject, "locale", Existing.locale); | ||||||
|  |         AssignIfPresent(RawObject, "billingCode", Existing.billingCode); | ||||||
|  |         AssignIfPresent(RawObject, "realMacAddress", Existing.realMacAddress); | ||||||
|  |         AssignIfPresent(RawObject, "contact", UpdateObj.contact, Existing.contact); | ||||||
|  |         AssignIfPresent(RawObject, "location", UpdateObj.location, Existing.location); | ||||||
|  |  | ||||||
|  |         if(RawObject->has("configuration")) { | ||||||
|  |             Existing.configuration = UpdateObj.configuration; | ||||||
|  |         } | ||||||
|  |         StorageService()->SubscriberDeviceDB().UpdateRecord("id",uuid,Existing); | ||||||
|  |         ApplyConfiguration(Existing.serialNumber); | ||||||
|  |         return ReturnUpdatedObject(DB_,Existing,*this); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     bool RESTAPI_sub_devices_handler::ApplyConfiguration(const std::string &SerialNumber) { | ||||||
|  |         auto Device = std::make_shared<APConfig>(SerialNumber, Logger()); | ||||||
|  |         auto Configuration = Poco::makeShared<Poco::JSON::Object>(); | ||||||
|  |         Poco::JSON::Object ErrorsObj, WarningsObj; | ||||||
|  |         Logger().debug(Poco::format("%s: Computing configuration.",SerialNumber)); | ||||||
|  |         if (Device->Get(Configuration)) { | ||||||
|  |             std::ostringstream OS; | ||||||
|  |             Configuration->stringify(OS); | ||||||
|  |             auto Response=Poco::makeShared<Poco::JSON::Object>(); | ||||||
|  |             Logger().debug(Poco::format("%s: Sending configuration push.",SerialNumber)); | ||||||
|  |             if (SDK::GW::Device::Configure(this, SerialNumber, Configuration, Response)) { | ||||||
|  |                 Logger().debug(Poco::format("%s: Sending configuration pushed.",SerialNumber)); | ||||||
|  |                 return true; | ||||||
|  |             } else { | ||||||
|  |                 Logger().debug(Poco::format("%s: Sending configuration failed.",SerialNumber)); | ||||||
|  |                 return false; | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             Logger().debug(Poco::format("%s: Configuration is bad.",SerialNumber)); | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										32
									
								
								src/RESTAPI/RESTAPI_sub_devices_handler.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/RESTAPI/RESTAPI_sub_devices_handler.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2022-04-06. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "framework/MicroService.h" | ||||||
|  | #include "StorageService.h" | ||||||
|  |  | ||||||
|  | namespace OpenWifi { | ||||||
|  |     class RESTAPI_sub_devices_handler : public RESTAPIHandler { | ||||||
|  |     public: | ||||||
|  |         RESTAPI_sub_devices_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_PUT, Poco::Net::HTTPRequest::HTTP_DELETE, | ||||||
|  |                                          Poco::Net::HTTPRequest::HTTP_OPTIONS}, | ||||||
|  |                                  Server, | ||||||
|  |                                  TransactionId, | ||||||
|  |                                  Internal){} | ||||||
|  |         static auto PathName() { return std::list<std::string>{"/api/v1/subscriberDevice/{uuid}"}; }; | ||||||
|  |         bool ApplyConfiguration(const std::string &SerialNumber); | ||||||
|  |  | ||||||
|  |     private: | ||||||
|  |         SubscriberDeviceDB    &DB_=StorageService()->SubscriberDeviceDB(); | ||||||
|  |         void DoGet() final ; | ||||||
|  |         void DoPost() final ; | ||||||
|  |         void DoPut() final ; | ||||||
|  |         void DoDelete() final ; | ||||||
|  |     }; | ||||||
|  | } | ||||||
							
								
								
									
										22
									
								
								src/RESTAPI/RESTAPI_sub_devices_list_handler.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/RESTAPI/RESTAPI_sub_devices_list_handler.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2022-04-06. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #include "RESTAPI_sub_devices_list_handler.h" | ||||||
|  | #include "RESTAPI/RESTAPI_db_helpers.h" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | namespace OpenWifi { | ||||||
|  |  | ||||||
|  |     void RESTAPI_sub_devices_list_handler::DoGet() { | ||||||
|  |         auto operatorId=GetParameter("operatorId"); | ||||||
|  |         auto subscriberId=GetParameter("subscriberId"); | ||||||
|  |  | ||||||
|  |         if(!operatorId.empty() && !StorageService()->OperatorDB().Exists("id",operatorId)) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::OperatorIdMustExist); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return ListHandlerForOperator<SubscriberDeviceDB>("subscriberDevices", DB_, *this, operatorId, subscriberId); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										31
									
								
								src/RESTAPI/RESTAPI_sub_devices_list_handler.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/RESTAPI/RESTAPI_sub_devices_list_handler.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2022-04-06. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "framework/MicroService.h" | ||||||
|  | #include "StorageService.h" | ||||||
|  |  | ||||||
|  | namespace OpenWifi { | ||||||
|  |  | ||||||
|  |     class RESTAPI_sub_devices_list_handler : public RESTAPIHandler { | ||||||
|  |     public: | ||||||
|  |         RESTAPI_sub_devices_list_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 auto PathName() { return std::list<std::string>{"/api/v1/subscriberDevice"}; }; | ||||||
|  |     private: | ||||||
|  |         SubscriberDeviceDB    &DB_=StorageService()->SubscriberDeviceDB(); | ||||||
|  |         void DoGet() final; | ||||||
|  |         void DoPost() final {}; | ||||||
|  |         void DoPut() final {}; | ||||||
|  |         void DoDelete() final {}; | ||||||
|  |     }; | ||||||
|  | } | ||||||
							
								
								
									
										142
									
								
								src/RESTAPI/RESTAPI_variables_handler.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										142
									
								
								src/RESTAPI/RESTAPI_variables_handler.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,142 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2022-02-23. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #include "RESTAPI_variables_handler.h" | ||||||
|  | #include "RESTAPI_db_helpers.h" | ||||||
|  |  | ||||||
|  | namespace OpenWifi { | ||||||
|  |  | ||||||
|  |     void RESTAPI_variables_handler::DoGet() { | ||||||
|  |         auto UUID = GetBinding("uuid",""); | ||||||
|  |         if(UUID.empty()) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::MissingUUID); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         VariablesDB::RecordName Existing; | ||||||
|  |         if(!DB_.GetRecord("id",UUID,Existing)) { | ||||||
|  |             return NotFound(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         Poco::JSON::Object Answer; | ||||||
|  |         if(QB_.AdditionalInfo) | ||||||
|  |             AddExtendedInfo(Existing, Answer); | ||||||
|  |         Existing.to_json(Answer); | ||||||
|  |         ReturnObject(Answer); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void RESTAPI_variables_handler::DoDelete() { | ||||||
|  |         auto UUID = GetBinding("uuid",""); | ||||||
|  |         if(UUID.empty()) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::MissingUUID); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         VariablesDB::RecordName Existing; | ||||||
|  |         if(!DB_.GetRecord("id",UUID,Existing)) { | ||||||
|  |             return NotFound(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(!Existing.configurations.empty()) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::StillInUse); | ||||||
|  |         } | ||||||
|  |         MoveUsage(StorageService()->PolicyDB(),DB_,Existing.managementPolicy,"",Existing.info.id); | ||||||
|  |         RemoveMembership(StorageService()->VenueDB(),&ProvObjects::Venue::variables,Existing.venue,Existing.info.id); | ||||||
|  |         RemoveMembership(StorageService()->EntityDB(),&ProvObjects::Entity::variables,Existing.entity,Existing.info.id); | ||||||
|  |         DB_.DeleteRecord("id", UUID); | ||||||
|  |  | ||||||
|  |         return OK(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void RESTAPI_variables_handler::DoPost() { | ||||||
|  |         auto UUID = GetBinding("uuid",""); | ||||||
|  |         if(UUID.empty()) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::MissingUUID); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         const auto & RawObj = ParsedBody_; | ||||||
|  |         VariablesDB::RecordName NewObject; | ||||||
|  |         if(!NewObject.from_json(RawObj)) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(!NewObject.entity.empty() && !StorageService()->EntityDB().Exists("id",NewObject.entity)) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::EntityMustExist); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(!NewObject.venue.empty() && !StorageService()->VenueDB().Exists("id",NewObject.venue)) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::VenueMustExist); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(!NewObject.managementPolicy.empty() && !StorageService()->PolicyDB().Exists("id",NewObject.managementPolicy)) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::UnknownManagementPolicyUUID); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(!ProvObjects::CreateObjectInfo(RawObj,UserInfo_.userinfo,NewObject.info)) { | ||||||
|  |             return BadRequest((RESTAPI::Errors::MissingOrInvalidParameters)); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(DB_.CreateRecord(NewObject)) { | ||||||
|  |             MoveUsage(StorageService()->PolicyDB(),DB_,"",NewObject.managementPolicy,NewObject.info.id); | ||||||
|  |             AddMembership(StorageService()->VenueDB(),&ProvObjects::Venue::variables,NewObject.venue, NewObject.info.id); | ||||||
|  |             AddMembership(StorageService()->EntityDB(),&ProvObjects::Entity::variables,NewObject.entity, NewObject.info.id); | ||||||
|  |  | ||||||
|  |             VariablesDB::RecordName Added; | ||||||
|  |             DB_.GetRecord("id",NewObject.info.id,Added); | ||||||
|  |             Poco::JSON::Object  Answer; | ||||||
|  |             Added.to_json(Answer); | ||||||
|  |             return ReturnObject(Answer); | ||||||
|  |         } | ||||||
|  |         return BadRequest(RESTAPI::Errors::RecordNotCreated); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void RESTAPI_variables_handler::DoPut() { | ||||||
|  |         auto UUID = GetBinding("uuid",""); | ||||||
|  |         if(UUID.empty()) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::MissingUUID); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         VariablesDB::RecordName Existing; | ||||||
|  |         if(!StorageService()->VariablesDB().GetRecord("id",UUID,Existing)) { | ||||||
|  |             return NotFound(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         const auto & RawObject = ParsedBody_; | ||||||
|  |         VariablesDB::RecordName NewObj; | ||||||
|  |         if(!NewObj.from_json(RawObject)) { | ||||||
|  |             return BadRequest(RESTAPI::Errors::InvalidJSONDocument); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(!ProvObjects::UpdateObjectInfo(RawObject,UserInfo_.userinfo,Existing.info)) { | ||||||
|  |             return BadRequest((RESTAPI::Errors::MissingOrInvalidParameters)); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if(RawObject->has("variables")) | ||||||
|  |             Existing.variables = NewObj.variables; | ||||||
|  |  | ||||||
|  |         std::string FromPolicy, ToPolicy; | ||||||
|  |         if(!CreateMove(RawObject,"managementPolicy",&VariablesDB::RecordName::managementPolicy, Existing, FromPolicy, ToPolicy, StorageService()->PolicyDB())) | ||||||
|  |             return BadRequest(RESTAPI::Errors::EntityMustExist); | ||||||
|  |  | ||||||
|  |         std::string FromEntity, ToEntity; | ||||||
|  |         if(!CreateMove(RawObject,"entity",&VariablesDB::RecordName::entity, Existing, FromEntity, ToEntity, StorageService()->EntityDB())) | ||||||
|  |             return BadRequest(RESTAPI::Errors::EntityMustExist); | ||||||
|  |  | ||||||
|  |         std::string FromVenue, ToVenue; | ||||||
|  |         if(!CreateMove(RawObject,"venue",&VariablesDB::RecordName::venue, Existing, FromVenue, ToVenue, StorageService()->VenueDB())) | ||||||
|  |             return BadRequest(RESTAPI::Errors::VenueMustExist); | ||||||
|  |  | ||||||
|  |         if(DB_.UpdateRecord("id", UUID, Existing)) { | ||||||
|  |             MoveUsage(StorageService()->PolicyDB(),DB_,FromPolicy,ToPolicy,Existing.info.id); | ||||||
|  |             ManageMembership(StorageService()->VenueDB(), &ProvObjects::Venue::variables, FromVenue, ToVenue, Existing.info.id); | ||||||
|  |             ManageMembership(StorageService()->EntityDB(), &ProvObjects::Entity::variables, FromEntity, ToEntity, Existing.info.id); | ||||||
|  |  | ||||||
|  |             VariablesDB::RecordName Added; | ||||||
|  |             DB_.GetRecord("id",NewObj.info.id,Added); | ||||||
|  |             Poco::JSON::Object  Answer; | ||||||
|  |             Added.to_json(Answer); | ||||||
|  |             return ReturnObject(Answer); | ||||||
|  |         } | ||||||
|  |         return BadRequest(RESTAPI::Errors::RecordNotCreated); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										29
									
								
								src/RESTAPI/RESTAPI_variables_handler.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/RESTAPI/RESTAPI_variables_handler.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2022-02-23. | ||||||
|  | // | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "framework/MicroService.h" | ||||||
|  | #include "StorageService.h" | ||||||
|  |  | ||||||
|  | namespace OpenWifi { | ||||||
|  |     class RESTAPI_variables_handler : public RESTAPIHandler { | ||||||
|  |     public: | ||||||
|  |         RESTAPI_variables_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_PUT, Poco::Net::HTTPRequest::HTTP_DELETE, | ||||||
|  |                                          Poco::Net::HTTPRequest::HTTP_OPTIONS}, | ||||||
|  |                                  Server, | ||||||
|  |                                  TransactionId, | ||||||
|  |                                  Internal){} | ||||||
|  |         static auto PathName() { return std::list<std::string>{"/api/v1/variable/{uuid}"}; }; | ||||||
|  |     private: | ||||||
|  |         VariablesDB    & DB_=StorageService()->VariablesDB(); | ||||||
|  |         void DoGet() final ; | ||||||
|  |         void DoPost() final ; | ||||||
|  |         void DoPut() final ; | ||||||
|  |         void DoDelete() final ; | ||||||
|  |     }; | ||||||
|  | } | ||||||
							
								
								
									
										14
									
								
								src/RESTAPI/RESTAPI_variables_list_handler.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/RESTAPI/RESTAPI_variables_list_handler.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2022-02-23. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #include "RESTAPI_variables_list_handler.h" | ||||||
|  | #include "RESTAPI/RESTAPI_db_helpers.h" | ||||||
|  |  | ||||||
|  | namespace OpenWifi { | ||||||
|  |  | ||||||
|  |     void RESTAPI_variables_list_handler::DoGet() { | ||||||
|  |         return ListHandler<VariablesDB>("variableBlocks", DB_, *this); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										31
									
								
								src/RESTAPI/RESTAPI_variables_list_handler.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/RESTAPI/RESTAPI_variables_list_handler.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | |||||||
|  | // | ||||||
|  | // Created by stephane bourque on 2022-02-23. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "framework/MicroService.h" | ||||||
|  | #include "StorageService.h" | ||||||
|  |  | ||||||
|  | namespace OpenWifi { | ||||||
|  |  | ||||||
|  |     class RESTAPI_variables_list_handler : public RESTAPIHandler { | ||||||
|  |     public: | ||||||
|  |         RESTAPI_variables_list_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 auto PathName() { return std::list<std::string>{"/api/v1/variable"}; }; | ||||||
|  |     private: | ||||||
|  |         VariablesDB    & DB_=StorageService()->VariablesDB(); | ||||||
|  |         void DoGet() final; | ||||||
|  |         void DoPost() final {}; | ||||||
|  |         void DoPut() final {}; | ||||||
|  |         void DoDelete() final {}; | ||||||
|  |     }; | ||||||
|  | } | ||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user