diff --git a/.gitignore b/.gitignore index c5037dc61d8f32e7f14492fcb24c67c621b564a4..502fd1ddc64681c5e5b6f7ea5c3361dfd78443f9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/c_cpp_properties.json -!.vscode/extensions.json +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/c_cpp_properties.json +!.vscode/extensions.json build/* \ No newline at end of file diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 300165b751dc8da6d14eb307836e6aa95573a71e..5afd2f0c77a7aebc65a7e00b66b5b164d52c9f6b 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -1,73 +1,73 @@ -{ - "configurations": [ - { - "name": "Mac", - "includePath": [ - "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/", - "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1", - "usr/local/Cellar/boost/1.60.0_1/include/", - "/usr/local/Cellar/openssl/1.0.2f/include/", - "${workspaceRoot}" - ], - "browse": { - "limitSymbolsToIncludedHeaders": true, - "databaseFilename": "", - "path": [ - "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/", - "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1", - "usr/local/Cellar/boost/1.60.0_1/include/", - "/usr/local/Cellar/openssl/1.0.2f/include/", - "${workspaceRoot}" - ] - }, - "intelliSenseMode": "clang-x64", - "macFrameworkPath": [ - "/System/Library/Frameworks", - "/Library/Frameworks" - ], - "compilerPath": "/usr/bin/gcc", - "cStandard": "gnu17", - "cppStandard": "gnu++14" - }, - { - "name": "Linux", - "includePath": [ - "/usr/include", - "${workspaceRoot}", - "${workspaceFolder}/source/foundation/include" - ], - "browse": { - "limitSymbolsToIncludedHeaders": true, - "databaseFilename": "", - "path": [ - "/usr/include", - "${workspaceRoot}" - ] - }, - "intelliSenseMode": "clang-x64", - "compilerPath": "/usr/bin/gcc", - "cStandard": "gnu17", - "cppStandard": "gnu++14" - }, - { - "name": "Win32", - "includePath": [ - "c:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/include", - "${workspaceRoot}" - ], - "browse": { - "limitSymbolsToIncludedHeaders": true, - "databaseFilename": "", - "path": [ - "c:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/include", - "${workspaceRoot}" - ] - }, - "intelliSenseMode": "msvc-x64", - "compilerPath": "/usr/bin/gcc", - "cStandard": "gnu17", - "cppStandard": "gnu++14" - } - ], - "version": 4 +{ + "configurations": [ + { + "name": "Mac", + "includePath": [ + "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/", + "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1", + "usr/local/Cellar/boost/1.60.0_1/include/", + "/usr/local/Cellar/openssl/1.0.2f/include/", + "${workspaceRoot}" + ], + "browse": { + "limitSymbolsToIncludedHeaders": true, + "databaseFilename": "", + "path": [ + "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/", + "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1", + "usr/local/Cellar/boost/1.60.0_1/include/", + "/usr/local/Cellar/openssl/1.0.2f/include/", + "${workspaceRoot}" + ] + }, + "intelliSenseMode": "clang-x64", + "macFrameworkPath": [ + "/System/Library/Frameworks", + "/Library/Frameworks" + ], + "compilerPath": "/usr/bin/gcc", + "cStandard": "gnu17", + "cppStandard": "gnu++14" + }, + { + "name": "Linux", + "includePath": [ + "/usr/include", + "${workspaceRoot}", + "${workspaceFolder}/source/foundation/include" + ], + "browse": { + "limitSymbolsToIncludedHeaders": true, + "databaseFilename": "", + "path": [ + "/usr/include", + "${workspaceRoot}" + ] + }, + "intelliSenseMode": "clang-x64", + "compilerPath": "/usr/bin/gcc", + "cStandard": "gnu17", + "cppStandard": "gnu++14" + }, + { + "name": "Win32", + "includePath": [ + "c:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/include", + "${workspaceRoot}" + ], + "browse": { + "limitSymbolsToIncludedHeaders": true, + "databaseFilename": "", + "path": [ + "c:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/include", + "${workspaceRoot}" + ] + }, + "intelliSenseMode": "msvc-x64", + "compilerPath": "/usr/bin/gcc", + "cStandard": "gnu17", + "cppStandard": "gnu++14" + } + ], + "version": 4 } \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index 0e6ff24b75495e1d069c338a1b2b02c0eca014a3..0bb12253fee18beb74a85be12683928bddbf68ad 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,69 +1,69 @@ -{ - "version": "0.2.0", - "configurations": [ - { - "name": "C++ Launch", - "type": "cppdbg", - "request": "launch", - "program": "${workspaceRoot}/build/micro-service", - "args": [], - "stopAtEntry": false, - "cwd": "${workspaceRoot}", - "environment": [], - "externalConsole": false, - "linux": { - "MIMode": "gdb", - "setupCommands": [ - { - "description": "Enable pretty-printing for gdb", - "text": "-enable-pretty-printing", - "ignoreFailures": true - } - ] - }, - "osx": { - "MIMode": "lldb" - }, - "windows": { - "MIMode": "gdb", - "setupCommands": [ - { - "description": "Enable pretty-printing for gdb", - "text": "-enable-pretty-printing", - "ignoreFailures": true - } - ] - } - }, - { - "name": "C++ Attach", - "type": "cppdbg", - "request": "attach", - "program": "enter program name, for example ${workspaceRoot}/a.out", - "processId": "${command.pickProcess}", - "linux": { - "MIMode": "gdb", - "setupCommands": [ - { - "description": "Enable pretty-printing for gdb", - "text": "-enable-pretty-printing", - "ignoreFailures": true - } - ] - }, - "osx": { - "MIMode": "lldb" - }, - "windows": { - "MIMode": "gdb", - "setupCommands": [ - { - "description": "Enable pretty-printing for gdb", - "text": "-enable-pretty-printing", - "ignoreFailures": true - } - ] - } - } - ] +{ + "version": "0.2.0", + "configurations": [ + { + "name": "C++ Launch", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceRoot}/build/micro-service", + "args": [], + "stopAtEntry": false, + "cwd": "${workspaceRoot}", + "environment": [], + "externalConsole": false, + "linux": { + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + }, + "osx": { + "MIMode": "lldb" + }, + "windows": { + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + } + }, + { + "name": "C++ Attach", + "type": "cppdbg", + "request": "attach", + "program": "enter program name, for example ${workspaceRoot}/a.out", + "processId": "${command.pickProcess}", + "linux": { + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + }, + "osx": { + "MIMode": "lldb" + }, + "windows": { + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + } + } + ] } \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 5c39598aa6eed5ff1ba328f65dfca39d98994d70..2de608750bd3525d1ee249c37c74f71d5b274d40 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,71 +1,71 @@ -{ - "files.associations": { - "cctype": "cpp", - "clocale": "cpp", - "cmath": "cpp", - "csignal": "cpp", - "cstdarg": "cpp", - "cstddef": "cpp", - "cstdio": "cpp", - "cstdlib": "cpp", - "cstring": "cpp", - "ctime": "cpp", - "cwchar": "cpp", - "cwctype": "cpp", - "array": "cpp", - "atomic": "cpp", - "strstream": "cpp", - "bit": "cpp", - "*.tcc": "cpp", - "bitset": "cpp", - "chrono": "cpp", - "codecvt": "cpp", - "complex": "cpp", - "condition_variable": "cpp", - "cstdint": "cpp", - "deque": "cpp", - "list": "cpp", - "map": "cpp", - "set": "cpp", - "unordered_map": "cpp", - "vector": "cpp", - "exception": "cpp", - "algorithm": "cpp", - "functional": "cpp", - "iterator": "cpp", - "memory": "cpp", - "memory_resource": "cpp", - "numeric": "cpp", - "optional": "cpp", - "random": "cpp", - "ratio": "cpp", - "regex": "cpp", - "string": "cpp", - "string_view": "cpp", - "system_error": "cpp", - "tuple": "cpp", - "type_traits": "cpp", - "utility": "cpp", - "fstream": "cpp", - "future": "cpp", - "initializer_list": "cpp", - "iomanip": "cpp", - "iosfwd": "cpp", - "iostream": "cpp", - "istream": "cpp", - "limits": "cpp", - "mutex": "cpp", - "new": "cpp", - "ostream": "cpp", - "shared_mutex": "cpp", - "sstream": "cpp", - "stdexcept": "cpp", - "streambuf": "cpp", - "thread": "cpp", - "cfenv": "cpp", - "cinttypes": "cpp", - "typeindex": "cpp", - "typeinfo": "cpp", - "variant": "cpp" - } +{ + "files.associations": { + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "csignal": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "array": "cpp", + "atomic": "cpp", + "strstream": "cpp", + "bit": "cpp", + "*.tcc": "cpp", + "bitset": "cpp", + "chrono": "cpp", + "codecvt": "cpp", + "complex": "cpp", + "condition_variable": "cpp", + "cstdint": "cpp", + "deque": "cpp", + "list": "cpp", + "map": "cpp", + "set": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "ratio": "cpp", + "regex": "cpp", + "string": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "future": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "mutex": "cpp", + "new": "cpp", + "ostream": "cpp", + "shared_mutex": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "thread": "cpp", + "cfenv": "cpp", + "cinttypes": "cpp", + "typeindex": "cpp", + "typeinfo": "cpp", + "variant": "cpp" + } } \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index a88f21c891f2527524ba7ee1fb972af7ea02a0b3..5c10bad50c229e64e5037c769e56af7122cbce5f 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -1,28 +1,28 @@ -{ - // See https://go.microsoft.com/fwlink/?LinkId=733558 - // for the documentation about the tasks.json format - "version": "0.1.0", - "command": "sh", - "isShellCommand": true, - "args": ["-c"], - "showOutput": "always", - "suppressTaskName": true, - "options": { - "cwd": "${workspaceRoot}/build" - }, - "tasks": [ - { - "taskName": "cmake", - "args": [ - "cmake -G 'Unix Makefiles' -DCMAKE_BUILD_TYPE=Debug .." - ] - }, - { - "taskName": "make", - "args": [ - "make -j 8" - ], - "isBuildCommand": true - } - ] +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "0.1.0", + "command": "sh", + "isShellCommand": true, + "args": ["-c"], + "showOutput": "always", + "suppressTaskName": true, + "options": { + "cwd": "${workspaceRoot}/build" + }, + "tasks": [ + { + "taskName": "cmake", + "args": [ + "cmake -G 'Unix Makefiles' -DCMAKE_BUILD_TYPE=Debug .." + ] + }, + { + "taskName": "make", + "args": [ + "make -j 8" + ], + "isBuildCommand": true + } + ] } \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 1eefe00c0d21365e06462c416652d9dbae8c1557..0ae0b213d568997e2dda24e05ca38dcfe6be3712 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,92 +1,48 @@ -cmake_minimum_required(VERSION 3.0) - -project(micro-service) - -set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES /usr/local/lib ${CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES}) - -# Configure required libraries ... -if(UNIX) # Darwing or Linux - find_package(Boost REQUIRED COMPONENTS system thread log program_options chrono) - find_package(Threads REQUIRED) - - if(APPLE) - file(GLOB OPENSSL_ROOT_DIR /usr/local/Cellar/openssl/*) - list(REVERSE OPENSSL_ROOT_DIR) - - find_package(OpenSSL 1.0.2 REQUIRED) - set(OPENSSL_VERSION "1.0.2p") - else() - find_package(OpenSSL 1.0.1 REQUIRED) - find_package(cpprestsdk REQUIRED) - find_package(mongocxx REQUIRED) - find_package(bsoncxx REQUIRED) - set(OPENSSL_VERSION "1.0.1") - endif() - -elseif(WIN32) # Windows systems including Win64. - message(FATAL_ERROR "-- Windows is not supported for now.") -else() - message(FATAL_ERROR "-- Unsupported platform sorry! :( ") -endif() - -# Configure compiler options ... -if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") - - message("-- configuring clang options") - set(CMAKE_CXX_FLAGS "-arch x86_64 -std=c++20 -stdlib=libc++ -DBOOST_LOG_DYN_LINK -Wno-deprecated-declarations") - -elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU") - - message("-- configuring gcc options") - - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++17 -DBOOST_LOG_DYN_LINK") - -endif() - -# Project construction ... - -# source files ... -add_executable(${PROJECT_NAME} ./source/main.cpp - ./source/microsvc_controller.cpp - ./source/database_manager.cpp - ./source/foundation/network_utils.cpp - ./source/foundation/basic_controller.cpp) - -# headers search paths ... -set(MICROSERVICE_INCLUDE_DIR "./source/foundation/include") -message(MICROSERVICE " ${MICROSERVICE_INCLUDE_DIR}") -set(HEADER_SEARCH_PATHS ${MICROSERVICE_INCLUDE_DIR} ${Boost_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR}) - -# library search paths ... -if(APPLE) - set(OPENSSL_LIBS "/usr/local/Cellar/openssl/${OPENSSL_VERSION}/lib/libssl.1.0.0.dylib;/usr/local/Cellar/openssl/${OPENSSL_VERSION}/lib/libcrypto.1.0.0.dylib") - set(ZIP_LIBRARY "/usr/local/Cellar/zlib/1.2.11/lib/libz.dylib") - set(LIBRARIES_SEARCH_PATHS ${OPENSSL_LIBS} ${Boost_LIBRARIES} ${ZIP_LIBRARY}) -else() - set(OPENSSL_LIBS "${OPENSSL_LIBRARIES}") - set(LIBRARIES_SEARCH_PATHS ${OPENSSL_LIBS} ${Boost_LIBRARIES}) -endif() - -message(BOOST_LIBS " ${Boost_LIBRARIES}") -message(OPENSSL_LIBS " ${OPENSSL_LIBRARIES}") -message(LIBRARIES_SEARCH_PATHS " ${LIBRARIES_SEARCH_PATHS}") - -include_directories( ${HEADER_SEARCH_PATHS}) -if (APPLE) - target_link_libraries(${PROJECT_NAME} "-framework CoreFoundation") - target_link_libraries(${PROJECT_NAME} "-framework Security") - target_link_libraries(${PROJECT_NAME} ${LIBRARIES_SEARCH_PATHS}) - set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "-W1, -F/Library/Frameworks") -else() - target_link_libraries(${PROJECT_NAME} PRIVATE ${LIBRARIES_SEARCH_PATHS}) - target_link_libraries(${PROJECT_NAME} PRIVATE cpprestsdk::cpprest) - target_link_libraries(${PROJECT_NAME} PRIVATE mongo::mongocxx_shared) - target_link_libraries(${PROJECT_NAME} PRIVATE mongo::bsoncxx_shared) -endif() - -#sanity check -get_target_property(LIBBSONCXX_DEFINITIONS mongo::bsoncxx_shared INTERFACE_COMPILE_DEFINITIONS) -list(FIND LIBBSONCXX_DEFINITIONS "BSONCXX_STATIC" LIST_IDX) -if (${LIST_IDX} GREATER -1) - message(FATAL_ERROR "Expected BSONCXX_STATIC to not be defined") +cmake_minimum_required(VERSION 3.0) + +project(micro-service) + +set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES /usr/local/ ${CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES}) + +# Configure required libraries ... +find_package(Boost REQUIRED COMPONENTS system thread log program_options chrono) +find_package(Threads REQUIRED) +find_package(OpenSSL 1.0.1 REQUIRED) +find_package(cpprestsdk REQUIRED) +find_package(mongocxx REQUIRED) +find_package(bsoncxx REQUIRED) + +set(OPENSSL_VERSION "1.0.1") + +# Configure compiler options ... +if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set(CMAKE_CXX_FLAGS "-arch x86_64 -std=c++20 -stdlib=libc++ -DBOOST_LOG_DYN_LINK -Wno-deprecated-declarations") +elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++17 -DBOOST_LOG_DYN_LINK") +endif() + +# source files ... +add_executable(${PROJECT_NAME} ./source/main.cpp + ./source/microsvc_controller.cpp + ./source/database_manager.cpp + ./source/foundation/network_utils.cpp + ./source/foundation/basic_controller.cpp) + +# headers search paths ... +set(MICROSERVICE_INCLUDE_DIR "./source/foundation/include") +set(HEADER_SEARCH_PATHS ${MICROSERVICE_INCLUDE_DIR} ${Boost_INCLUDE_DIR} ${OpenSSL_INCLUDE_DIR}) +set(LIBRARIES_SEARCH_PATHS ${OpenSSL_LIBRARIES} ${Boost_LIBRARIES}) + +include_directories(${HEADER_SEARCH_PATHS}) + +target_link_libraries(${PROJECT_NAME} PRIVATE ${LIBRARIES_SEARCH_PATHS}) +target_link_libraries(${PROJECT_NAME} PRIVATE cpprestsdk::cpprest) +target_link_libraries(${PROJECT_NAME} PRIVATE mongo::mongocxx_shared) +target_link_libraries(${PROJECT_NAME} PRIVATE mongo::bsoncxx_shared) + +#sanity check +get_target_property(LIBBSONCXX_DEFINITIONS mongo::bsoncxx_shared INTERFACE_COMPILE_DEFINITIONS) +list(FIND LIBBSONCXX_DEFINITIONS "BSONCXX_STATIC" LIST_IDX) +if (${LIST_IDX} GREATER -1) + message(FATAL_ERROR "Expected BSONCXX_STATIC to not be defined") endif() \ No newline at end of file diff --git a/LICENSE b/LICENSE index 23eefa3242f99940b9111887c3cd7889e1dfad48..24339485880755387e0b3e8c864c03986c50aff9 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,21 @@ -MIT License - -Copyright (c) 2016 Ivan Mejia - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +MIT License + +Copyright (c) 2016 Ivan Mejia + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 800d5f15c0500dc0406b1f1a9a524bee624d91e9..639ae03ef225d84aeb148bd0ecc881883f155150 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ -# micro-service -D4 Web Server - +# micro-service +D4 Web Server + diff --git a/json_requests/Cluster0.txt b/json_requests/Cluster0.txt index 619348cdb8c9d8248856127eaec0b03331f8674c..f16007375ace0e1897f3c67edca789283c328596 100644 --- a/json_requests/Cluster0.txt +++ b/json_requests/Cluster0.txt @@ -1,3 +1,3 @@ - -Password: 65kCnKukCMpJjwX0 + +Password: 65kCnKukCMpJjwX0 username: dev-access \ No newline at end of file diff --git a/json_requests/avatarStats.json b/json_requests/avatarStats.json index 8c1f5b66daa589e04b4bbcaf930e752046d86db8..97a7c53aff3aec24dd1e13dc92751180c9bd3da1 100644 --- a/json_requests/avatarStats.json +++ b/json_requests/avatarStats.json @@ -1,3 +1,3 @@ -{ - "team-id":123 +{ + "team-id":123 } \ No newline at end of file diff --git a/json_requests/avatarUpdate.json b/json_requests/avatarUpdate.json index d4b3f78600f829db0c9a54d7e2a40c9cb0ebe02d..ae1d2dfc5a90e8690aadde604732b6dfa765f737 100644 --- a/json_requests/avatarUpdate.json +++ b/json_requests/avatarUpdate.json @@ -1,4 +1,4 @@ -{ - "team-id":123, - "health":80 +{ + "team-id":123, + "health":80 } \ No newline at end of file diff --git a/json_requests/copyfile.txt b/json_requests/copyfile.txt new file mode 100644 index 0000000000000000000000000000000000000000..e71cd5df0925406287f186857072a6495c9b698d --- /dev/null +++ b/json_requests/copyfile.txt @@ -0,0 +1,6 @@ + +PC to AWS +scp -r C:\users\jonah\.ssh\AWS\D4\D4-webserver-keypair.pem C:\coursework\D4\d4-server ubuntu@ec2-18-135-114-10.eu-west-2.compute.amazonaws.com:~/D4 + +AWS to PC +scp -i C:\AWS\POTWKeyPair.pem ec2-user@ec2-35-176-250-197.eu-west-2.compute.amazonaws.com:/home/ec2-user/* C:\potw-server\hold diff --git a/json_requests/createCompetition.json b/json_requests/createCompetition.json index 4bfc8e0ce57bd614eb980651b6109fdf95eb9c51..790838720eeb4404bcf95ead8fd0a37c6cc4851b 100644 --- a/json_requests/createCompetition.json +++ b/json_requests/createCompetition.json @@ -1,4 +1,4 @@ -{ - "user-id":567, - "team-id":123 +{ + "user-id":567, + "team-id":123 } \ No newline at end of file diff --git a/json_requests/createTeam.json b/json_requests/createTeam.json index ffd67d9f212630f8c56c2c1d2f51f01ef3e86849..1b93ccf608494af12d464114a102afca39cdb684 100644 --- a/json_requests/createTeam.json +++ b/json_requests/createTeam.json @@ -1,4 +1,4 @@ -{ - "user-id":567, - "avatar-name":"snoopy" -} +{ + "user-id":567, + "avatar-name":"snoopy" +} diff --git a/json_requests/curl_commands.txt b/json_requests/curl_commands.txt index 85d3de2e676fdfb7e65e785089cb5ff8457deb00..2c8aae49103cf6d05f01f6aefb2dfd3458a63622 100644 --- a/json_requests/curl_commands.txt +++ b/json_requests/curl_commands.txt @@ -1,14 +1,29 @@ - -info -- curl -X GET -H "Content-Type:application/json" http://127.0.1.1:6502/service/info - -create team -- curl -X POST -H "Content-Type:application/json" -d @createTeam.json http://127.0.1.1:6502/team/create - -join team -- curl -X POST -H "Content-Type:application/json" -d @joinTeam.json http://127.0.1.1:6502/team/join - -create competition -- curl -X POST -H "Content-Type:application/json" -d @createCompetition.json http://127.0.1.1:6502/competition/create - -join competition -- curl -X POST -H "Content-Type:application/json" -d @joinCompetition.json http://127.0.1.1:6502/team/join - -avatar stats -- curl -X GET -H "Content-Type:application/json" -d @avatarStats.json http://127.0.1.1:6502/avatar/stats - -avatar update-- curl -X POST -H "Content-Type:application/json" -d @avatarUpdate.json http://127.0.1.1:6502/avatar/update + + +create team -- curl -X POST -H "Content-Type:application/json" -d @createTeam.json http://127.0.1.1:6502/team/create + +join team -- curl -X POST -H "Content-Type:application/json" -d @joinTeam.json http://127.0.1.1:6502/team/join + +create competition -- curl -X POST -H "Content-Type:application/json" -d @createCompetition.json http://127.0.1.1:6502/competition/create + +join competition -- curl -X POST -H "Content-Type:application/json" -d @joinCompetition.json http://127.0.1.1:6502/team/join + +avatar stats -- curl -X GET -H "Content-Type:application/json" -d @avatarStats.json http://127.0.1.1:6502/avatar/stats + +avatar update-- curl -X POST -H "Content-Type:application/json" -d @avatarUpdate.json http://127.0.1.1:6502/avatar/update + +--------------------------------------------------- + +create team -- curl -X POST -H "Content-Type:application/json" -d @createTeam.json http://ec2-18-135-114-10.eu-west-2.compute.amazonaws.com:6502/team/create + +create team -- curl -X POST -H "Content-Type:application/json" -d @createTeam.json http://ec2-18-135-114-10.eu-west-2.compute.amazonaws.com:6502/team/create + +join team -- curl -X POST -H "Content-Type:application/json" -d @joinTeam.json http://ec2-18-135-114-10.eu-west-2.compute.amazonaws.com/team/join + +create competition -- curl -X POST -H "Content-Type:application/json" -d @createCompetition.json http://ec2-18-135-114-10.eu-west-2.compute.amazonaws.com/competition/create + +join competition -- curl -X POST -H "Content-Type:application/json" -d @joinCompetition.json http://ec2-18-135-114-10.eu-west-2.compute.amazonaws.com/team/join + +avatar stats -- curl -X GET -H "Content-Type:application/json" -d @avatarStats.json http://ec2-18-135-114-10.eu-west-2.compute.amazonaws.com/avatar/stats + +avatar update-- curl -X POST -H "Content-Type:application/json" -d @avatarUpdate.json http://ec2-18-135-114-10.eu-west-2.compute.amazonaws.com/avatar/update \ No newline at end of file diff --git a/json_requests/joinCompetition.json b/json_requests/joinCompetition.json index dffc0c8766c66f825e4c80eb8d4e3a26554a4733..deabe8fd7d80b6a0ce65e7f647595dc14113325f 100644 --- a/json_requests/joinCompetition.json +++ b/json_requests/joinCompetition.json @@ -1,5 +1,5 @@ -{ - "team-id":789, - "competition-id":789, - "user-id":123 +{ + "team-id":789, + "competition-id":789, + "user-id":123 } \ No newline at end of file diff --git a/json_requests/joinTeam.json b/json_requests/joinTeam.json index d01c98afa1ea31d8c2424f3a4b4f532e2ebb9f19..4f982bcd8b6efba153b18dd4455fdcbbd5fad833 100644 --- a/json_requests/joinTeam.json +++ b/json_requests/joinTeam.json @@ -1,4 +1,4 @@ -{ - "team-id" : 123, - "user-id" : 456 +{ + "team-id" : 123, + "user-id" : 456 } \ No newline at end of file diff --git a/libs/build_dependencies.sh b/libs/build_dependencies.sh index 9878d6643f25960fcc433a92bfcab1c13b089df3..e985e343625008c3b76a3b96d989734eb8e88693 100644 --- a/libs/build_dependencies.sh +++ b/libs/build_dependencies.sh @@ -1,29 +1,29 @@ -#!/bin/bash - -RESTSDK_VERSION="v2.10.6" -DEFAULT_LIB_DIRECTORY_PATH="." - -libDir=${1:-$DEFAULT_LIB_DIRECTORY_PATH} - - -install_cpprestsdk(){ - - restsdkDir="$libDir/cpprestsdk" - restsdkBuildDir="$restsdkDir/build.release" - - if [ -d "$restsdkDir" ]; then - rm -rf "$restsdkDir" - fi - - git clone https://github.com/Microsoft/cpprestsdk.git "$restsdkDir" - (cd $restsdkDir && git submodule update --init && git checkout tags/$RESTSDK_VERSION -b $RESTSDK_VERSION) - mkdir "$restsdkBuildDir" - if [[ "$OSTYPE" == "linux-gnu" ]]; then - export CXX=g++-9.3.0 - fi - (cd "$restsdkBuildDir" && cmake ../Release -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DBUILD_TESTS=OFF -DBUILD_SAMPLES=OFF) - (cd "$restsdkBuildDir" && make) -} - -mkdir -p "$libDir" -install_cpprestsdk +#!/bin/bash + +RESTSDK_VERSION="v2.10.6" +DEFAULT_LIB_DIRECTORY_PATH="." + +libDir=${1:-$DEFAULT_LIB_DIRECTORY_PATH} + + +install_cpprestsdk(){ + + restsdkDir="$libDir/cpprestsdk" + restsdkBuildDir="$restsdkDir/build.release" + + if [ -d "$restsdkDir" ]; then + rm -rf "$restsdkDir" + fi + + git clone https://github.com/Microsoft/cpprestsdk.git "$restsdkDir" + (cd $restsdkDir && git submodule update --init && git checkout tags/$RESTSDK_VERSION -b $RESTSDK_VERSION) + mkdir "$restsdkBuildDir" + if [[ "$OSTYPE" == "linux-gnu" ]]; then + export CXX=g++-9.3.0 + fi + (cd "$restsdkBuildDir" && cmake ../Release -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DBUILD_TESTS=OFF -DBUILD_SAMPLES=OFF) + (cd "$restsdkBuildDir" && make) +} + +mkdir -p "$libDir" +install_cpprestsdk diff --git a/source/database_manager.cpp b/source/database_manager.cpp index b394783affc6f26cb918cea7df2f957676eb74ed..6d78583d2a4d813b10500aafc2ec183b3ce68413 100644 --- a/source/database_manager.cpp +++ b/source/database_manager.cpp @@ -1,258 +1,258 @@ -#include <database_manager.hpp> -#include <utility> -#include <iostream> -#include <iterator> -#include <map> -#include <algorithm> - -using namespace bsoncxx; -using bsoncxx::builder::basic::kvp; - -void -databaseManager::configure_mongo(mongocxx::uri uri) { - class noop_logger : public mongocxx::logger { - public: - virtual void operator()(mongocxx::log_level, - bsoncxx::stdx::string_view, - bsoncxx::stdx::string_view) noexcept {} - }; - auto instance = bsoncxx::stdx::make_unique<mongocxx::instance>(bsoncxx::stdx::make_unique<noop_logger>()); - mongo_access::instance().configure(std::move(instance), - bsoncxx::stdx::make_unique<mongocxx::pool>(std::move(uri))); -} - -json::value -databaseManager::competition::create(int team_id, int user_id) { - auto dbclient = mongo_access::instance().try_get_connection(); - - auto session = dbclient->start_session(); - auto coll = (*dbclient)["competition"]["active"]; - - if(!databaseManager::team::isHost(team_id,user_id)) - throw databaseManagerException("Only the host of a team is allowed to create a competition"); - - auto competition - = builder::stream::document{} - << "competition-id" << 789 - << "teams" - << builder::stream::open_array - << team_id - << builder::stream::close_array - << builder::stream::finalize; - - auto insertResult = coll.insert_one(competition.view()); - - if (insertResult.value().result().inserted_count() == 0) - throw databaseManagerException("Unsuccessful competition creation"); - else - return json::value::parse(to_json(competition.view())); -} - -json::value -databaseManager::competition::join(int competition_id, int team_id, int user_id) { - auto dbclient = mongo_access::instance().try_get_connection(); - - auto session = dbclient->start_session(); - auto coll = (*dbclient)["competition"]["active"]; - - if(!databaseManager::team::is Host(team_id,user_id)) - throw databaseManagerException("Only the host of a team is allowed to join a competition"); - - auto teamExists = coll.find_one(builder::stream::document{} - << "competition-id" << competition_id - << "teams" << team_id - << builder::stream::finalize); - if(teamExists) - throw databaseManagerException("Team already exists in this competition! / Competition does not exist"); - - auto queryResult - = coll.find_one_and_update( - builder::stream::document{} - << "competition-id" << competition_id - << builder::stream::finalize, - builder::stream::document{} - << "$push" - << builder::stream::open_document - << "teams" << team_id - << builder::stream::close_document - << builder::stream::finalize); - - if(!queryResult) - throw databaseManagerException("Could not find the competition you were looking for (wrong ID)"); - else - return getTeamIDs(competition_id); -} - -json::value -databaseManager::competition::getTeamIDs(int competition_id) { - auto dbclient = mongo_access::instance().try_get_connection(); - - auto session = dbclient->start_session(); - auto coll = (*dbclient)["competition"]["active"]; - - auto queryResult - = coll.find_one( - builder::stream::document{} - << "competition-id" << competition_id - << builder::stream::finalize); - - if(!queryResult) - throw databaseManagerException("Error getting team IDs, supplied competition ID may be incorrect"); - else { - auto competition = queryResult.value().view(); - auto ids = to_json(competition["teams"].get_array().value); - return json::value::parse(ids); - } -} - -bool -databaseManager::team::isHost(int team_id, int user_id) { - auto dbclient = mongo_access::instance().try_get_connection(); - - auto session = dbclient->start_session(); - auto coll = (*dbclient)["teams"]["teams"]; - - auto team = coll.find_one(builder::stream::document{} - << "team-id" << team_id - << builder::stream::finalize); - - if(!team) - throw databaseManagerException("There does not exist a team with the specified ID"); - else { - auto teamView = team.value().view(); - int host_id = teamView["host-id"].get_int32().value; - return user_id == host_id; - } - -} - -json::value -databaseManager::team::create(int user_host_id, std::string avatar_name) { - auto dbclient = mongo_access::instance().try_get_connection(); - - auto session = dbclient->start_session(); - auto coll = (*dbclient)["teams"]["teams"]; - - auto team - = builder::stream::document{} - << "team-id" << 123 - << "host-id" << user_host_id - << "avatar" - << builder::stream::open_document - << "avatar-name" << avatar_name - << "health" << 100 - << builder::stream::close_document - << "users" - << builder::stream::open_array - << user_host_id - << builder::stream::close_array - << builder::stream::finalize; - - auto insertResult = coll.insert_one(team.view()); - - if (insertResult.value().result().inserted_count() == 0) - throw databaseManagerException("Unsuccessful team creation"); - else { - return json::value::parse(to_json(team.view())); - } -} - -json::value -databaseManager::team::join(int team_id, int user_id) { - auto dbclient = mongo_access::instance().try_get_connection(); - - auto session = dbclient->start_session(); - auto coll = (*dbclient)["teams"]["teams"]; - - auto userExists = coll.find_one(builder::stream::document{} - << "team-id" << team_id - << "users" << user_id - << builder::stream::finalize); - if(userExists) - throw databaseManagerException("User already exists in this competition! / Competition does not exist"); - - auto queryResult - = coll.find_one_and_update( - builder::stream::document{} - << "team-id" << team_id - << builder::stream::finalize, - builder::stream::document{} - << "$push" - << builder::stream::open_document - << "users" << user_id - << builder::stream::close_document - << builder::stream::finalize); - - if(!queryResult) - throw databaseManagerException("Could not find the team you were looking for (wrong ID)"); - else - return getUserIDs(team_id); -} - -json::value -databaseManager::team::getUserIDs(int team_id) { - auto dbclient = mongo_access::instance().try_get_connection(); - - auto session = dbclient->start_session(); - auto coll = (*dbclient)["teams"]["teams"]; - - auto queryResult - = coll.find_one(builder::stream::document{} - << "team-id" << team_id - << builder::stream::finalize); - - if(!queryResult) - throw databaseManagerException("Error getting user IDs, team id may be incorrect"); - else { - auto team = queryResult.value().view(); - auto ids = to_json(team["users"].get_array().value); - return json::value::parse(ids); - } -} - -json::value -databaseManager::avatar::update(int team_id, int health) { - auto dbclient = mongo_access::instance().try_get_connection(); - - auto session = dbclient->start_session(); - auto coll = (*dbclient)["teams"]["teams"]; - - auto queryResult - = coll.find_one_and_update( - builder::stream::document{} - << "team-id" << team_id - << builder::stream::finalize, - builder::stream::document{} - << "$set" - << builder::stream::open_document - << "avatar.health" << health - << builder::stream::close_document - << builder::stream::finalize); - - if(!queryResult) - throw databaseManagerException("Could not update your avatar, wrong team ID"); - else - return getStats(team_id); -} - -json::value -databaseManager::avatar::getStats(int team_id) { - auto dbclient = mongo_access::instance().try_get_connection(); - - auto session = dbclient->start_session(); - auto coll = (*dbclient)["teams"]["teams"]; - - auto queryResult - = coll.find_one(builder::stream::document{} - << "team-id" << team_id - << builder::stream::finalize); - - if(!queryResult) - throw databaseManagerException("Could not find the team with the specified ID"); - else { - auto team = queryResult.value().view(); - auto teamJson = json::value::parse(to_json(team)); - return teamJson["avatar"]; - } - -} +#include <database_manager.hpp> +#include <utility> +#include <iostream> +#include <iterator> +#include <map> +#include <algorithm> + +using namespace bsoncxx; +using bsoncxx::builder::basic::kvp; + +void +databaseManager::configure_mongo(mongocxx::uri uri) { + class noop_logger : public mongocxx::logger { + public: + virtual void operator()(mongocxx::log_level, + bsoncxx::stdx::string_view, + bsoncxx::stdx::string_view) noexcept {} + }; + auto instance = bsoncxx::stdx::make_unique<mongocxx::instance>(bsoncxx::stdx::make_unique<noop_logger>()); + mongo_access::instance().configure(std::move(instance), + bsoncxx::stdx::make_unique<mongocxx::pool>(std::move(uri))); +} + +json::value +databaseManager::competition::create(int team_id, int user_id) { + auto dbclient = mongo_access::instance().try_get_connection(); + + auto session = dbclient->start_session(); + auto coll = (*dbclient)["competition"]["active"]; + + if(!databaseManager::team::isHost(team_id,user_id)) + throw databaseManagerException("Only the host of a team is allowed to create a competition"); + + auto competition + = builder::stream::document{} + << "competition-id" << 789 + << "teams" + << builder::stream::open_array + << team_id + << builder::stream::close_array + << builder::stream::finalize; + + auto insertResult = coll.insert_one(competition.view()); + + if (insertResult.value().result().inserted_count() == 0) + throw databaseManagerException("Unsuccessful competition creation"); + else + return json::value::parse(to_json(competition.view())); +} + +json::value +databaseManager::competition::join(int competition_id, int team_id, int user_id) { + auto dbclient = mongo_access::instance().try_get_connection(); + + auto session = dbclient->start_session(); + auto coll = (*dbclient)["competition"]["active"]; + + if(!databaseManager::team::isHost(team_id,user_id)) + throw databaseManagerException("Only the host of a team is allowed to join a competition"); + + auto teamExists = coll.find_one(builder::stream::document{} + << "competition-id" << competition_id + << "teams" << team_id + << builder::stream::finalize); + if(teamExists) + throw databaseManagerException("Team already exists in this competition! / Competition does not exist"); + + auto queryResult + = coll.find_one_and_update( + builder::stream::document{} + << "competition-id" << competition_id + << builder::stream::finalize, + builder::stream::document{} + << "$push" + << builder::stream::open_document + << "teams" << team_id + << builder::stream::close_document + << builder::stream::finalize); + + if(!queryResult) + throw databaseManagerException("Could not find the competition you were looking for (wrong ID)"); + else + return getTeamIDs(competition_id); +} + +json::value +databaseManager::competition::getTeamIDs(int competition_id) { + auto dbclient = mongo_access::instance().try_get_connection(); + + auto session = dbclient->start_session(); + auto coll = (*dbclient)["competition"]["active"]; + + auto queryResult + = coll.find_one( + builder::stream::document{} + << "competition-id" << competition_id + << builder::stream::finalize); + + if(!queryResult) + throw databaseManagerException("Error getting team IDs, supplied competition ID may be incorrect"); + else { + auto competition = queryResult.value().view(); + auto ids = to_json(competition["teams"].get_array().value); + return json::value::parse(ids); + } +} + +bool +databaseManager::team::isHost(int team_id, int user_id) { + auto dbclient = mongo_access::instance().try_get_connection(); + + auto session = dbclient->start_session(); + auto coll = (*dbclient)["teams"]["teams"]; + + auto team = coll.find_one(builder::stream::document{} + << "team-id" << team_id + << builder::stream::finalize); + + if(!team) + throw databaseManagerException("There does not exist a team with the specified ID"); + else { + auto teamView = team.value().view(); + int host_id = teamView["host-id"].get_int32().value; + return user_id == host_id; + } + +} + +json::value +databaseManager::team::create(int user_host_id, std::string avatar_name) { + auto dbclient = mongo_access::instance().try_get_connection(); + + auto session = dbclient->start_session(); + auto coll = (*dbclient)["teams"]["teams"]; + + auto team + = builder::stream::document{} + << "team-id" << 123 + << "host-id" << user_host_id + << "avatar" + << builder::stream::open_document + << "avatar-name" << avatar_name + << "health" << 100 + << builder::stream::close_document + << "users" + << builder::stream::open_array + << user_host_id + << builder::stream::close_array + << builder::stream::finalize; + + auto insertResult = coll.insert_one(team.view()); + + if (insertResult.value().result().inserted_count() == 0) + throw databaseManagerException("Unsuccessful team creation"); + else { + return json::value::parse(to_json(team.view())); + } +} + +json::value +databaseManager::team::join(int team_id, int user_id) { + auto dbclient = mongo_access::instance().try_get_connection(); + + auto session = dbclient->start_session(); + auto coll = (*dbclient)["teams"]["teams"]; + + auto userExists = coll.find_one(builder::stream::document{} + << "team-id" << team_id + << "users" << user_id + << builder::stream::finalize); + if(userExists) + throw databaseManagerException("User already exists in this competition! / Competition does not exist"); + + auto queryResult + = coll.find_one_and_update( + builder::stream::document{} + << "team-id" << team_id + << builder::stream::finalize, + builder::stream::document{} + << "$push" + << builder::stream::open_document + << "users" << user_id + << builder::stream::close_document + << builder::stream::finalize); + + if(!queryResult) + throw databaseManagerException("Could not find the team you were looking for (wrong ID)"); + else + return getUserIDs(team_id); +} + +json::value +databaseManager::team::getUserIDs(int team_id) { + auto dbclient = mongo_access::instance().try_get_connection(); + + auto session = dbclient->start_session(); + auto coll = (*dbclient)["teams"]["teams"]; + + auto queryResult + = coll.find_one(builder::stream::document{} + << "team-id" << team_id + << builder::stream::finalize); + + if(!queryResult) + throw databaseManagerException("Error getting user IDs, team id may be incorrect"); + else { + auto team = queryResult.value().view(); + auto ids = to_json(team["users"].get_array().value); + return json::value::parse(ids); + } +} + +json::value +databaseManager::avatar::update(int team_id, int health) { + auto dbclient = mongo_access::instance().try_get_connection(); + + auto session = dbclient->start_session(); + auto coll = (*dbclient)["teams"]["teams"]; + + auto queryResult + = coll.find_one_and_update( + builder::stream::document{} + << "team-id" << team_id + << builder::stream::finalize, + builder::stream::document{} + << "$set" + << builder::stream::open_document + << "avatar.health" << health + << builder::stream::close_document + << builder::stream::finalize); + + if(!queryResult) + throw databaseManagerException("Could not update your avatar, wrong team ID"); + else + return getStats(team_id); +} + +json::value +databaseManager::avatar::getStats(int team_id) { + auto dbclient = mongo_access::instance().try_get_connection(); + + auto session = dbclient->start_session(); + auto coll = (*dbclient)["teams"]["teams"]; + + auto queryResult + = coll.find_one(builder::stream::document{} + << "team-id" << team_id + << builder::stream::finalize); + + if(!queryResult) + throw databaseManagerException("Could not find the team with the specified ID"); + else { + auto team = queryResult.value().view(); + auto teamJson = json::value::parse(to_json(team)); + return teamJson["avatar"]; + } + +} diff --git a/source/foundation/basic_controller.cpp b/source/foundation/basic_controller.cpp index 3acad3c8a294c3cddfe3f01cec8441b3de5fec71..cc93da0ef5e1576146be25d818cd5f58fd0b11ae 100644 --- a/source/foundation/basic_controller.cpp +++ b/source/foundation/basic_controller.cpp @@ -1,41 +1,44 @@ -// Adapted from code provided by Ivan Mejia on 12/24/16 liscenced under the MIT License - -#include "basic_controller.hpp" -#include "network_utils.hpp" - -namespace cfx { - void BasicController::setEndpoint(const std::string & value) { - uri endpointURI(value); - uri_builder endpointBuilder; - - endpointBuilder.set_scheme(endpointURI.scheme()); - if (endpointURI.host() == "host_auto_ip4") { - endpointBuilder.set_host(NetworkUtils::hostIP4()); - } - else if (endpointURI.host() == "host_auto_ip6") { - endpointBuilder.set_host(NetworkUtils::hostIP6()); - } - endpointBuilder.set_port(endpointURI.port()); - endpointBuilder.set_path(endpointURI.path()); - - listener = http_listener(endpointBuilder.to_uri()); - } - - std::string BasicController::endpoint() const { - return listener.uri().to_string(); - } - - pplx::task<void> BasicController::accept() { - initRestOpHandlers(); - return listener.open(); - } - - pplx::task<void> BasicController::shutdown() { - return listener.close(); - } - - std::vector<utility::string_t> BasicController::requestPath(const http_request & message) { - auto relativePath = uri::decode(message.relative_uri().path()); - return uri::split_path(relativePath); - } +// Adapted from code provided by Ivan Mejia on 12/24/16 liscenced under the MIT License + +#include "basic_controller.hpp" +#include "network_utils.hpp" + +namespace cfx { + void BasicController::setEndpoint(const std::string & value) { + uri endpointURI(value); + uri_builder endpointBuilder; + + endpointBuilder.set_scheme(endpointURI.scheme()); + if (endpointURI.host() == "host_auto_ip4") { + endpointBuilder.set_host(NetworkUtils::hostIP4()); + } + else if (endpointURI.host() == "host_auto_ip6") { + endpointBuilder.set_host(NetworkUtils::hostIP6()); + } + else { + endpointBuilder.set_host(endpointURI.host()); + } + endpointBuilder.set_port(endpointURI.port()); + endpointBuilder.set_path(endpointURI.path()); + + listener = http_listener(endpointBuilder.to_uri()); + } + + std::string BasicController::endpoint() const { + return listener.uri().to_string(); + } + + pplx::task<void> BasicController::accept() { + initRestOpHandlers(); + return listener.open(); + } + + pplx::task<void> BasicController::shutdown() { + return listener.close(); + } + + std::vector<utility::string_t> BasicController::requestPath(const http_request & message) { + auto relativePath = uri::decode(message.relative_uri().path()); + return uri::split_path(relativePath); + } } \ No newline at end of file diff --git a/source/foundation/include/basic_controller.hpp b/source/foundation/include/basic_controller.hpp index 51a16e65251e26d3c8a460f56cfa886df08d7eb6..6d94ad261f2c0595b29860e7497e37550b731e54 100644 --- a/source/foundation/include/basic_controller.hpp +++ b/source/foundation/include/basic_controller.hpp @@ -1,34 +1,34 @@ -// Adapted from code provided by Ivan Mejia on 12/24/16 liscenced under the MIT License - -#pragma once - -#include <string> -#include <cpprest/http_listener.h> -#include <pplx/pplxtasks.h> -#include <controller.hpp> -#include <std_micro_service.hpp> -#include <functional> - -using namespace web; -using namespace http::experimental::listener; - -namespace cfx { - class BasicController { - public: - BasicController() = default; - ~BasicController() = default; - - void setEndpoint(const std::string & value); - std::string endpoint() const; - pplx::task<void> accept(); - pplx::task<void> shutdown(); - - virtual void initRestOpHandlers() { - /* had to be implemented by the child class */ - } - - std::vector<utility::string_t> requestPath(const http_request & message); - protected: - http_listener listener; // main micro service network endpoint - }; +// Adapted from code provided by Ivan Mejia on 12/24/16 liscenced under the MIT License + +#pragma once + +#include <string> +#include <cpprest/http_listener.h> +#include <pplx/pplxtasks.h> +#include <controller.hpp> +#include <std_micro_service.hpp> +#include <functional> + +using namespace web; +using namespace http::experimental::listener; + +namespace cfx { + class BasicController { + public: + BasicController() = default; + ~BasicController() = default; + + void setEndpoint(const std::string & value); + std::string endpoint() const; + pplx::task<void> accept(); + pplx::task<void> shutdown(); + + virtual void initRestOpHandlers() { + /* had to be implemented by the child class */ + } + + std::vector<utility::string_t> requestPath(const http_request & message); + protected: + http_listener listener; // main micro service network endpoint + }; } \ No newline at end of file diff --git a/source/foundation/include/controller.hpp b/source/foundation/include/controller.hpp index 5cccfc73018b03051f89b952ad7a7ce85b495533..e72f832c563769484c23c2a9b00b8bc65385b5b5 100644 --- a/source/foundation/include/controller.hpp +++ b/source/foundation/include/controller.hpp @@ -1,24 +1,24 @@ -// Adapted from code provided by Ivan Mejia on 12/24/16 liscenced under the MIT License - -#pragma once - -#include <cpprest/http_msg.h> - -using namespace web; -using namespace http; - -namespace cfx { - - /*! - * Dispatcher class represents the basic interface for a - * web serivce handler. - */ - class Controller { - public: - virtual void handleGet(http_request message) = 0; - virtual void handlePut(http_request message) = 0; - virtual void handlePost(http_request message) = 0; - virtual void handleDelete(http_request message) = 0; - virtual void handleConnect(http_request message) = 0; - }; +// Adapted from code provided by Ivan Mejia on 12/24/16 liscenced under the MIT License + +#pragma once + +#include <cpprest/http_msg.h> + +using namespace web; +using namespace http; + +namespace cfx { + + /*! + * Dispatcher class represents the basic interface for a + * web serivce handler. + */ + class Controller { + public: + virtual void handleGet(http_request message) = 0; + virtual void handlePut(http_request message) = 0; + virtual void handlePost(http_request message) = 0; + virtual void handleDelete(http_request message) = 0; + virtual void handleConnect(http_request message) = 0; + }; } \ No newline at end of file diff --git a/source/foundation/include/database_manager.hpp b/source/foundation/include/database_manager.hpp index 4a602803a8e1cc50e61870ec1246ec30fe8dd6b1..e023d00ab14d1a1b09499ff66cd7b02e407585df 100644 --- a/source/foundation/include/database_manager.hpp +++ b/source/foundation/include/database_manager.hpp @@ -1,81 +1,81 @@ -#pragma once - -#include <std_micro_service.hpp> -#include <cpprest/http_listener.h> -#include <memory> -#include <string> -#include <optional> -#include <map> - -using namespace bsoncxx; -using namespace bsoncxx::document; -using namespace web; - -namespace databaseManager -{ - void configure_mongo(mongocxx::uri uri); - - class databaseManagerException : public std::exception { - std::string _message; - public: - databaseManagerException(const std::string & message) : - _message(message) {} - const char * what() const throw() { - return _message.c_str(); - } - }; - - class mongo_access { - public: - static mongo_access& instance() { //this function is called alot - static mongo_access instance; - return instance; - } - - void configure(std::unique_ptr<mongocxx::instance> instance, - std::unique_ptr<mongocxx::pool> pool) { - _instance = std::move(instance); - _pool = std::move(pool); - } - - using connection = mongocxx::pool::entry; - - //an entry is like an std::unique_ptr to a mongocxx::client - //dereference via * to get the underlying client or use -> operator - connection get_connection() { - return _pool->acquire(); - } - - connection try_get_connection() { - auto entry = _pool->try_acquire(); - if(!entry) - throw databaseManagerException("Could not acquire an entry to the DB"); - else - return std::move(entry.value()); - } - - private: - mongo_access() = default; - std::unique_ptr<mongocxx::instance> _instance = nullptr; - std::unique_ptr<mongocxx::pool> _pool = nullptr; - }; - - //API helper Namespaces - namespace competition { - json::value create(int team_id, int user_id); - json::value join(int competition_id, int team_id, int user_id); - json::value getTeamIDs(int competition_id); - } - namespace team { - json::value create(int user_host_id, std::string avatar_name); - json::value join(int team_id, int user_id); - json::value getUserIDs(int team_id); - bool isHost(int team_id, int user_id); - }; - - namespace avatar { - json::value update(int team_id, int health); - json::value getStats(int team_id); - }; -}; +#pragma once + +#include <std_micro_service.hpp> +#include <cpprest/http_listener.h> +#include <memory> +#include <string> +#include <optional> +#include <map> + +using namespace bsoncxx; +using namespace bsoncxx::document; +using namespace web; + +namespace databaseManager +{ + void configure_mongo(mongocxx::uri uri); + + class databaseManagerException : public std::exception { + std::string _message; + public: + databaseManagerException(const std::string & message) : + _message(message) {} + const char * what() const throw() { + return _message.c_str(); + } + }; + + class mongo_access { + public: + static mongo_access& instance() { //this function is called alot + static mongo_access instance; + return instance; + } + + void configure(std::unique_ptr<mongocxx::instance> instance, + std::unique_ptr<mongocxx::pool> pool) { + _instance = std::move(instance); + _pool = std::move(pool); + } + + using connection = mongocxx::pool::entry; + + //an entry is like an std::unique_ptr to a mongocxx::client + //dereference via * to get the underlying client or use -> operator + connection get_connection() { + return _pool->acquire(); + } + + connection try_get_connection() { + auto entry = _pool->try_acquire(); + if(!entry) + throw databaseManagerException("Could not acquire an entry to the DB"); + else + return std::move(entry.value()); + } + + private: + mongo_access() = default; + std::unique_ptr<mongocxx::instance> _instance = nullptr; + std::unique_ptr<mongocxx::pool> _pool = nullptr; + }; + + //API helper Namespaces + namespace competition { + json::value create(int team_id, int user_id); + json::value join(int competition_id, int team_id, int user_id); + json::value getTeamIDs(int competition_id); + } + namespace team { + json::value create(int user_host_id, std::string avatar_name); + json::value join(int team_id, int user_id); + json::value getUserIDs(int team_id); + bool isHost(int team_id, int user_id); + }; + + namespace avatar { + json::value update(int team_id, int health); + json::value getStats(int team_id); + }; +}; \ No newline at end of file diff --git a/source/foundation/include/microsvc_controller.hpp b/source/foundation/include/microsvc_controller.hpp index a13156da8ad051ff00dcb3b9909698baf2050a82..88fab31ad80f34196f13cddcf3807b6c6af54ea6 100644 --- a/source/foundation/include/microsvc_controller.hpp +++ b/source/foundation/include/microsvc_controller.hpp @@ -1,25 +1,25 @@ -// Adapted from code provided by Ivan Mejia on 12/24/16 liscenced under the MIT License - -#pragma once - -#include <std_micro_service.hpp> -#include <basic_controller.hpp> -#include <database_manager.hpp> - -using namespace cfx; - -class MicroserviceController : public BasicController, Controller { -public: - MicroserviceController() : BasicController() {} - ~MicroserviceController() {} - void handleGet(http_request message) override; - void handlePut(http_request message) override; - void handlePost(http_request message) override; - void handleDelete(http_request message) override; - void handleConnect(http_request message) override; - void initRestOpHandlers() override; - -private: - std::pair<http::status_code, json::value> lippincott(); - static json::value responseNotImpl(const http::method & method); +// Adapted from code provided by Ivan Mejia on 12/24/16 liscenced under the MIT License + +#pragma once + +#include <std_micro_service.hpp> +#include <basic_controller.hpp> +#include <database_manager.hpp> + +using namespace cfx; + +class MicroserviceController : public BasicController, Controller { +public: + MicroserviceController() : BasicController() {} + ~MicroserviceController() {} + void handleGet(http_request message) override; + void handlePut(http_request message) override; + void handlePost(http_request message) override; + void handleDelete(http_request message) override; + void handleConnect(http_request message) override; + void initRestOpHandlers() override; + +private: + std::pair<http::status_code, json::value> lippincott(); + static json::value responseNotImpl(const http::method & method); }; \ No newline at end of file diff --git a/source/foundation/include/network_utils.hpp b/source/foundation/include/network_utils.hpp index ff694d78e4af541f9496232fc5e01e367a2a1080..a831fadf2ef0775d637511343947ec92ab2dec12 100644 --- a/source/foundation/include/network_utils.hpp +++ b/source/foundation/include/network_utils.hpp @@ -1,35 +1,35 @@ -// Adapted from code provided by Ivan Mejia on 12/24/16 liscenced under the MIT License - -#pragma once - -#include <string> -#include "std_micro_service.hpp" - -using namespace boost::asio; -using namespace boost::asio::ip; - -namespace cfx { - - using HostInetInfo = tcp::resolver::iterator; - - class NetworkUtils { - private: - static HostInetInfo queryHostInetInfo(); - static std::string hostIP(unsigned short family); - public: - // gets the host IP4 string formatted - static std::string hostIP4() { - return hostIP(AF_INET); - } - - // gets the host IP6 string formatted - static std::string hostIP6() { - - return hostIP(AF_INET6); - } - static std::string hostName() { - return ip::host_name(); - } - }; - -} +// Adapted from code provided by Ivan Mejia on 12/24/16 liscenced under the MIT License + +#pragma once + +#include <string> +#include "std_micro_service.hpp" + +using namespace boost::asio; +using namespace boost::asio::ip; + +namespace cfx { + + using HostInetInfo = tcp::resolver::iterator; + + class NetworkUtils { + private: + static HostInetInfo queryHostInetInfo(); + static std::string hostIP(unsigned short family); + public: + // gets the host IP4 string formatted + static std::string hostIP4() { + return hostIP(AF_INET); + } + + // gets the host IP6 string formatted + static std::string hostIP6() { + + return hostIP(AF_INET6); + } + static std::string hostName() { + return ip::host_name(); + } + }; + +} diff --git a/source/foundation/include/runtime_utils.hpp b/source/foundation/include/runtime_utils.hpp index 78f2cf01a4955cd236051835ce287e0bdcfed009..d33170a7bdad83174d3a47d15db9c16c9c40ee3d 100644 --- a/source/foundation/include/runtime_utils.hpp +++ b/source/foundation/include/runtime_utils.hpp @@ -1,23 +1,23 @@ -// Adapted from code provided by Ivan Mejia on 12/24/16 liscenced under the MIT License - -#pragma once - -#include <execinfo.h> -#include <unistd.h> - -namespace cfx { - class RuntimeUtils { - public: - static void printStackTrace() { - const int MAX_CALLSTACK = 100; - void * callstack[MAX_CALLSTACK]; - int frames; - - // get void*'s for all entries on the stack... - frames = backtrace(callstack, MAX_CALLSTACK); - - // print out all the frames to stderr... - backtrace_symbols_fd(callstack, frames, STDERR_FILENO); - } - }; +// Adapted from code provided by Ivan Mejia on 12/24/16 liscenced under the MIT License + +#pragma once + +#include <execinfo.h> +#include <unistd.h> + +namespace cfx { + class RuntimeUtils { + public: + static void printStackTrace() { + const int MAX_CALLSTACK = 100; + void * callstack[MAX_CALLSTACK]; + int frames; + + // get void*'s for all entries on the stack... + frames = backtrace(callstack, MAX_CALLSTACK); + + // print out all the frames to stderr... + backtrace_symbols_fd(callstack, frames, STDERR_FILENO); + } + }; } \ No newline at end of file diff --git a/source/foundation/include/std_micro_service.hpp b/source/foundation/include/std_micro_service.hpp index 002831455e984d3242625243311058bae3fecc68..392fef2cf6fed526baf363b8eb5b5f566b000992 100644 --- a/source/foundation/include/std_micro_service.hpp +++ b/source/foundation/include/std_micro_service.hpp @@ -1,49 +1,49 @@ -// Adapted from code provided by Ivan Mejia on 12/24/16 liscenced under the MIT License - -#pragma once - -#define BOOST_SPIRIT_THREADSAFE // enable thread safety to json read on property tree!z - -#include <boost/format.hpp> - -#include <boost/log/core.hpp> -#include <boost/log/trivial.hpp> -#include <boost/log/expressions.hpp> -#include <boost/log/utility/setup/console.hpp> -#include <boost/log/support/date_time.hpp> -#include <boost/log/utility/setup/common_attributes.hpp> - -#include <boost/property_tree/ptree.hpp> -#include <boost/property_tree/json_parser.hpp> - -#include <boost/asio.hpp> -#include <boost/algorithm/string.hpp> - -#include <mongocxx/v_noabi/mongocxx/client.hpp> -#include <mongocxx/v_noabi/mongocxx/stdx.hpp> -#include <mongocxx/v_noabi/mongocxx/uri.hpp> -#include <mongocxx/v_noabi/mongocxx/instance.hpp> -#include <mongocxx/v_noabi/mongocxx/collection.hpp> -#include <mongocxx/v_noabi/mongocxx/pool.hpp> -#include <mongocxx/v_noabi/mongocxx/logger.hpp> - -#include <bsoncxx/v_noabi/bsoncxx/json.hpp> -#include <bsoncxx/v_noabi/bsoncxx/types.hpp> - -#include <bsoncxx/v_noabi/bsoncxx/builder/stream/helpers.hpp> -#include <bsoncxx/v_noabi/bsoncxx/builder/stream/document.hpp> -#include <bsoncxx/v_noabi/bsoncxx/builder/stream/array.hpp> - -#include <bsoncxx/v_noabi/bsoncxx/builder/basic/kvp.hpp> -#include <bsoncxx/v_noabi/bsoncxx/builder/basic/document.hpp> -#include <bsoncxx/v_noabi/bsoncxx/builder/basic/array.hpp> - -#include <bsoncxx/v_noabi/bsoncxx/stdx/optional.hpp> -#include <bsoncxx/v_noabi/bsoncxx/stdx/make_unique.hpp> -#include <bsoncxx/v_noabi/bsoncxx/stdx/string_view.hpp> - -#include <string> -#include <iostream> -#include <vector> -#include <map> -#include <regex> +// Adapted from code provided by Ivan Mejia on 12/24/16 liscenced under the MIT License + +#pragma once + +#define BOOST_SPIRIT_THREADSAFE // enable thread safety to json read on property tree!z + +#include <boost/format.hpp> + +#include <boost/log/core.hpp> +#include <boost/log/trivial.hpp> +#include <boost/log/expressions.hpp> +#include <boost/log/utility/setup/console.hpp> +#include <boost/log/support/date_time.hpp> +#include <boost/log/utility/setup/common_attributes.hpp> + +#include <boost/property_tree/ptree.hpp> +#include <boost/property_tree/json_parser.hpp> + +#include <boost/asio.hpp> +#include <boost/algorithm/string.hpp> + +#include <mongocxx/v_noabi/mongocxx/client.hpp> +#include <mongocxx/v_noabi/mongocxx/stdx.hpp> +#include <mongocxx/v_noabi/mongocxx/uri.hpp> +#include <mongocxx/v_noabi/mongocxx/instance.hpp> +#include <mongocxx/v_noabi/mongocxx/collection.hpp> +#include <mongocxx/v_noabi/mongocxx/pool.hpp> +#include <mongocxx/v_noabi/mongocxx/logger.hpp> + +#include <bsoncxx/v_noabi/bsoncxx/json.hpp> +#include <bsoncxx/v_noabi/bsoncxx/types.hpp> + +#include <bsoncxx/v_noabi/bsoncxx/builder/stream/helpers.hpp> +#include <bsoncxx/v_noabi/bsoncxx/builder/stream/document.hpp> +#include <bsoncxx/v_noabi/bsoncxx/builder/stream/array.hpp> + +#include <bsoncxx/v_noabi/bsoncxx/builder/basic/kvp.hpp> +#include <bsoncxx/v_noabi/bsoncxx/builder/basic/document.hpp> +#include <bsoncxx/v_noabi/bsoncxx/builder/basic/array.hpp> + +#include <bsoncxx/v_noabi/bsoncxx/stdx/optional.hpp> +#include <bsoncxx/v_noabi/bsoncxx/stdx/make_unique.hpp> +#include <bsoncxx/v_noabi/bsoncxx/stdx/string_view.hpp> + +#include <string> +#include <iostream> +#include <vector> +#include <map> +#include <regex> diff --git a/source/foundation/include/usr_interrupt_handler.hpp b/source/foundation/include/usr_interrupt_handler.hpp index 9705861216634de05e05df6bfd4078250db601d5..ae0f2883fd1495aa8aa498cacc21d9f453022c3a 100644 --- a/source/foundation/include/usr_interrupt_handler.hpp +++ b/source/foundation/include/usr_interrupt_handler.hpp @@ -1,32 +1,32 @@ -// Adapted from code provided by Ivan Mejia on 12/24/16 liscenced under the MIT License - -#include <condition_variable> -#include <mutex> -#include <iostream> -#include <signal.h> - -static std::condition_variable _condition; -static std::mutex _mutex; - -namespace cfx { - class InterruptHandler { - public: - static void hookSIGINT() { - signal(SIGINT, handleUserInterrupt); - } - - static void handleUserInterrupt(int signal){ - if (signal == SIGINT) { - std::cout << "SIGINT trapped ..." << '\n'; - _condition.notify_one(); - } - } - - static void waitForUserInterrupt() { - std::unique_lock<std::mutex> lock { _mutex }; - _condition.wait(lock); - std::cout << "user has signaled to interrup program..." << '\n'; - lock.unlock(); - } - }; +// Adapted from code provided by Ivan Mejia on 12/24/16 liscenced under the MIT License + +#include <condition_variable> +#include <mutex> +#include <iostream> +#include <signal.h> + +static std::condition_variable _condition; +static std::mutex _mutex; + +namespace cfx { + class InterruptHandler { + public: + static void hookSIGINT() { + signal(SIGINT, handleUserInterrupt); + } + + static void handleUserInterrupt(int signal){ + if (signal == SIGINT) { + std::cout << "SIGINT trapped ..." << '\n'; + _condition.notify_one(); + } + } + + static void waitForUserInterrupt() { + std::unique_lock<std::mutex> lock { _mutex }; + _condition.wait(lock); + std::cout << "user has signaled to interrup program..." << '\n'; + lock.unlock(); + } + }; } \ No newline at end of file diff --git a/source/foundation/network_utils.cpp b/source/foundation/network_utils.cpp index 2d74fb59654a94b80aee93228a2f65107e105350..d04696c78f04299409675e9da3dbdfe8f4bae23e 100644 --- a/source/foundation/network_utils.cpp +++ b/source/foundation/network_utils.cpp @@ -1,27 +1,27 @@ -// Adapted from code provided by Ivan Mejia on 12/24/16 liscenced under the MIT License - -#include "network_utils.hpp" - -namespace cfx { - - HostInetInfo NetworkUtils::queryHostInetInfo() { - io_service ios; - tcp::resolver resolver(ios); - tcp::resolver::query query(host_name(), ""); - return resolver.resolve(query); - } - - std::string NetworkUtils::hostIP(unsigned short family) { - auto hostInetInfo = queryHostInetInfo(); - tcp::resolver::iterator end; - while(hostInetInfo != end) { - tcp::endpoint ep = *hostInetInfo++; - sockaddr sa = *ep.data(); - if (sa.sa_family == family) { - return ep.address().to_string(); - } - } - return nullptr; - } - +// Adapted from code provided by Ivan Mejia on 12/24/16 liscenced under the MIT License + +#include "network_utils.hpp" + +namespace cfx { + + HostInetInfo NetworkUtils::queryHostInetInfo() { + io_service ios; + tcp::resolver resolver(ios); + tcp::resolver::query query(host_name(), ""); + return resolver.resolve(query); + } + + std::string NetworkUtils::hostIP(unsigned short family) { + auto hostInetInfo = queryHostInetInfo(); + tcp::resolver::iterator end; + while(hostInetInfo != end) { + tcp::endpoint ep = *hostInetInfo++; + sockaddr sa = *ep.data(); + if (sa.sa_family == family) { + return ep.address().to_string(); + } + } + return nullptr; + } + } \ No newline at end of file diff --git a/source/main.cpp b/source/main.cpp index f44eba0bec5ea8d57d67dc6d5e5c9a8504dca398..f810a8ded10c4f68068b99552c3b6dd2dacc0607 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -1,38 +1,39 @@ -// Adapted from code provided by Ivan Mejia on 12/24/16 liscenced under the MIT License - -#include <iostream> -#include <usr_interrupt_handler.hpp> -#include <runtime_utils.hpp> -#include <microsvc_controller.hpp> -#include <database_manager.hpp> - -// cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug .. -// make -j 8 - -using namespace web; - -int main() { - InterruptHandler::hookSIGINT(); - - mongocxx::uri _uri{ "mongodb+srv://dev-access:65kCnKukCMpJjwX0@cluster0.um0xm.mongodb.net/Furlough?retryWrites=true&w=majority" }; - databaseManager::configure_mongo(std::move(_uri)); - - MicroserviceController server{}; - server.setEndpoint("http://host_auto_ip4:6502/"); - - try { - // wait for server initialization... - server.accept().wait(); - std::cout << "D4 web server listening for requests at: " << server.endpoint() << '\n'; - - InterruptHandler::waitForUserInterrupt(); - server.shutdown().wait(); - } - catch(std::exception & e) { - std::cerr << "Error initialising server" << '\n'; - } - catch(...) { - RuntimeUtils::printStackTrace(); - } - return 0; -} +// Adapted from code provided by Ivan Mejia on 12/24/16 liscenced under the MIT License + +#include <iostream> +#include <usr_interrupt_handler.hpp> +#include <runtime_utils.hpp> +#include <microsvc_controller.hpp> +#include <database_manager.hpp> + +// cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug .. +// make -j 8 + +using namespace web; + +int main() { + InterruptHandler::hookSIGINT(); + + mongocxx::uri _uri{ "mongodb+srv://dev-access:65kCnKukCMpJjwX0@cluster0.um0xm.mongodb.net/Furlough?retryWrites=true&w=majority" }; + databaseManager::configure_mongo(std::move(_uri)); + + MicroserviceController server{}; + server.setEndpoint("http://ec2-18-135-114-10.eu-west-2.compute.amazonaws.com:6502/"); + server.setEndpoint("http://host_auto_ip4:6502/"); + + try { + // wait for server initialization... + server.accept().wait(); + std::cout << "D4 web server listening for requests at: " << server.endpoint() << '\n'; + + InterruptHandler::waitForUserInterrupt(); + server.shutdown().wait(); + } + catch(std::exception & e) { + std::cerr << "Error initialising server" << '\n'; + } + catch(...) { + RuntimeUtils::printStackTrace(); + } + return 0; +} diff --git a/source/microsvc_controller.cpp b/source/microsvc_controller.cpp index ad6c5c7ab1e1a5cb086f8fdae733498c9885ce93..c22dbedab26eed82fef5437eb440dbe4d349757f 100644 --- a/source/microsvc_controller.cpp +++ b/source/microsvc_controller.cpp @@ -1,251 +1,251 @@ -// Adapted from code provided by Ivan Mejia on 12/24/16 liscenced under the MIT License - -#include <std_micro_service.hpp> -#include "microsvc_controller.hpp" -#include "database_manager.hpp" - -using namespace web; -using namespace http; - -void MicroserviceController::initRestOpHandlers() { - listener.support(methods::GET, std::bind(&MicroserviceController::handleGet, this, std::placeholders::_1)); - listener.support(methods::PUT, std::bind(&MicroserviceController::handlePut, this, std::placeholders::_1)); - listener.support(methods::POST, std::bind(&MicroserviceController::handlePost, this, std::placeholders::_1)); - listener.support(methods::DEL, std::bind(&MicroserviceController::handleDelete, this, std::placeholders::_1)); - listener.support(methods::CONNECT, std::bind(&MicroserviceController::handleConnect, this, std::placeholders::_1)); -} - -std::pair<http::status_code, json::value> -MicroserviceController::lippincott() { - try { - throw; - } - catch (json::json_exception& e) { - json::value response; - response["message"] = json::value::string("Incorrect or missing field provided in JSON message"); - response["data"] = json::value::string(""); - return {status_codes::BadRequest, response}; - } - catch (std::exception& e) { - json::value response; - response["message"] = json::value::string(e.what()); - response["data"] = json::value::string(""); - return {status_codes::BadRequest, response}; - } - catch(...) { - json::value response; - response["message"] = json::value::string("Unspecified error in request"); - response["data"] = json::value::string(""); - return {status_codes::BadRequest, response}; - } -} - -/* -The GET method requests a representation of the specified resource. -Requests using GET should only retrieve data -*/ -void MicroserviceController::handleGet(http_request message) { - auto path = requestPath(message); - if (!path.empty()) { - if(path[0] == "avatar") { - if(path[1] == "stats") { - message - .extract_json() - .then([=](json::value request) { - try { - auto team_id = request["team-id"].as_integer(); - - auto stats = databaseManager::avatar::getStats(team_id); - - json::value response; - response["message"] = json::value::string("Successfully retrieved avatar stats"); - response["data"] = stats; - - message.reply(status_codes::OK, response); - } - catch(...) { - auto [code,resp] = MicroserviceController::lippincott(); - message.reply(code,resp); - } - }); - } - else { - message.reply(status_codes::NotFound); - } - } - else { - message.reply(status_codes::NotFound); - } - } - else { - message.reply(status_codes::NotFound); - } -} - -/* -The PUT method replaces all current representations of the target -resource with the request payload. -*/ -void MicroserviceController::handlePost(http_request message) { - auto path = requestPath(message); - if (!path.empty()) { - if (path[0] == "team") { - if(path[1] == "create") { - message - .extract_json() - .then([=](json::value request) { - try { - auto user_id = request["user-id"].as_integer(); - auto avatar_name = request["avatar-name"].as_string(); - - auto team = databaseManager::team::create(user_id, avatar_name); - - json::value response; - json::value sub; - sub ["hello"] = json::value::string("world"); - response["message"] = json::value::string("Successfully created team"); - response["data"] = team; - - message.reply(status_codes::OK, response); - } - catch(...) { - auto [code,resp] = MicroserviceController::lippincott(); - message.reply(code,resp); - } - }); - - } - else if (path[1] == "join") { - message - .extract_json() - .then([=](json::value request) { - try { - auto user_id = request["user-id"].as_integer(); - auto team_id = request["team-id"].as_integer(); - - auto userIDs = databaseManager::team::join(team_id, user_id); - - json::value response; - response["message"] = json::value::string("Successfully joined team"); - response["data"] = userIDs; - - message.reply(status_codes::OK, response); - } - catch(...) { - auto [code,resp] = MicroserviceController::lippincott(); - message.reply(code,resp); - } - }); - } - else { - message.reply(status_codes::NotFound); - } - } - else if(path[0] == "competition") { - if(path[1] == "join") { - message - .extract_json() - .then([=](json::value request) { - try { - auto team_id = request["team-id"].as_integer(); - auto comp_id = request["competition-id"].as_integer(); - auto user_id = request["user-id"].as_integer(); - - auto competition = databaseManager::competition::join(comp_id,team_id,user_id); - - json::value response; - response["message"] = json::value::string("Successfully joined competition"); - response["data"] = competition; - - message.reply(status_codes::OK, response); - } - catch(...) { - auto [code,resp] = MicroserviceController::lippincott(); - message.reply(code,resp); - } - }); - } - else if(path[1] == "create") { - message - .extract_json() - .then([=](json::value request) { - try { - auto user_id = request["user-id"].as_integer(); - auto team_id = request["team-id"].as_integer(); - - auto teamIDs = databaseManager::competition::create(team_id,user_id); - - json::value response; - response["message"] = json::value::string("Successfully created competition"); - response["data"] = teamIDs; - - message.reply(status_codes::OK, response); - - } - catch(...) { - auto [code,resp] = MicroserviceController::lippincott(); - message.reply(code,resp); - } - }); - } - else { - message.reply(status_codes::NotFound); - } - } - else if(path[0] == "avatar") { - if(path[1] == "update") { - message - .extract_json() - .then([=](json::value request) { - try { - auto team_id = request["team-id"].as_integer(); - auto health = request["health"].as_integer(); - - auto stats = databaseManager::avatar::update(team_id, health); - - json::value response; - response["message"] = json::value::string("Successfully update avatar stats"); - response["data"] = stats; - - message.reply(status_codes::OK, response); - } - catch(...) { - auto [code,resp] = MicroserviceController::lippincott(); - message.reply(code,resp); - } - }); - } - else { - message.reply(status_codes::NotFound); - } - } - } - else { - message.reply(status_codes::NotFound); - } -} - -/* -The POST method is used to submit an entity to the specified resource, -often causing a change in state or side effects on the server. -*/ -void MicroserviceController::handlePut(http_request message) { - message.reply(status_codes::NotImplemented, responseNotImpl(methods::POST)); -} - -/* The DELETE method deletes the specified resource. */ -void MicroserviceController::handleDelete(http_request message) { - message.reply(status_codes::NotImplemented, responseNotImpl(methods::DEL)); -} - -/* The CONNECT method establishes a tunnel to the server identified by the target resource.*/ -void MicroserviceController::handleConnect(http_request message) { - message.reply(status_codes::NotImplemented, responseNotImpl(methods::CONNECT)); -} - -json::value MicroserviceController::responseNotImpl(const http::method & method) { - auto response = json::value::object(); - response["serviceName"] = json::value::string("C++ Mircroservice Sample"); - response["http_method"] = json::value::string(method); - return response ; +// Adapted from code provided by Ivan Mejia on 12/24/16 liscenced under the MIT License + +#include <std_micro_service.hpp> +#include "microsvc_controller.hpp" +#include "database_manager.hpp" + +using namespace web; +using namespace http; + +void MicroserviceController::initRestOpHandlers() { + listener.support(methods::GET, std::bind(&MicroserviceController::handleGet, this, std::placeholders::_1)); + listener.support(methods::PUT, std::bind(&MicroserviceController::handlePut, this, std::placeholders::_1)); + listener.support(methods::POST, std::bind(&MicroserviceController::handlePost, this, std::placeholders::_1)); + listener.support(methods::DEL, std::bind(&MicroserviceController::handleDelete, this, std::placeholders::_1)); + listener.support(methods::CONNECT, std::bind(&MicroserviceController::handleConnect, this, std::placeholders::_1)); +} + +std::pair<http::status_code, json::value> +MicroserviceController::lippincott() { + try { + throw; + } + catch (json::json_exception& e) { + json::value response; + response["message"] = json::value::string("Incorrect or missing field provided in JSON message"); + response["data"] = json::value::string(""); + return {status_codes::BadRequest, response}; + } + catch (std::exception& e) { + json::value response; + response["message"] = json::value::string(e.what()); + response["data"] = json::value::string(""); + return {status_codes::BadRequest, response}; + } + catch(...) { + json::value response; + response["message"] = json::value::string("Unspecified error in request"); + response["data"] = json::value::string(""); + return {status_codes::BadRequest, response}; + } +} + +/* +The GET method requests a representation of the specified resource. +Requests using GET should only retrieve data +*/ +void MicroserviceController::handleGet(http_request message) { + auto path = requestPath(message); + if (!path.empty()) { + if(path[0] == "avatar") { + if(path[1] == "stats") { + message + .extract_json() + .then([=](json::value request) { + try { + auto team_id = request["team-id"].as_integer(); + + auto stats = databaseManager::avatar::getStats(team_id); + + json::value response; + response["message"] = json::value::string("Successfully retrieved avatar stats"); + response["data"] = stats; + + message.reply(status_codes::OK, response); + } + catch(...) { + auto [code,resp] = MicroserviceController::lippincott(); + message.reply(code,resp); + } + }); + } + else { + message.reply(status_codes::NotFound); + } + } + else { + message.reply(status_codes::NotFound); + } + } + else { + message.reply(status_codes::NotFound); + } +} + +/* +The PUT method replaces all current representations of the target +resource with the request payload. +*/ +void MicroserviceController::handlePost(http_request message) { + auto path = requestPath(message); + if (!path.empty()) { + if (path[0] == "team") { + if(path[1] == "create") { + message + .extract_json() + .then([=](json::value request) { + try { + auto user_id = request["user-id"].as_integer(); + auto avatar_name = request["avatar-name"].as_string(); + + auto team = databaseManager::team::create(user_id, avatar_name); + + json::value response; + json::value sub; + sub ["hello"] = json::value::string("world"); + response["message"] = json::value::string("Successfully created team"); + response["data"] = team; + + message.reply(status_codes::OK, response); + } + catch(...) { + auto [code,resp] = MicroserviceController::lippincott(); + message.reply(code,resp); + } + }); + + } + else if (path[1] == "join") { + message + .extract_json() + .then([=](json::value request) { + try { + auto user_id = request["user-id"].as_integer(); + auto team_id = request["team-id"].as_integer(); + + auto userIDs = databaseManager::team::join(team_id, user_id); + + json::value response; + response["message"] = json::value::string("Successfully joined team"); + response["data"] = userIDs; + + message.reply(status_codes::OK, response); + } + catch(...) { + auto [code,resp] = MicroserviceController::lippincott(); + message.reply(code,resp); + } + }); + } + else { + message.reply(status_codes::NotFound); + } + } + else if(path[0] == "competition") { + if(path[1] == "join") { + message + .extract_json() + .then([=](json::value request) { + try { + auto team_id = request["team-id"].as_integer(); + auto comp_id = request["competition-id"].as_integer(); + auto user_id = request["user-id"].as_integer(); + + auto competition = databaseManager::competition::join(comp_id,team_id,user_id); + + json::value response; + response["message"] = json::value::string("Successfully joined competition"); + response["data"] = competition; + + message.reply(status_codes::OK, response); + } + catch(...) { + auto [code,resp] = MicroserviceController::lippincott(); + message.reply(code,resp); + } + }); + } + else if(path[1] == "create") { + message + .extract_json() + .then([=](json::value request) { + try { + auto user_id = request["user-id"].as_integer(); + auto team_id = request["team-id"].as_integer(); + + auto teamIDs = databaseManager::competition::create(team_id,user_id); + + json::value response; + response["message"] = json::value::string("Successfully created competition"); + response["data"] = teamIDs; + + message.reply(status_codes::OK, response); + + } + catch(...) { + auto [code,resp] = MicroserviceController::lippincott(); + message.reply(code,resp); + } + }); + } + else { + message.reply(status_codes::NotFound); + } + } + else if(path[0] == "avatar") { + if(path[1] == "update") { + message + .extract_json() + .then([=](json::value request) { + try { + auto team_id = request["team-id"].as_integer(); + auto health = request["health"].as_integer(); + + auto stats = databaseManager::avatar::update(team_id, health); + + json::value response; + response["message"] = json::value::string("Successfully update avatar stats"); + response["data"] = stats; + + message.reply(status_codes::OK, response); + } + catch(...) { + auto [code,resp] = MicroserviceController::lippincott(); + message.reply(code,resp); + } + }); + } + else { + message.reply(status_codes::NotFound); + } + } + } + else { + message.reply(status_codes::NotFound); + } +} + +/* +The POST method is used to submit an entity to the specified resource, +often causing a change in state or side effects on the server. +*/ +void MicroserviceController::handlePut(http_request message) { + message.reply(status_codes::NotImplemented, responseNotImpl(methods::POST)); +} + +/* The DELETE method deletes the specified resource. */ +void MicroserviceController::handleDelete(http_request message) { + message.reply(status_codes::NotImplemented, responseNotImpl(methods::DEL)); +} + +/* The CONNECT method establishes a tunnel to the server identified by the target resource.*/ +void MicroserviceController::handleConnect(http_request message) { + message.reply(status_codes::NotImplemented, responseNotImpl(methods::CONNECT)); +} + +json::value MicroserviceController::responseNotImpl(const http::method & method) { + auto response = json::value::object(); + response["serviceName"] = json::value::string("C++ Mircroservice Sample"); + response["http_method"] = json::value::string(method); + return response ; } \ No newline at end of file diff --git a/tests/wrk/benchmark_microsvc.lua b/tests/wrk/benchmark_microsvc.lua index a0f505e61e846d2fa34fb2edb49d328afc128b31..a0b04f588b8c2e884143c7a68a8605163ac0bde6 100644 --- a/tests/wrk/benchmark_microsvc.lua +++ b/tests/wrk/benchmark_microsvc.lua @@ -1,32 +1,32 @@ --- MIT License --- --- Copyright (c) 2016 ivmeroLabs. --- --- Permission is hereby granted, free of charge, to any person obtaining a copy --- of this software and associated documentation files (the "Software"), to deal --- in the Software without restriction, including without limitation the rights --- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell --- copies of the Software, and to permit persons to whom the Software is --- furnished to do so, subject to the following conditions: --- --- The above copyright notice and this permission notice shall be included in all --- copies or substantial portions of the Software. --- --- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR --- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, --- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE --- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER --- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, --- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE --- SOFTWARE. - -request = function() - headers = {} - headers["Content-Type"] = "application/json" - return wrk.format("GET", "/v1/ivmero/api/service/test", headers, "") -end - -response = function(status, headers, body) - -- comment the following line to avoid server's excesive I/O to console on heavy load - -- io.write("response: \n" .. body .. "\n---------------------------------------------\n") +-- MIT License +-- +-- Copyright (c) 2016 ivmeroLabs. +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy +-- of this software and associated documentation files (the "Software"), to deal +-- in the Software without restriction, including without limitation the rights +-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +-- copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all +-- copies or substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +-- SOFTWARE. + +request = function() + headers = {} + headers["Content-Type"] = "application/json" + return wrk.format("GET", "/v1/ivmero/api/service/test", headers, "") +end + +response = function(status, headers, body) + -- comment the following line to avoid server's excesive I/O to console on heavy load + -- io.write("response: \n" .. body .. "\n---------------------------------------------\n") end \ No newline at end of file diff --git a/tests/wrk/benchmark_microsvc_POST.lua b/tests/wrk/benchmark_microsvc_POST.lua index 20089f8c7fe9698f6ef6e632f83f3d638d3d1262..d481a3a50d6feba81a55d8ba6b1a507ef48aa432 100644 --- a/tests/wrk/benchmark_microsvc_POST.lua +++ b/tests/wrk/benchmark_microsvc_POST.lua @@ -1,33 +1,33 @@ --- MIT License --- --- Copyright (c) 2016 ivmeroLabs. --- --- Permission is hereby granted, free of charge, to any person obtaining a copy --- of this software and associated documentation files (the "Software"), to deal --- in the Software without restriction, including without limitation the rights --- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell --- copies of the Software, and to permit persons to whom the Software is --- furnished to do so, subject to the following conditions: --- --- The above copyright notice and this permission notice shall be included in all --- copies or substantial portions of the Software. --- --- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR --- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, --- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE --- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER --- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, --- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE --- SOFTWARE. - -request = function() - headers = {} - headers["Content-Type"] = "application/json" - body = "{}" - return wrk.format("POST", "/v1/ivmero/api", headers, body) -end - -response = function(status, headers, body) - -- comment the following line to avoid server's excesive I/O to console on heavy load - io.write("response: \n" .. body .. "\n---------------------------------------------\n") +-- MIT License +-- +-- Copyright (c) 2016 ivmeroLabs. +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy +-- of this software and associated documentation files (the "Software"), to deal +-- in the Software without restriction, including without limitation the rights +-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +-- copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all +-- copies or substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +-- SOFTWARE. + +request = function() + headers = {} + headers["Content-Type"] = "application/json" + body = "{}" + return wrk.format("POST", "/v1/ivmero/api", headers, body) +end + +response = function(status, headers, body) + -- comment the following line to avoid server's excesive I/O to console on heavy load + io.write("response: \n" .. body .. "\n---------------------------------------------\n") end \ No newline at end of file