Adding Signup

This commit is contained in:
stephb9959
2022-02-22 23:09:18 -08:00
parent d9e9afef62
commit b3ab9b5e1f
9 changed files with 225 additions and 19 deletions

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -14,7 +14,9 @@ namespace OpenWifi {
std::vector<std::string>{
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:
};

View File

@@ -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++;
}
}
}
}

View File

@@ -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;
std::atomic_bool Running_ = false;
std::map<std::string, ProvObjects::SignupEntry> OutstandingSignups_;
Poco::Thread Worker_;
Signup() noexcept:
SubSystemServer("SignupServer", "SIGNUP", "signup")

View File

@@ -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 {

View File

@@ -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);
}

View File

@@ -20,12 +20,14 @@ namespace OpenWifi {
std::string,
uint64_t,
uint64_t,
std::string
std::string,
uint64_t
> SignupDBRecordType;
class SignupDB : public ORM::DB<SignupDBRecordType, ProvObjects::SignupEntry> {
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:
};
}

View File

@@ -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}