From b3ab9b5e1f2baa9906b63ff4e2938b0a276e3473 Mon Sep 17 00:00:00 2001 From: stephb9959 Date: Tue, 22 Feb 2022 23:09:18 -0800 Subject: [PATCH] Adding Signup --- openapi/owprov.yaml | 66 ++++++++++++++++++++++++++ src/RESTAPI/RESTAPI_signup_handler.cpp | 50 ++++++++++++++++--- src/RESTAPI/RESTAPI_signup_handler.h | 8 ++-- src/Signup.cpp | 63 +++++++++++++++++++++++- src/Signup.h | 32 +++++++++++-- src/framework/ow_constants.h | 1 + src/storage/storage_signup.cpp | 16 ++++++- src/storage/storage_signup.h | 6 ++- test_scripts/curl/cli | 2 +- 9 files changed, 225 insertions(+), 19 deletions(-) diff --git a/openapi/owprov.yaml b/openapi/owprov.yaml index 57e7873..0b14754 100644 --- a/openapi/owprov.yaml +++ b/openapi/owprov.yaml @@ -2577,6 +2577,72 @@ paths: $ref: '#/components/responses/NotFound' /signup: + get: + tags: + - Subscriber Registration + summary: This call allows someone to get the status of a signup. + operationId: getSignup + parameters: + - in: query + name: email + schema: + type: string + format: email + required: false + - in: query + name: serialNumber + schema: + type: string + required: false + - in: query + mame: signupUUID + schema: + type: string + format: uuid + required: false + responses: + 200: + $ref: '#/components/schemas/SignupEntry' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + + delete: + tags: + - Subscriber Registration + summary: This call allows someone to get the status of a signup. + operationId: getSignup + parameters: + - in: query + name: email + schema: + type: string + format: email + required: false + - in: query + name: serialNumber + schema: + type: string + required: false + - in: query + mame: signupUUID + schema: + type: string + format: uuid + required: false + responses: + 204: + $ref: '#/components/responses/Success' + 400: + $ref: '#/components/responses/BadRequest' + 403: + $ref: '#/components/responses/Unauthorized' + 404: + $ref: '#/components/responses/NotFound' + post: tags: - Subscriber Registration diff --git a/src/RESTAPI/RESTAPI_signup_handler.cpp b/src/RESTAPI/RESTAPI_signup_handler.cpp index f950867..848ace1 100644 --- a/src/RESTAPI/RESTAPI_signup_handler.cpp +++ b/src/RESTAPI/RESTAPI_signup_handler.cpp @@ -68,7 +68,7 @@ namespace OpenWifi { }, Body, 30000); Poco::JSON::Object::Ptr Answer; - if(CreateUser.Do(Answer)) { + if(CreateUser.Do(Answer) == Poco::Net::HTTPServerResponse::HTTP_OK) { SecurityObjects::UserInfo UI; UI.from_json(Answer); @@ -90,6 +90,7 @@ namespace OpenWifi { std::cout << "Creating signup entry: " << SE.email << std::endl; StorageService()->SignupDB().CreateRecord(SE); + Signup()->AddOutstandingSignup(SE); // We do not have a device, so let's create one. if(IT.serialNumber.empty()) { @@ -103,9 +104,9 @@ namespace OpenWifi { StateDoc.set("errorCode",0); StateDoc.set("date", OpenWifi::Now()); StateDoc.set("status", "waiting for email-verification"); - std::ostringstream os; - StateDoc.stringify(os); - IT.state = os.str(); + std::ostringstream os2; + StateDoc.stringify(os2); + IT.state = os2.str(); std::cout << "Creating inventory entry: " << SE.serialNumber << std::endl; StorageService()->InventoryDB().CreateRecord(IT); } else { @@ -116,9 +117,9 @@ namespace OpenWifi { StateDoc.set("errorCode",0); StateDoc.set("date", OpenWifi::Now()); StateDoc.set("status", "waiting for email-verification"); - std::ostringstream os; - StateDoc.stringify(os); - IT.state = os.str(); + std::ostringstream os2; + StateDoc.stringify(os2); + IT.state = os2.str(); IT.info.modified = OpenWifi::Now(); std::cout << "Updating inventory entry: " << SE.serialNumber << std::endl; StorageService()->InventoryDB().UpdateRecord("id",IT.info.id,IT); @@ -151,13 +152,48 @@ namespace OpenWifi { SE.info.modified = OpenWifi::Now(); SE.status = "emailVerified"; + StorageService()->SignupDB().UpdateRecord("id", SE.info.id, SE); + Signup()->AddOutstandingSignup(SE); Poco::JSON::Object Answer; SE.to_json(Answer); + return ReturnObject(Answer); } + } + void RESTAPI_signup_handler::DoGet() { + auto EMail = GetParameter("email", ""); + auto SignupUUID = GetParameter("signupUUID", ""); + auto SerialNumber = GetParameter("serialNumber", ""); + + Poco::JSON::Object Answer; + ProvObjects::SignupEntry SE; + if(!SignupUUID.empty()) { + if(StorageService()->SignupDB().GetRecord("id", SignupUUID, SE)) { + SE.to_json(Answer); + return ReturnObject(Answer); + } + return NotFound(); + } else if(!EMail.empty()) { + SignupDB::RecordVec SEs; + if(StorageService()->SignupDB().GetRecords(0,100,SEs, " email='"+EMail+"' ")) { + return ReturnObject("signups",SEs); + } + return NotFound(); + } else if(!SerialNumber.empty()) { + SignupDB::RecordVec SEs; + if(StorageService()->SignupDB().GetRecords(0,100,SEs, " serialNumber='"+SerialNumber+"' ")) { + return ReturnObject("signups",SEs); + } + return NotFound(); + } + return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters); + } + + void RESTAPI_signup_handler::DoDelete() { + return BadRequest(RESTAPI::Errors::NotImplemented); } } \ No newline at end of file diff --git a/src/RESTAPI/RESTAPI_signup_handler.h b/src/RESTAPI/RESTAPI_signup_handler.h index c863f71..32f578e 100644 --- a/src/RESTAPI/RESTAPI_signup_handler.h +++ b/src/RESTAPI/RESTAPI_signup_handler.h @@ -14,7 +14,9 @@ namespace OpenWifi { std::vector{ Poco::Net::HTTPRequest::HTTP_POST, Poco::Net::HTTPRequest::HTTP_OPTIONS, - Poco::Net::HTTPRequest::HTTP_PUT}, + Poco::Net::HTTPRequest::HTTP_PUT, + Poco::Net::HTTPRequest::HTTP_GET, + Poco::Net::HTTPRequest::HTTP_DELETE}, Server, TransactionId, Internal, false, true ){} @@ -29,10 +31,10 @@ namespace OpenWifi { return true; } */ - void DoGet() final {}; + void DoGet() final; void DoPost() final; void DoPut() final ; - void DoDelete() final {}; + void DoDelete() final; private: }; diff --git a/src/Signup.cpp b/src/Signup.cpp index 1451bb1..b72a18a 100644 --- a/src/Signup.cpp +++ b/src/Signup.cpp @@ -3,6 +3,7 @@ // #include "Signup.h" +#include "StorageService.h" namespace OpenWifi { @@ -10,11 +11,71 @@ namespace OpenWifi { GracePeriod_ = MicroService::instance().ConfigGetInt("signup.graceperiod", 60*60); LingerPeriod_ = MicroService::instance().ConfigGetInt("signup.lingerperiod", 24*60*60); + SignupDB::RecordVec Signups_; + StorageService()->SignupDB().GetIncompleteSignups(Signups_); + + for(const auto &i:Signups_) { + OutstandingSignups_[i.info.id] = i; + } + Worker_.start(*this); return 0; } void Signup::Stop() { - + Running_ = false; + Worker_.wakeUp(); + Worker_.join(); } + void Signup::run() { + Running_ = true; + while(Running_) { + Poco::Thread::trySleep(5000); + + if(!Running_) + break; + + // get the list of outstanding stuff and see if we have gotten the device... + std::lock_guard G(Mutex_); + for(auto &[uuid,SE]:OutstandingSignups_) { + if(SE.status == "emailVerified") { + // look for the device... + ProvObjects::InventoryTag IT; + if(StorageService()->InventoryDB().GetRecord("serialNumber",SE.serialNumber,IT)) { + // if the deviceType is empty, we know that the device has not contacted + // the service yet. + if(IT.deviceType.empty()) + continue; + + // We have a device type, so the device contacted us. + // We must now complete the device transfer to this new subscriber and complete the + // signup job. + IT.subscriber = SE.userId; + IT.info.modified = OpenWifi::Now(); + Poco::JSON::Object NewState; + NewState.set("method","signup"); + NewState.set("date", OpenWifi::Now()); + NewState.set("status", "completed"); + std::ostringstream OS; + NewState.stringify(OS); + IT.state = OS.str(); + StorageService()->InventoryDB().UpdateRecord("id",IT.info.id,IT); + + SE.status = "signup completed"; + SE.completed = OpenWifi::Now(); + SE.info.modified = OpenWifi::Now(); + SE.error = 0 ; + StorageService()->SignupDB().UpdateRecord("id", SE.info.id, SE); + } + } + } + + for(auto i = begin(OutstandingSignups_); i!=end(OutstandingSignups_);) { + if(i->second.completed!=0) + i = OutstandingSignups_.erase(i); + else + i++; + } + } + } } \ No newline at end of file diff --git a/src/Signup.h b/src/Signup.h index 4f0efea3..e00b241 100644 --- a/src/Signup.h +++ b/src/Signup.h @@ -5,10 +5,11 @@ #pragma once #include "framework/MicroService.h" +#include "RESTObjects/RESTAPI_ProvObjects.h" namespace OpenWifi { - class Signup : public SubSystemServer { + class Signup : public SubSystemServer, Poco::Runnable { public: static auto instance() { @@ -18,13 +19,38 @@ namespace OpenWifi { int Start() override; void Stop() override; + void run() final; inline uint64_t GracePeriod() const { return GracePeriod_; }; inline uint64_t LingerPeriod() const { return LingerPeriod_; } + inline bool GetSignupById(const std::string & UUID, ProvObjects::SignupEntry &SE) { + std::lock_guard G(Mutex_); + auto hint = OutstandingSignups_.find(UUID); + + if(hint == end(OutstandingSignups_)) + return false; + + SE = hint->second; + return true; + } + + inline void RemoveSignupById(const std::string & UUID) { + std::lock_guard G(Mutex_); + OutstandingSignups_.erase(UUID); + } + + inline void AddOutstandingSignup(const ProvObjects::SignupEntry &SE) { + std::lock_guard G(Mutex_); + OutstandingSignups_[SE.info.id] = SE; + } + private: - uint64_t GracePeriod_ = 60 * 60; - uint64_t LingerPeriod_ = 24 * 60 * 60; + uint64_t GracePeriod_ = 60 * 60; + uint64_t LingerPeriod_ = 24 * 60 * 60; + std::atomic_bool Running_ = false; + std::map OutstandingSignups_; + Poco::Thread Worker_; Signup() noexcept: SubSystemServer("SignupServer", "SIGNUP", "signup") diff --git a/src/framework/ow_constants.h b/src/framework/ow_constants.h index fd59d75..ad58182 100644 --- a/src/framework/ow_constants.h +++ b/src/framework/ow_constants.h @@ -70,6 +70,7 @@ namespace OpenWifi::RESTAPI::Errors { static const std::string SerialNumberAlreadyProvisioned{"This device has already been provisioned to a subscriber."}; static const std::string SerialNumberNotTheProperClass{"Device is not available to subscribers. It ahs been assigned to another class of devices."}; static const std::string UserAlreadyExists{"Username already exists."}; + static const std::string NotImplemented{"Function not implemented."}; } namespace OpenWifi::RESTAPI::Protocol { diff --git a/src/storage/storage_signup.cpp b/src/storage/storage_signup.cpp index 65af01d..8b20f40 100644 --- a/src/storage/storage_signup.cpp +++ b/src/storage/storage_signup.cpp @@ -24,7 +24,8 @@ namespace OpenWifi { ORM::Field{"serialNumber",ORM::FieldType::FT_TEXT}, ORM::Field{"submitted",ORM::FieldType::FT_BIGINT}, ORM::Field{"completed",ORM::FieldType::FT_BIGINT}, - ORM::Field{"status",ORM::FieldType::FT_TEXT} + ORM::Field{"status",ORM::FieldType::FT_TEXT}, + ORM::Field{"error",ORM::FieldType::FT_BIGINT} }; const static ORM::IndexVec SignupDB_Indexes{ @@ -34,10 +35,19 @@ namespace OpenWifi { ORM::Indextype::ASC} } } }; - SignupDB::SignupDB( OpenWifi::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L) : + SignupDB::SignupDB( OpenWifi::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L) noexcept : DB(T, "signups", SignupDB_Fields, SignupDB_Indexes, P, L, "sig") { } + bool SignupDB::GetIncompleteSignups(SignupDB::RecordVec &Signups) { + try { + return GetRecords(0,10000,Signups," completed=0 and error=0 "); + } catch (const Poco::Exception &E) { + Logger().log(E); + } + return false; + } + } template<> void ORM::DB< OpenWifi::SignupDBRecordType, OpenWifi::ProvObjects::SignupEntry>::Convert(const OpenWifi::SignupDBRecordType &In, OpenWifi::ProvObjects::SignupEntry &Out) { @@ -53,6 +63,7 @@ template<> void ORM::DB< OpenWifi::SignupDBRecordType, OpenWifi::ProvObjects: Out.submitted = In.get<9>(); Out.completed = In.get<10>(); Out.status = In.get<11>(); + Out.error = In.get<12>(); } template<> void ORM::DB< OpenWifi::SignupDBRecordType, OpenWifi::ProvObjects::SignupEntry>::Convert(const OpenWifi::ProvObjects::SignupEntry &In, OpenWifi::SignupDBRecordType &Out) { @@ -68,4 +79,5 @@ template<> void ORM::DB< OpenWifi::SignupDBRecordType, OpenWifi::ProvObjects: Out.set<9>(In.submitted); Out.set<10>(In.completed); Out.set<11>(In.status); + Out.set<12>(In.error); } diff --git a/src/storage/storage_signup.h b/src/storage/storage_signup.h index d396f84..bae0a07 100644 --- a/src/storage/storage_signup.h +++ b/src/storage/storage_signup.h @@ -20,12 +20,14 @@ namespace OpenWifi { std::string, uint64_t, uint64_t, - std::string + std::string, + uint64_t > SignupDBRecordType; class SignupDB : public ORM::DB { public: - SignupDB( OpenWifi::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L); + explicit SignupDB(OpenWifi::DBType T, Poco::Data::SessionPool & P, Poco::Logger &L) noexcept; + bool GetIncompleteSignups( SignupDB::RecordVec & Signups ); private: }; } \ No newline at end of file diff --git a/test_scripts/curl/cli b/test_scripts/curl/cli index e169deb..9304441 100755 --- a/test_scripts/curl/cli +++ b/test_scripts/curl/cli @@ -462,7 +462,7 @@ affecteddevices() { } signup() { - curl ${FLAGS} -X POST "https://${OWPROV}/api/v1/signup?email=stehane.bourque@gmail.com&serialNumber=112233445566" \ + curl ${FLAGS} -X POST "https://${OWPROV}/api/v1/signup?email=stephane.bourque@gmail.com&serialNumber=112233445566" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ${token}" \ -H "accept: application/json" > ${result_file}