mirror of
https://github.com/Telecominfraproject/wlan-cloud-owprov.git
synced 2025-10-29 17:52:28 +00:00
Adding Signup Table
This commit is contained in:
@@ -128,7 +128,7 @@ add_executable(owprov
|
||||
src/WebSocketClientServer.cpp src/WebSocketClientServer.h
|
||||
src/storage/storage_maps.cpp src/storage/storage_maps.h
|
||||
src/RESTAPI/RESTAPI_map_handler.cpp src/RESTAPI/RESTAPI_map_handler.h
|
||||
src/RESTAPI/RESTAPI_map_list_handler.cpp src/RESTAPI/RESTAPI_map_list_handler.h src/storage/storage_signup.cpp src/storage/storage_signup.h)
|
||||
src/RESTAPI/RESTAPI_map_list_handler.cpp src/RESTAPI/RESTAPI_map_list_handler.h src/storage/storage_signup.cpp src/storage/storage_signup.h src/Signup.cpp src/Signup.h)
|
||||
|
||||
target_link_libraries(owprov PUBLIC
|
||||
${Poco_LIBRARIES} ${MySQL_LIBRARIES}
|
||||
|
||||
@@ -568,7 +568,7 @@ components:
|
||||
type: string
|
||||
devClass:
|
||||
type: string
|
||||
enum:4
|
||||
enum:
|
||||
- any
|
||||
- venue
|
||||
- entity
|
||||
@@ -734,6 +734,31 @@ components:
|
||||
reason:
|
||||
type: string
|
||||
|
||||
SignupEntry:
|
||||
type: object
|
||||
properties:
|
||||
allOf:
|
||||
$ref: '#/components/schemas/ObjectInfo'
|
||||
email:
|
||||
type: string
|
||||
format: email
|
||||
userId:
|
||||
type: string
|
||||
format: uuid
|
||||
serialNumber:
|
||||
type: string
|
||||
created:
|
||||
type: integer
|
||||
format: int64
|
||||
completed:
|
||||
type: integer
|
||||
format: int64
|
||||
error:
|
||||
type: integer
|
||||
format: int64
|
||||
status:
|
||||
type: string
|
||||
|
||||
#########################################################################################
|
||||
##
|
||||
## These are endpoints that all services in the OPenWiFI stack must provide
|
||||
@@ -2571,16 +2596,7 @@ paths:
|
||||
required: true
|
||||
responses:
|
||||
200:
|
||||
description: Success signup post
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type:
|
||||
object
|
||||
properties:
|
||||
signupUUID:
|
||||
type: string
|
||||
format: uuid
|
||||
$ref: '#/components/schemas/SignupEntry'
|
||||
400:
|
||||
$ref: '#/components/responses/BadRequest'
|
||||
403:
|
||||
@@ -2625,11 +2641,13 @@ paths:
|
||||
errorCode:
|
||||
type: integer
|
||||
format: int32
|
||||
status:
|
||||
type: string
|
||||
required: false
|
||||
|
||||
responses:
|
||||
200:
|
||||
$ref: '#/components/responses/Success'
|
||||
$ref: '#/components/schemas/SignupEntry'
|
||||
400:
|
||||
$ref: '#/components/responses/BadRequest'
|
||||
403:
|
||||
|
||||
@@ -70,6 +70,9 @@ openwifi.kafka.ssl.certificate.location =
|
||||
openwifi.kafka.ssl.key.location =
|
||||
openwifi.kafka.ssl.key.password =
|
||||
|
||||
signup.graceperiod = 3600
|
||||
signup.lingerperiod = 84400
|
||||
|
||||
#
|
||||
# This section select which form of persistence you need
|
||||
# Only one selected at a time. If you select multiple, this service will die if a horrible
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "JobController.h"
|
||||
#include "WebSocketClientServer.h"
|
||||
#include "FindCountry.h"
|
||||
#include "Signup.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
class Daemon *Daemon::instance_ = nullptr;
|
||||
@@ -36,7 +37,8 @@ namespace OpenWifi {
|
||||
AutoDiscovery(),
|
||||
JobController(),
|
||||
WebSocketClientServer(),
|
||||
FindCountryFromIP()
|
||||
FindCountryFromIP(),
|
||||
Signup()
|
||||
});
|
||||
}
|
||||
return instance_;
|
||||
|
||||
@@ -4,14 +4,16 @@
|
||||
|
||||
#include "RESTAPI_signup_handler.h"
|
||||
#include "StorageService.h"
|
||||
#include "RESTObjects/RESTAPI_SecurityObjects.h"
|
||||
#include "Signup.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
void RESTAPI_signup_handler::DoPost() {
|
||||
|
||||
auto UserName = GetParameter("email","");
|
||||
Poco::toLowerInPlace(UserName);
|
||||
auto SerialNumber = GetParameter("serialNumber","");
|
||||
Poco::toLowerInPlace(SerialNumber);
|
||||
|
||||
if(UserName.empty() || SerialNumber.empty()) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
@@ -25,15 +27,134 @@ namespace OpenWifi {
|
||||
return BadRequest(RESTAPI::Errors::InvalidSerialNumber);
|
||||
}
|
||||
|
||||
// let's see if the user already exists. If so, we will try and see if
|
||||
// it's just
|
||||
// if a signup already exists for this user, we should just return its value
|
||||
// or its completion
|
||||
SignupDB::RecordVec SEs;
|
||||
if(StorageService()->SignupDB().GetRecords(0,100, SEs, "email='" + UserName + "'")) {
|
||||
for(const auto &i:SEs) {
|
||||
if((i.created + Signup()->GracePeriod()) > OpenWifi::Now() && i.serialNumber==SerialNumber) {
|
||||
Poco::JSON::Object Answer;
|
||||
i.to_json(Answer);
|
||||
return ReturnObject(Answer);
|
||||
} else if((i.created + Signup()->GracePeriod()) < OpenWifi::Now() && i.completed==0) {
|
||||
StorageService()->SignupDB().DeleteRecord("id", i.info.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Do we already exist? Can only signup once...
|
||||
return OK();
|
||||
// So we do not have an outstanding signup...
|
||||
// Can we actually claim this serial number??? if not, we need to return an error
|
||||
ProvObjects::InventoryTag IT;
|
||||
if(StorageService()->InventoryDB().GetRecord("serialNumber",SerialNumber,IT)) {
|
||||
|
||||
if(!IT.subscriber.empty()) {
|
||||
return BadRequest(RESTAPI::Errors::SerialNumberAlreadyProvisioned);
|
||||
}
|
||||
|
||||
if(!(IT.devClass.empty() || IT.devClass=="subscriber" || IT.devClass=="any")) {
|
||||
return BadRequest(RESTAPI::Errors::SerialNumberNotTheProperClass);
|
||||
}
|
||||
}
|
||||
|
||||
// OK, we can claim this device, can we create a userid?
|
||||
// Let's create one
|
||||
// If sec.signup("email",uuid);
|
||||
auto SignupUUID = MicroService::instance().CreateUUID();
|
||||
|
||||
Poco::JSON::Object Body;
|
||||
OpenAPIRequestPost CreateUser( uSERVICE_SECURITY, "/api/v1/signup", {
|
||||
{ "email", UserName },
|
||||
{ "signupUUID" , SignupUUID }
|
||||
}, Body, 30000);
|
||||
|
||||
Poco::JSON::Object::Ptr Answer;
|
||||
if(CreateUser.Do(Answer)) {
|
||||
SecurityObjects::UserInfo UI;
|
||||
|
||||
UI.from_json(Answer);
|
||||
|
||||
// so create the Signup entry and modify the inventory
|
||||
ProvObjects::SignupEntry SE;
|
||||
|
||||
SE.info.id = SignupUUID;
|
||||
SE.info.created = SE.info.modified = SE.created = OpenWifi::Now();
|
||||
SE.completed = 0 ;
|
||||
SE.serialNumber = SerialNumber;
|
||||
SE.error = 0 ;
|
||||
SE.userId = UI.id;
|
||||
SE.email = UserName;
|
||||
SE.status = "waiting-for-email-verification";
|
||||
|
||||
std::cout << "Creating signup entry: " << SE.email << std::endl;
|
||||
StorageService()->SignupDB().CreateRecord(SE);
|
||||
|
||||
// We do not have a device, so let's create one.
|
||||
if(IT.serialNumber.empty()) {
|
||||
IT.serialNumber = SerialNumber;
|
||||
IT.info.id = MicroService::instance().CreateUUID();
|
||||
IT.info.created = IT.info.modified = OpenWifi::Now();
|
||||
Poco::JSON::Object StateDoc;
|
||||
StateDoc.set("method", "signup");
|
||||
StateDoc.set("claimer", UserName);
|
||||
StateDoc.set("claimId", UI.id);
|
||||
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::cout << "Creating inventory entry: " << SE.serialNumber << std::endl;
|
||||
StorageService()->InventoryDB().CreateRecord(IT);
|
||||
} else {
|
||||
Poco::JSON::Object StateDoc;
|
||||
StateDoc.set("method", "signup");
|
||||
StateDoc.set("claimer", UserName);
|
||||
StateDoc.set("claimId", UI.id);
|
||||
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();
|
||||
IT.info.modified = OpenWifi::Now();
|
||||
std::cout << "Updating inventory entry: " << SE.serialNumber << std::endl;
|
||||
StorageService()->InventoryDB().UpdateRecord("id",IT.info.id,IT);
|
||||
}
|
||||
|
||||
Poco::JSON::Object SEAnswer;
|
||||
SE.to_json(SEAnswer);
|
||||
return ReturnObject(SEAnswer);
|
||||
}
|
||||
|
||||
return BadRequest(RESTAPI::Errors::UserAlreadyExists);
|
||||
}
|
||||
|
||||
// this will be called by the SEC backend once the password has been verified.
|
||||
void RESTAPI_signup_handler::DoPut() {
|
||||
// TODO
|
||||
auto SignupUUID = GetParameter("signupUUID","");
|
||||
auto Operation = GetParameter("operation","");
|
||||
|
||||
if(SignupUUID.empty() || Operation.empty()) {
|
||||
return BadRequest(RESTAPI::Errors::MissingOrInvalidParameters);
|
||||
}
|
||||
|
||||
ProvObjects::SignupEntry SE;
|
||||
if(!StorageService()->SignupDB().GetRecord("id",SignupUUID,SE)) {
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
if(Operation == "emailVerified") {
|
||||
std::cout << "Verified email for : " << SE.email << std::endl;
|
||||
|
||||
SE.info.modified = OpenWifi::Now();
|
||||
SE.status = "emailVerified";
|
||||
StorageService()->SignupDB().UpdateRecord("id", SE.info.id, SE);
|
||||
|
||||
Poco::JSON::Object Answer;
|
||||
SE.to_json(Answer);
|
||||
return ReturnObject(Answer);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -610,6 +610,8 @@ namespace OpenWifi::ProvObjects {
|
||||
RESTAPI_utils::field_to_json( Obj,"serialNumber", serialNumber);
|
||||
RESTAPI_utils::field_to_json( Obj,"created", created);
|
||||
RESTAPI_utils::field_to_json( Obj,"completed", completed);
|
||||
RESTAPI_utils::field_to_json( Obj,"status", status);
|
||||
RESTAPI_utils::field_to_json( Obj,"error", error);
|
||||
}
|
||||
|
||||
bool SignupEntry::from_json(const Poco::JSON::Object::Ptr &Obj) {
|
||||
@@ -620,6 +622,8 @@ namespace OpenWifi::ProvObjects {
|
||||
RESTAPI_utils::field_from_json( Obj,"serialNumber", serialNumber);
|
||||
RESTAPI_utils::field_from_json( Obj,"created", created);
|
||||
RESTAPI_utils::field_from_json( Obj,"completed", completed);
|
||||
RESTAPI_utils::field_from_json( Obj,"status", status);
|
||||
RESTAPI_utils::field_from_json( Obj,"error", error);
|
||||
return true;
|
||||
} catch(...) {
|
||||
|
||||
|
||||
@@ -393,6 +393,8 @@ namespace OpenWifi::ProvObjects {
|
||||
std::string serialNumber;
|
||||
uint64_t created = 0 ;
|
||||
uint64_t completed = 0 ;
|
||||
std::string status;
|
||||
uint64_t error=0;
|
||||
|
||||
void to_json(Poco::JSON::Object &Obj) const;
|
||||
bool from_json(const Poco::JSON::Object::Ptr &Obj);
|
||||
|
||||
20
src/Signup.cpp
Normal file
20
src/Signup.cpp
Normal file
@@ -0,0 +1,20 @@
|
||||
//
|
||||
// Created by stephane bourque on 2022-02-22.
|
||||
//
|
||||
|
||||
#include "Signup.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
int Signup::Start() {
|
||||
GracePeriod_ = MicroService::instance().ConfigGetInt("signup.graceperiod", 60*60);
|
||||
LingerPeriod_ = MicroService::instance().ConfigGetInt("signup.lingerperiod", 24*60*60);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Signup::Stop() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
37
src/Signup.h
Normal file
37
src/Signup.h
Normal file
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// Created by stephane bourque on 2022-02-22.
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "framework/MicroService.h"
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
class Signup : public SubSystemServer {
|
||||
public:
|
||||
|
||||
static auto instance() {
|
||||
static auto instance_ = new Signup;
|
||||
return instance_;
|
||||
}
|
||||
|
||||
int Start() override;
|
||||
void Stop() override;
|
||||
|
||||
inline uint64_t GracePeriod() const { return GracePeriod_; };
|
||||
inline uint64_t LingerPeriod() const { return LingerPeriod_; }
|
||||
|
||||
private:
|
||||
uint64_t GracePeriod_ = 60 * 60;
|
||||
uint64_t LingerPeriod_ = 24 * 60 * 60;
|
||||
|
||||
Signup() noexcept:
|
||||
SubSystemServer("SignupServer", "SIGNUP", "signup")
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
inline auto Signup() { return Signup::instance(); }
|
||||
|
||||
}
|
||||
@@ -86,6 +86,8 @@ using namespace std::chrono_literals;
|
||||
|
||||
namespace OpenWifi {
|
||||
|
||||
inline uint64_t Now() { return std::time(nullptr); };
|
||||
|
||||
enum UNAUTHORIZED_REASON {
|
||||
SUCCESS=0,
|
||||
PASSWORD_CHANGE_REQUIRED,
|
||||
|
||||
@@ -466,9 +466,10 @@ namespace ORM {
|
||||
return false;
|
||||
}
|
||||
|
||||
typedef std::vector<RecordTuple> RecordList;
|
||||
typedef std::vector<RecordTuple> RecordList;
|
||||
typedef std::vector<RecordType> RecordVec;
|
||||
|
||||
bool GetRecords( uint64_t Offset, uint64_t HowMany, std::vector<RecordType> & Records, const std::string & Where = "", const std::string & OrderBy = "") {
|
||||
bool GetRecords( uint64_t Offset, uint64_t HowMany, RecordVec & Records, const std::string & Where = "", const std::string & OrderBy = "") {
|
||||
try {
|
||||
Poco::Data::Session Session = Pool_.get();
|
||||
Poco::Data::Statement Select(Session);
|
||||
|
||||
@@ -67,6 +67,9 @@ namespace OpenWifi::RESTAPI::Errors {
|
||||
static const std::string SMSCouldNotBeSentRetry{"SMS could not be sent to validate device, try later or change the phone number."};
|
||||
static const std::string SMSCouldNotValidate{"Code and number could not be validated"};
|
||||
static const std::string InvalidDeviceClass{"Invalid device class. Must be: any, venue, entity, or subscriber"};
|
||||
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."};
|
||||
}
|
||||
|
||||
namespace OpenWifi::RESTAPI::Protocol {
|
||||
@@ -214,6 +217,9 @@ namespace OpenWifi::uCentralProtocol {
|
||||
static const char * FIRMWARE = "firmware";
|
||||
static const char * CONNECT = "connect";
|
||||
static const char * STATE = "state";
|
||||
static const char * STATUS = "status";
|
||||
static const char * ERROR = "error";
|
||||
static const char * TEXT = "text";
|
||||
static const char * HEALTHCHECK = "healthcheck";
|
||||
static const char * LOG = "log";
|
||||
static const char * CRASHLOG = "crashlog";
|
||||
|
||||
@@ -23,7 +23,8 @@ namespace OpenWifi {
|
||||
ORM::Field{"userId",ORM::FieldType::FT_TEXT},
|
||||
ORM::Field{"serialNumber",ORM::FieldType::FT_TEXT},
|
||||
ORM::Field{"created",ORM::FieldType::FT_BIGINT},
|
||||
ORM::Field{"completed",ORM::FieldType::FT_BIGINT}
|
||||
ORM::Field{"completed",ORM::FieldType::FT_BIGINT},
|
||||
ORM::Field{"status",ORM::FieldType::FT_TEXT}
|
||||
};
|
||||
|
||||
const static ORM::IndexVec SignupDB_Indexes{
|
||||
@@ -51,6 +52,7 @@ template<> void ORM::DB< OpenWifi::SignupDBRecordType, OpenWifi::ProvObjects:
|
||||
Out.serialNumber = In.get<8>();
|
||||
Out.created = In.get<9>();
|
||||
Out.completed = In.get<10>();
|
||||
Out.status = In.get<11>();
|
||||
}
|
||||
|
||||
template<> void ORM::DB< OpenWifi::SignupDBRecordType, OpenWifi::ProvObjects::SignupEntry>::Convert(const OpenWifi::ProvObjects::SignupEntry &In, OpenWifi::SignupDBRecordType &Out) {
|
||||
@@ -65,4 +67,5 @@ template<> void ORM::DB< OpenWifi::SignupDBRecordType, OpenWifi::ProvObjects:
|
||||
Out.set<8>(In.serialNumber);
|
||||
Out.set<9>(In.created);
|
||||
Out.set<10>(In.created);
|
||||
Out.set<11>(In.status);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,8 @@ namespace OpenWifi {
|
||||
std::string,
|
||||
std::string,
|
||||
uint64_t,
|
||||
uint64_t
|
||||
uint64_t,
|
||||
std::string
|
||||
> SignupDBRecordType;
|
||||
|
||||
class SignupDB : public ORM::DB<SignupDBRecordType, ProvObjects::SignupEntry> {
|
||||
|
||||
Reference in New Issue
Block a user