mirror of
https://github.com/Telecominfraproject/wlan-cloud-owprov.git
synced 2025-10-29 09:42:38 +00:00
Adding Signup
This commit is contained in:
@@ -2577,6 +2577,72 @@ paths:
|
|||||||
$ref: '#/components/responses/NotFound'
|
$ref: '#/components/responses/NotFound'
|
||||||
|
|
||||||
/signup:
|
/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:
|
post:
|
||||||
tags:
|
tags:
|
||||||
- Subscriber Registration
|
- Subscriber Registration
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ namespace OpenWifi {
|
|||||||
}, Body, 30000);
|
}, Body, 30000);
|
||||||
|
|
||||||
Poco::JSON::Object::Ptr Answer;
|
Poco::JSON::Object::Ptr Answer;
|
||||||
if(CreateUser.Do(Answer)) {
|
if(CreateUser.Do(Answer) == Poco::Net::HTTPServerResponse::HTTP_OK) {
|
||||||
SecurityObjects::UserInfo UI;
|
SecurityObjects::UserInfo UI;
|
||||||
|
|
||||||
UI.from_json(Answer);
|
UI.from_json(Answer);
|
||||||
@@ -90,6 +90,7 @@ namespace OpenWifi {
|
|||||||
|
|
||||||
std::cout << "Creating signup entry: " << SE.email << std::endl;
|
std::cout << "Creating signup entry: " << SE.email << std::endl;
|
||||||
StorageService()->SignupDB().CreateRecord(SE);
|
StorageService()->SignupDB().CreateRecord(SE);
|
||||||
|
Signup()->AddOutstandingSignup(SE);
|
||||||
|
|
||||||
// We do not have a device, so let's create one.
|
// We do not have a device, so let's create one.
|
||||||
if(IT.serialNumber.empty()) {
|
if(IT.serialNumber.empty()) {
|
||||||
@@ -103,9 +104,9 @@ namespace OpenWifi {
|
|||||||
StateDoc.set("errorCode",0);
|
StateDoc.set("errorCode",0);
|
||||||
StateDoc.set("date", OpenWifi::Now());
|
StateDoc.set("date", OpenWifi::Now());
|
||||||
StateDoc.set("status", "waiting for email-verification");
|
StateDoc.set("status", "waiting for email-verification");
|
||||||
std::ostringstream os;
|
std::ostringstream os2;
|
||||||
StateDoc.stringify(os);
|
StateDoc.stringify(os2);
|
||||||
IT.state = os.str();
|
IT.state = os2.str();
|
||||||
std::cout << "Creating inventory entry: " << SE.serialNumber << std::endl;
|
std::cout << "Creating inventory entry: " << SE.serialNumber << std::endl;
|
||||||
StorageService()->InventoryDB().CreateRecord(IT);
|
StorageService()->InventoryDB().CreateRecord(IT);
|
||||||
} else {
|
} else {
|
||||||
@@ -116,9 +117,9 @@ namespace OpenWifi {
|
|||||||
StateDoc.set("errorCode",0);
|
StateDoc.set("errorCode",0);
|
||||||
StateDoc.set("date", OpenWifi::Now());
|
StateDoc.set("date", OpenWifi::Now());
|
||||||
StateDoc.set("status", "waiting for email-verification");
|
StateDoc.set("status", "waiting for email-verification");
|
||||||
std::ostringstream os;
|
std::ostringstream os2;
|
||||||
StateDoc.stringify(os);
|
StateDoc.stringify(os2);
|
||||||
IT.state = os.str();
|
IT.state = os2.str();
|
||||||
IT.info.modified = OpenWifi::Now();
|
IT.info.modified = OpenWifi::Now();
|
||||||
std::cout << "Updating inventory entry: " << SE.serialNumber << std::endl;
|
std::cout << "Updating inventory entry: " << SE.serialNumber << std::endl;
|
||||||
StorageService()->InventoryDB().UpdateRecord("id",IT.info.id,IT);
|
StorageService()->InventoryDB().UpdateRecord("id",IT.info.id,IT);
|
||||||
@@ -151,13 +152,48 @@ namespace OpenWifi {
|
|||||||
|
|
||||||
SE.info.modified = OpenWifi::Now();
|
SE.info.modified = OpenWifi::Now();
|
||||||
SE.status = "emailVerified";
|
SE.status = "emailVerified";
|
||||||
|
|
||||||
StorageService()->SignupDB().UpdateRecord("id", SE.info.id, SE);
|
StorageService()->SignupDB().UpdateRecord("id", SE.info.id, SE);
|
||||||
|
Signup()->AddOutstandingSignup(SE);
|
||||||
|
|
||||||
Poco::JSON::Object Answer;
|
Poco::JSON::Object Answer;
|
||||||
SE.to_json(Answer);
|
SE.to_json(Answer);
|
||||||
|
|
||||||
return ReturnObject(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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -14,7 +14,9 @@ namespace OpenWifi {
|
|||||||
std::vector<std::string>{
|
std::vector<std::string>{
|
||||||
Poco::Net::HTTPRequest::HTTP_POST,
|
Poco::Net::HTTPRequest::HTTP_POST,
|
||||||
Poco::Net::HTTPRequest::HTTP_OPTIONS,
|
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,
|
Server,
|
||||||
TransactionId,
|
TransactionId,
|
||||||
Internal, false, true ){}
|
Internal, false, true ){}
|
||||||
@@ -29,10 +31,10 @@ namespace OpenWifi {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
void DoGet() final {};
|
void DoGet() final;
|
||||||
void DoPost() final;
|
void DoPost() final;
|
||||||
void DoPut() final ;
|
void DoPut() final ;
|
||||||
void DoDelete() final {};
|
void DoDelete() final;
|
||||||
private:
|
private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include "Signup.h"
|
#include "Signup.h"
|
||||||
|
#include "StorageService.h"
|
||||||
|
|
||||||
namespace OpenWifi {
|
namespace OpenWifi {
|
||||||
|
|
||||||
@@ -10,11 +11,71 @@ namespace OpenWifi {
|
|||||||
GracePeriod_ = MicroService::instance().ConfigGetInt("signup.graceperiod", 60*60);
|
GracePeriod_ = MicroService::instance().ConfigGetInt("signup.graceperiod", 60*60);
|
||||||
LingerPeriod_ = MicroService::instance().ConfigGetInt("signup.lingerperiod", 24*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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Signup::Stop() {
|
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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
32
src/Signup.h
32
src/Signup.h
@@ -5,10 +5,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "framework/MicroService.h"
|
#include "framework/MicroService.h"
|
||||||
|
#include "RESTObjects/RESTAPI_ProvObjects.h"
|
||||||
|
|
||||||
namespace OpenWifi {
|
namespace OpenWifi {
|
||||||
|
|
||||||
class Signup : public SubSystemServer {
|
class Signup : public SubSystemServer, Poco::Runnable {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static auto instance() {
|
static auto instance() {
|
||||||
@@ -18,13 +19,38 @@ namespace OpenWifi {
|
|||||||
|
|
||||||
int Start() override;
|
int Start() override;
|
||||||
void Stop() override;
|
void Stop() override;
|
||||||
|
void run() final;
|
||||||
|
|
||||||
inline uint64_t GracePeriod() const { return GracePeriod_; };
|
inline uint64_t GracePeriod() const { return GracePeriod_; };
|
||||||
inline uint64_t LingerPeriod() const { return LingerPeriod_; }
|
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:
|
private:
|
||||||
uint64_t GracePeriod_ = 60 * 60;
|
uint64_t GracePeriod_ = 60 * 60;
|
||||||
uint64_t LingerPeriod_ = 24 * 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:
|
Signup() noexcept:
|
||||||
SubSystemServer("SignupServer", "SIGNUP", "signup")
|
SubSystemServer("SignupServer", "SIGNUP", "signup")
|
||||||
|
|||||||
@@ -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 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 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 UserAlreadyExists{"Username already exists."};
|
||||||
|
static const std::string NotImplemented{"Function not implemented."};
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace OpenWifi::RESTAPI::Protocol {
|
namespace OpenWifi::RESTAPI::Protocol {
|
||||||
|
|||||||
@@ -24,7 +24,8 @@ namespace OpenWifi {
|
|||||||
ORM::Field{"serialNumber",ORM::FieldType::FT_TEXT},
|
ORM::Field{"serialNumber",ORM::FieldType::FT_TEXT},
|
||||||
ORM::Field{"submitted",ORM::FieldType::FT_BIGINT},
|
ORM::Field{"submitted",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}
|
ORM::Field{"status",ORM::FieldType::FT_TEXT},
|
||||||
|
ORM::Field{"error",ORM::FieldType::FT_BIGINT}
|
||||||
};
|
};
|
||||||
|
|
||||||
const static ORM::IndexVec SignupDB_Indexes{
|
const static ORM::IndexVec SignupDB_Indexes{
|
||||||
@@ -34,10 +35,19 @@ namespace OpenWifi {
|
|||||||
ORM::Indextype::ASC} } }
|
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") {
|
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) {
|
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.submitted = In.get<9>();
|
||||||
Out.completed = In.get<10>();
|
Out.completed = In.get<10>();
|
||||||
Out.status = In.get<11>();
|
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) {
|
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<9>(In.submitted);
|
||||||
Out.set<10>(In.completed);
|
Out.set<10>(In.completed);
|
||||||
Out.set<11>(In.status);
|
Out.set<11>(In.status);
|
||||||
|
Out.set<12>(In.error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,12 +20,14 @@ namespace OpenWifi {
|
|||||||
std::string,
|
std::string,
|
||||||
uint64_t,
|
uint64_t,
|
||||||
uint64_t,
|
uint64_t,
|
||||||
std::string
|
std::string,
|
||||||
|
uint64_t
|
||||||
> SignupDBRecordType;
|
> SignupDBRecordType;
|
||||||
|
|
||||||
class SignupDB : public ORM::DB<SignupDBRecordType, ProvObjects::SignupEntry> {
|
class SignupDB : public ORM::DB<SignupDBRecordType, ProvObjects::SignupEntry> {
|
||||||
public:
|
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:
|
private:
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -462,7 +462,7 @@ affecteddevices() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
signup() {
|
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 "Content-Type: application/json" \
|
||||||
-H "Authorization: Bearer ${token}" \
|
-H "Authorization: Bearer ${token}" \
|
||||||
-H "accept: application/json" > ${result_file}
|
-H "accept: application/json" > ${result_file}
|
||||||
|
|||||||
Reference in New Issue
Block a user