Initial checkin for username creation

This commit is contained in:
stephb9959
2021-07-08 19:23:29 -07:00
parent 23cf3447c7
commit d3ca22b18e
24 changed files with 1095 additions and 861 deletions

View File

@@ -64,7 +64,6 @@ add_executable( ucentralsec
src/AuthService.h src/AuthService.cpp
src/KafkaManager.h src/KafkaManager.cpp
src/StorageService.cpp src/StorageService.h
src/storage_identity.cpp
src/Utils.cpp src/Utils.h
src/storage_sqlite.cpp src/storage_odbc.cpp src/storage_sqlite.cpp src/storage_pgql.cpp src/storage_mysql.cpp
src/storage_tables.cpp src/SMTPMailerService.cpp src/SMTPMailerService.h

View File

@@ -35,37 +35,6 @@ components:
content:
application/json:
schema:
$ref: '#/components/schemas/GenericErrorResponse'
Unauthorized:
description: The requested does not have sufficient rights to perform the operation.
content:
application/json:
schema:
$ref: '#/components/schemas/GenericErrorResponse'
Success:
description: The requested operation was performed.
content:
application/json:
schema:
$ref: '#/components/schemas/GenericGoodAnswer'
CommandSubmitSuccess:
description: The command was submitted succesfully.
content:
application/json:
schema:
properties:
serialNumber:
type: string
UUID:
type: string
format: uuid
schemas:
GenericErrorResponse:
description: Typical error response
properties:
ErrorCode:
type: integer
@@ -74,8 +43,24 @@ components:
ErrorDescription:
type: string
GenericGoodAnswer:
description: used for all succesful responses.
Unauthorized:
description: The requested does not have sufficient rights to perform the operation.
content:
application/json:
schema:
properties:
ErrorCode:
type: integer
ErrorDetails:
type: string
ErrorDescription:
type: string
Success:
description: The requested operation was performed.
content:
application/json:
schema:
properties:
Operation:
type: string
@@ -84,6 +69,8 @@ components:
Code:
type: integer
schemas:
WebTokenRequest:
description: User Id and password.
type: object
@@ -97,25 +84,6 @@ components:
password:
type: string
default: support
refreshToken:
type: string
example:
userId: support@example.com
password: support
WebTokenRequestChangePassword:
description: User Id and password.
type: object
required:
- userId
- password
properties:
userId:
type: string
default: support@example.com
oldPassword:
type: string
default: support
newPassword:
type: string
default: support
@@ -148,6 +116,8 @@ components:
format: int64
userMustChangePassword:
type: boolean
errorCode:
type: integer # 0 = no error, 1 = passwordAlreadyUsed, 2=invalidPassword
aclTemplate:
$ref: '#/components/schemas/WebTokenAclTemplate'
@@ -230,8 +200,8 @@ components:
type: object
properties:
id:
type: integer
format: int64
type: string
format: uuid
name:
type: string
description:
@@ -241,10 +211,12 @@ components:
format: uri
email:
type: string
format: email
validated:
type: boolean
validationEmail:
type: string
format: email
validationDate:
type: integer
format: int64
@@ -319,7 +291,7 @@ components:
UserList:
type: object
properties:
list:
users:
type: array
items:
$ref: '#/components/schemas/UserInfo'
@@ -401,6 +373,7 @@ components:
access:
type: string
enum:
- NONE
- READ
- MODIFY
- DELETE
@@ -482,7 +455,7 @@ paths:
operationId: getAccessToken
parameters:
- in: query
name: changePassword
name: newPassword
schema:
type: string
required: false
@@ -492,9 +465,7 @@ paths:
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/WebTokenRequestChangePassword'
- $ref: '#/components/schemas/WebTokenRequest'
$ref: '#/components/schemas/WebTokenRequest'
responses:
200:
description: successful operation
@@ -526,7 +497,7 @@ paths:
content:
application/json:
schema:
$ref: '#/components/schemas/GenericGoodAnswer'
$ref: '#/components/responses/Success'
403:
$ref: '#/components/responses/Unauthorized'
404:
@@ -593,8 +564,8 @@ paths:
- in: path
name: id
schema:
type: integer
format: int64
type: string
format: uuid
required: true
responses:
200:

View File

@@ -154,16 +154,6 @@ namespace uCentral {
UInfo.webtoken.expires_in_ = Expires.epochTime() - IssuedAt.epochTime();
UInfo.webtoken.idle_timeout_ = 5*60;
if(Storage()->GetIdentityRights(Identity, UInfo.webtoken.acl_template_)) {
} else {
// we can get in but we have no given rights... something is very wrong
UInfo.webtoken.acl_template_.Read_ = true ;
UInfo.webtoken.acl_template_.ReadWriteCreate_ =
UInfo.webtoken.acl_template_.ReadWrite_ =
UInfo.webtoken.acl_template_.Delete_ = false;
UInfo.webtoken.acl_template_.PortalLogin_ = true;
}
UserCache_[UInfo.webtoken.access_token_] = UInfo;
return true;
@@ -180,6 +170,9 @@ namespace uCentral {
SubMutexGuard Guard(Mutex_);
std::string Token = GenerateToken(UserName,USERNAME,30);
SecurityObjects::AclTemplate ACL;
ACL.PortalLogin_ = ACL.Read_ = ACL.ReadWrite_ = ACL.ReadWriteCreate_ = ACL.Delete_ = true;
UInfo.webtoken.acl_template_ = ACL;
UInfo.webtoken.expires_in_ = 30 * 24 * 60 * 60 ;
UInfo.webtoken.idle_timeout_ = 5 * 60;
UInfo.webtoken.token_type_ = "Bearer";
@@ -188,17 +181,59 @@ namespace uCentral {
UInfo.webtoken.refresh_token_ = Token;
UInfo.webtoken.created_ = time(nullptr);
UInfo.webtoken.username_ = UserName;
UInfo.webtoken.errorCode = 0;
UInfo.webtoken.userMustChangePassword = false;
UserCache_[Token] = UInfo;
}
bool AuthService::Authorize( const std::string & UserName, const std::string & Password, SecurityObjects::UserInfoAndPolicy & UInfo )
bool AuthService::SetPassword(const std::string &NewPassword, SecurityObjects::UserInfo & UInfo) {
auto NewPasswordHash = ComputePasswordHash(UInfo.email, NewPassword);
for (auto const &i:UInfo.lastPasswords) {
if (i == NewPasswordHash) {
return false;
}
}
if(UInfo.lastPasswords.size()==5) {
UInfo.lastPasswords.erase(UInfo.lastPasswords.begin());
}
UInfo.lastPasswords.push_back(NewPasswordHash);
UInfo.currentPassword = NewPasswordHash;
return true;
}
bool AuthService::Authorize( std::string & UserName, const std::string & Password, const std::string & NewPassword, SecurityObjects::UserInfoAndPolicy & UInfo )
{
SubMutexGuard Guard(Mutex_);
SecurityObjects::AclTemplate ACL;
if(Mechanism_=="internal")
{
Poco::toLowerInPlace(UserName);
auto PasswordHash = ComputePasswordHash(UserName, Password);
if(Storage()->GetUserByEmail(UserName,UInfo.userinfo)) {
if(PasswordHash != UInfo.userinfo.currentPassword) {
return false;
}
if(UInfo.userinfo.changePassword && NewPassword.empty()) {
UInfo.webtoken.userMustChangePassword = true ;
return true;
}
if(UInfo.userinfo.changePassword || !NewPassword.empty()) {
if(!SetPassword(NewPassword,UInfo.userinfo)) {
UInfo.webtoken.errorCode = 1;
return true;
}
UInfo.userinfo.lastPasswordChange = std::time(nullptr);
UInfo.userinfo.changePassword = false;
Storage()->UpdateUserInfo(AUTHENTICATION_SYSTEM, UInfo.userinfo.Id,UInfo.userinfo);
}
// so we have a good password, password up date has taken place if need be, now generate the token.
CreateToken(UserName, UInfo );
return true;
}
if(((UserName == DefaultUserName_) && (DefaultPassword_== ComputePasswordHash(UserName,Password))) || !Secure_)
{
ACL.PortalLogin_ = ACL.Read_ = ACL.ReadWrite_ = ACL.ReadWriteCreate_ = ACL.Delete_ = true;
@@ -209,15 +244,6 @@ namespace uCentral {
CreateToken(UserName, UInfo );
return true;
}
} else if (Mechanism_=="db") {
auto PasswordHash = ComputePasswordHash(UserName, Password);
std::string TUser{UserName};
if(Storage()->GetIdentity(TUser,PasswordHash,USERNAME,ACL)) {
CreateToken(UserName, UInfo);
return true;
}
}
return false;
}
@@ -228,7 +254,6 @@ namespace uCentral {
}
bool AuthService::IsValidToken(const std::string &Token, SecurityObjects::WebToken &WebToken, SecurityObjects::UserInfo &UserInfo) {
return true;
}

View File

@@ -21,6 +21,8 @@
namespace uCentral{
static const std::string AUTHENTICATION_SYSTEM{"SYSTEM"};
class AuthService : public SubSystemServer {
public:
@@ -44,9 +46,10 @@ namespace uCentral{
void Stop() override;
[[nodiscard]] bool IsAuthorized(Poco::Net::HTTPServerRequest & Request,std::string &SessionToken, SecurityObjects::UserInfoAndPolicy & UInfo );
[[nodiscard]] bool Authorize( const std::string & UserName, const std::string & Password, SecurityObjects::UserInfoAndPolicy & UInfo );
[[nodiscard]] bool Authorize( std::string & UserName, const std::string & Password, const std::string & NewPassword, SecurityObjects::UserInfoAndPolicy & UInfo );
void CreateToken(const std::string & UserName, SecurityObjects::UserInfoAndPolicy &UInfo);
[[nodiscard]] bool ValidateToken(const std::string & Token, std::string & SessionToken, SecurityObjects::UserInfoAndPolicy & UserInfo );
[[nodiscard]] bool SetPassword(const std::string &Password, SecurityObjects::UserInfo & UInfo);
void Logout(const std::string &token);

View File

@@ -25,6 +25,56 @@ namespace uCentral::SecurityObjects {
field_to_json(Obj,"PortalLogin",PortalLogin_);
}
ResourceAccessType ResourceAccessTypeFromString(const std::string &s) {
if(s=="READ") return READ;
if(s=="MODIFY") return MODIFY;
if(s=="DELETE") return DELETE;
if(s=="CREATE") return CREATE;
if(s=="TEST") return TEST;
if(s=="MOVE") return MOVE;
return NONE;
}
std::string ResourceAccessTypeToString(const ResourceAccessType & T) {
switch(T) {
case READ: return "READ";
case MODIFY: return "MODIFY";
case DELETE: return "DELETE";
case CREATE: return "CREATE";
case TEST: return "TEST";
case MOVE: return "MOVE";
default: return "NONE";
}
}
USER_ROLE UserTypeFromString(const std::string &U) {
if (U=="root")
return ROOT;
else if (U=="admin")
return ADMIN;
else if (U=="subscriber")
return SUBSCRIBER;
else if (U=="csr")
return CSR;
else if (U=="system")
return SYSTEM;
else if (U=="special")
return SPECIAL;
return UNKNOWN;
}
std::string UserTypeToString(USER_ROLE U) {
switch(U) {
case UNKNOWN: return "unknown";
case ROOT: return "root";
case SUBSCRIBER: return "subscriber";
case CSR: return "csr";
case SYSTEM: return "system";
case SPECIAL: return "special";
default: return "unknown";
}
}
bool AclTemplate::from_json(const Poco::JSON::Object::Ptr &Obj) {
try {
field_from_json(Obj, "Read", Read_);
@@ -48,6 +98,8 @@ namespace uCentral::SecurityObjects {
field_to_json(Obj,"idle_timeout",idle_timeout_);
field_to_json(Obj,"created",created_);
field_to_json(Obj,"username",username_);
field_to_json(Obj,"userMustChangePassword",userMustChangePassword);
field_to_json(Obj,"errorCode", errorCode);
Obj.set("aclTemplate",AclTemplateObj);
}
@@ -64,6 +116,7 @@ namespace uCentral::SecurityObjects {
field_from_json(Obj, "idle_timeout", idle_timeout_);
field_from_json(Obj, "created", created_);
field_from_json(Obj, "username", username_);
field_from_json(Obj, "userMustChangePassword",userMustChangePassword);
return true;
} catch (...) {
@@ -94,7 +147,7 @@ namespace uCentral::SecurityObjects {
field_to_json(Obj,"owner", owner);
field_to_json(Obj,"suspended", suspended);
field_to_json(Obj,"blackListed", blackListed);
field_to_json(Obj,"userRole", userRole);
field_to_json<USER_ROLE>(Obj,"userRole", userRole, UserTypeToString);
field_to_json(Obj,"userTypeProprietaryInfo", userTypeProprietaryInfo);
field_to_json(Obj,"securityPolicy", securityPolicy);
field_to_json(Obj,"securityPolicyChange", securityPolicyChange);
@@ -116,7 +169,7 @@ namespace uCentral::SecurityObjects {
field_from_json(Obj,"currentLoginURI",currentLoginURI);
field_from_json(Obj,"locale",locale);
field_from_json(Obj,"notes",notes);
field_from_json(Obj,"userRole",userRole);
field_from_json<USER_ROLE>(Obj,"userRole",userRole, UserTypeFromString);
field_from_json(Obj,"securityPolicy",securityPolicy);
field_from_json(Obj,"userTypeProprietaryInfo",userTypeProprietaryInfo);
field_from_json(Obj,"validationDate",validationDate);
@@ -249,5 +302,55 @@ namespace uCentral::SecurityObjects {
return false;
}
void ProfileAction::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"resource", resource);
field_to_json<ResourceAccessType>(Obj,"access", access, ResourceAccessTypeToString);
}
bool ProfileAction::from_json(Poco::JSON::Object::Ptr Obj) {
try {
field_from_json(Obj,"resource",resource);
field_from_json<ResourceAccessType>(Obj,"access",access,ResourceAccessTypeFromString );
} catch(...) {
}
return false;
}
void SecurityProfile::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj,"id", id);
field_to_json(Obj,"name", name);
field_to_json(Obj,"description", description);
field_to_json(Obj,"policy", policy);
field_to_json(Obj,"role", role);
field_to_json(Obj,"notes", notes);
}
bool SecurityProfile::from_json(Poco::JSON::Object::Ptr Obj) {
try {
field_from_json(Obj,"id",id);
field_from_json(Obj,"name",name);
field_from_json(Obj,"description",description);
field_from_json(Obj,"policy",policy);
field_from_json(Obj,"role",role);
field_from_json(Obj,"notes",notes);
} catch(...) {
}
return false;
}
void SecurityProfileList::to_json(Poco::JSON::Object &Obj) const {
field_to_json(Obj, "profiles", profiles);
}
bool SecurityProfileList::from_json(Poco::JSON::Object::Ptr Obj) {
try {
field_from_json(Obj,"profiles",profiles);
} catch(...) {
}
return false;
}
}

View File

@@ -30,15 +30,34 @@ namespace uCentral::SecurityObjects {
std::string id_token_;
std::string token_type_;
std::string username_;
uint64_t expires_in_;
uint64_t idle_timeout_;
bool userMustChangePassword=false;
uint64_t errorCode=0;
uint64_t expires_in_=0;
uint64_t idle_timeout_=0;
AclTemplate acl_template_;
uint64_t created_;
uint64_t created_=0;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
enum AUTH_ERROR {
SUCCESS,
PASSWORD_CHANGE_REQUIRED,
PASSWORD_DOES_NOT_MATCH,
PASSWORD_ALREADY_USED,
USERNAME_PENDING_VERIFICATION,
PASSWORD_INVALID,
INTERNAL_ERROR
};
enum USER_ROLE {
UNKNOWN, ROOT, ADMIN, SUBSCRIBER, CSR, SYSTEM, SPECIAL
};
USER_ROLE UserTypeFromString(const std::string &U);
std::string UserTypeToString(USER_ROLE U);
struct NoteInfo {
uint64_t created = std::time(nullptr);
std::string createdBy;
@@ -49,7 +68,7 @@ namespace uCentral::SecurityObjects {
typedef std::vector<NoteInfo> NoteInfoVec;
struct UserInfo {
uint64_t Id = 0;
std::string Id;
std::string name;
std::string description;
std::string avatar;
@@ -59,7 +78,7 @@ namespace uCentral::SecurityObjects {
uint64_t validationDate = 0;
uint64_t creationDate = 0;
std::string validationURI;
bool changePassword = true;
bool changePassword = false;
uint64_t lastLogin = 0;
std::string currentLoginURI;
uint64_t lastPasswordChange = 0;
@@ -71,11 +90,10 @@ namespace uCentral::SecurityObjects {
std::string owner;
bool suspended = false;
bool blackListed = false;
std::string userRole;
USER_ROLE userRole;
std::string userTypeProprietaryInfo;
std::string securityPolicy;
uint64_t securityPolicyChange;
uint64_t securityPolicyChange = 0 ;
std::string currentPassword;
Types::StringVec lastPasswords;
std::string oauthType;
@@ -84,6 +102,41 @@ namespace uCentral::SecurityObjects {
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
typedef std::vector<UserInfo> UserInfoVec;
struct InternalServiceInfo {
std::string privateURI;
std::string publicURI;
std::string token;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
typedef std::vector<InternalServiceInfo> InternalServiceInfoVec;
struct InternalSystemServices {
std::string key;
std::string version;
InternalServiceInfoVec services;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct SystemEndpoint {
std::string type;
uint64_t id = 0;
std::string vendor;
std::string uri;
std::string authenticationType;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
typedef std::vector<SystemEndpoint> SystemEndpointVec;
struct SystemEndpointList {
SystemEndpointVec endpoints;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
struct UserInfoAndPolicy {
WebToken webtoken;
@@ -91,41 +144,46 @@ namespace uCentral::SecurityObjects {
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
typedef std::map<std::string,SecurityObjects::UserInfoAndPolicy> UserInfoCache;
struct InternalServiceInfo {
std::string privateURI;
std::string publicURI;
std::string token;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
enum ResourceAccessType {
NONE,
READ,
MODIFY,
DELETE,
CREATE,
TEST,
MOVE
};
struct InternalSystemServices {
std::string key;
std::string version;
std::vector<InternalServiceInfo> services;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
};
ResourceAccessType ResourceAccessTypeFromString(const std::string &s);
std::string ResourceAccessTypeToString(const ResourceAccessType & T);
struct SystemEndpoint {
std::string type;
struct ProfileAction {
std::string resource;
ResourceAccessType access;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(Poco::JSON::Object::Ptr Obj);
};
typedef std::vector<ProfileAction> ProfileActionVec;
struct SecurityProfile {
uint64_t id;
std::string vendor;
std::string uri;
std::string authenticationType;
std::string name;
std::string description;
ProfileActionVec policy;
std::string role;
NoteInfoVec notes;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
bool from_json(Poco::JSON::Object::Ptr Obj);
};
typedef std::vector<SecurityProfile> SecurityProfileVec;
struct SystemEndpointList {
std::vector<SystemEndpoint> endpoints;
struct SecurityProfileList {
SecurityProfileVec profiles;
void to_json(Poco::JSON::Object &Obj) const;
bool from_json(const Poco::JSON::Object::Ptr &Obj);
bool from_json(Poco::JSON::Object::Ptr Obj);
};
}
#endif //UCENTRAL_RESTAPI_SECURITYOBJECTS_H

View File

@@ -45,7 +45,7 @@ namespace uCentral {
if (PathItems[i] != ParamItems[i]) {
if (ParamItems[i][0] == '{') {
auto ParamName = ParamItems[i].substr(1, ParamItems[i].size() - 2);
bindings[ParamName] = PathItems[i];
bindings[Poco::toLower(ParamName)] = PathItems[i];
} else {
Matched = false;
}
@@ -111,8 +111,7 @@ namespace uCentral {
}
const std::string &RESTAPIHandler::GetBinding(const std::string &Name, const std::string &Default) {
auto E = Bindings_.find(Name);
auto E = Bindings_.find(Poco::toLower(Name));
if (E == Bindings_.end())
return Default;
@@ -121,7 +120,6 @@ namespace uCentral {
static std::string MakeList(const std::vector<std::string> &L) {
std::string Return;
for (const auto &i : L)
if (Return.empty())
Return = i;
@@ -184,27 +182,53 @@ namespace uCentral {
}
void RESTAPIHandler::BadRequest(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
Poco::Net::HTTPServerResponse &Response,
const std::string & Reason) {
PrepareResponse(Request, Response, Poco::Net::HTTPResponse::HTTP_BAD_REQUEST);
Response.send();
Poco::JSON::Object ErrorObject;
ErrorObject.set("ErrorCode",500);
ErrorObject.set("ErrorDetails",Request.getMethod());
ErrorObject.set("ErrorDescription",Reason.empty() ? "Command is missing parameters or wrong values." : Reason) ;
std::ostream &Answer = Response.send();
Poco::JSON::Stringifier::stringify(ErrorObject, Answer);
}
void RESTAPIHandler::UnAuthorized(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
PrepareResponse(Request, Response, Poco::Net::HTTPResponse::HTTP_FORBIDDEN);
Response.send();
Poco::JSON::Object ErrorObject;
ErrorObject.set("ErrorCode",403);
ErrorObject.set("ErrorDetails",Request.getMethod());
ErrorObject.set("ErrorDescription","You do not have access to this resource.");
std::ostream &Answer = Response.send();
Poco::JSON::Stringifier::stringify(ErrorObject, Answer);
}
void RESTAPIHandler::NotFound(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
PrepareResponse(Request, Response, Poco::Net::HTTPResponse::HTTP_NOT_FOUND);
Response.send();
Poco::JSON::Object ErrorObject;
ErrorObject.set("ErrorCode",404);
ErrorObject.set("ErrorDetails",Request.getMethod());
ErrorObject.set("ErrorDescription","This resource does not exist.");
std::ostream &Answer = Response.send();
Poco::JSON::Stringifier::stringify(ErrorObject, Answer);
}
void RESTAPIHandler::OK(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response) {
PrepareResponse(Request, Response);
if( Request.getMethod()==Poco::Net::HTTPRequest::HTTP_DELETE ||
Request.getMethod()==Poco::Net::HTTPRequest::HTTP_OPTIONS) {
Response.send();
} else {
Poco::JSON::Object ErrorObject;
ErrorObject.set("Code", 0);
ErrorObject.set("Operation", Request.getMethod());
ErrorObject.set("Details", "Command completed.");
std::ostream &Answer = Response.send();
Poco::JSON::Stringifier::stringify(ErrorObject, Answer);
}
}
void RESTAPIHandler::SendFile(Poco::File & File, const std::string & UUID, Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) {

View File

@@ -30,6 +30,7 @@ namespace uCentral {
std::string SerialNumber, Filter, Select;
bool Lifetime=false, LastOnly=false, Newest=false;
};
typedef std::map<std::string, std::string> BindingMap;
RESTAPIHandler(BindingMap map, Poco::Logger &l, std::vector<std::string> Methods)
@@ -61,7 +62,7 @@ namespace uCentral {
std::string GetParameter(const std::string &Name, const std::string &Default);
bool GetBoolParameter(const std::string &Name, bool Default);
void BadRequest(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response);
void BadRequest(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response, const std::string &Reason = "");
void UnAuthorized(Poco::Net::HTTPServerRequest &Request,
Poco::Net::HTTPServerResponse &Response);
void ReturnObject(Poco::Net::HTTPServerRequest &Request, Poco::JSON::Object &Object,

View File

@@ -11,6 +11,7 @@
#include "AuthService.h"
#include "RESTAPI_oauth2Handler.h"
#include "RESTAPI_protocol.h"
#include "Utils.h"
namespace uCentral {
void RESTAPI_oauth2Handler::handleRequest(Poco::Net::HTTPServerRequest &Request,
@@ -21,19 +22,18 @@ namespace uCentral {
try {
if (Request.getMethod() == Poco::Net::HTTPServerRequest::HTTP_POST) {
// Extract the info for login...
Poco::JSON::Parser parser;
Poco::JSON::Object::Ptr Obj =
parser.parse(Request.stream()).extract<Poco::JSON::Object::Ptr>();
Poco::JSON::Object::Ptr Obj = parser.parse(Request.stream()).extract<Poco::JSON::Object::Ptr>();
auto userId = GetS(uCentral::RESTAPI::Protocol::USERID, Obj);
auto password = GetS(uCentral::RESTAPI::Protocol::PASSWORD, Obj);
auto newPassword = GetS(uCentral::RESTAPI::Protocol::NEWPASSWORD, Obj);
Poco::toLowerInPlace(userId);
SecurityObjects::UserInfoAndPolicy UInfo;
if (AuthService()->Authorize(userId, password, UInfo)) {
if (AuthService()->Authorize(userId, password, newPassword, UInfo)) {
Poco::JSON::Object ReturnObj;
UInfo.webtoken.to_json(ReturnObj);
ReturnObject(Request, ReturnObj, Response);

View File

@@ -72,7 +72,9 @@ namespace uCentral::RESTAPI::Protocol {
static const char * REASON = "reason";
static const char * FILEUUID = "uuid";
static const char * USERID = "userId";
static const char * USERS = "users";
static const char * PASSWORD = "password";
static const char * NEWPASSWORD = "newPassword";
static const char * TOKEN = "token";
static const char * SETLOGLEVEL = "setloglevel";
static const char * GETLOGLEVELS = "getloglevels";

View File

@@ -3,9 +3,181 @@
//
#include "RESTAPI_user_handler.h"
#include "StorageService.h"
#include "Poco/JSON/Parser.h"
#include "Utils.h"
#include "RESTAPI_utils.h"
namespace uCentral {
void RESTAPI_user_handler::handleRequest(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) {
if (!ContinueProcessing(Request, Response))
return;
if (!IsAuthorized(Request, Response))
return;
ParseParameters(Request);
if(Request.getMethod()==Poco::Net::HTTPRequest::HTTP_GET)
DoGet(Request, Response);
else if(Request.getMethod()==Poco::Net::HTTPRequest::HTTP_POST)
DoPost(Request, Response);
else if(Request.getMethod()==Poco::Net::HTTPRequest::HTTP_DELETE)
DoDelete(Request, Response);
else if(Request.getMethod()==Poco::Net::HTTPRequest::HTTP_PUT)
DoPut(Request, Response);
else
BadRequest(Request, Response, "Unimplemented HTTP Operation.");
}
void RESTAPI_user_handler::DoGet(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) {
try {
std::string Id = GetBinding("id", "");
if(Id.empty()) {
BadRequest(Request, Response, "You must supply the ID of the user.");
return;
}
SecurityObjects::UserInfo UInfo;
if(!Storage()->GetUserById(Id,UInfo)) {
NotFound(Request, Response);
return;
}
Poco::JSON::Object UserInfoObject;
UInfo.to_json(UserInfoObject);
ReturnObject(Request, UserInfoObject, Response);
return;
} catch (const Poco::Exception &E ) {
Logger_.log(E);
}
BadRequest(Request, Response);
}
void RESTAPI_user_handler::DoDelete(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) {
try {
std::string Id = GetBinding("id", "");
if(Id.empty()) {
BadRequest(Request, Response, "You must supply the ID of the user.");
return;
}
if(!Storage()->DeleteUser(UserInfo_.userinfo.name,Id)) {
NotFound(Request, Response);
return;
}
Logger_.information(Poco::format("User '%s' deleted by '%s'.",Id,UserInfo_.userinfo.email));
OK(Request, Response);
return;
} catch (const Poco::Exception &E ) {
Logger_.log(E);
}
BadRequest(Request, Response);
}
void RESTAPI_user_handler::DoPost(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) {
try {
std::string Id = GetBinding("id", "");
if(Id!="0") {
BadRequest(Request, Response, "To create a user, you must set the ID to 0");
return;
}
SecurityObjects::UserInfo UInfo;
RESTAPI_utils::from_request(UInfo,Request);
Poco::toLowerInPlace(UInfo.email);
if(!Utils::ValidEMailAddress(UInfo.email)) {
BadRequest(Request, Response, "Invalid email address.");
return;
}
if(!Storage()->CreateUser(UserInfo_.userinfo.name,UInfo)) {
Logger_.information(Poco::format("Could not add user '%s'.",UInfo.email));
BadRequest(Request, Response);
return;
}
if(!Storage()->GetUserByEmail(UInfo.email, UInfo)) {
Logger_.information(Poco::format("User '%s' but not retrieved.",UInfo.email));
BadRequest(Request, Response);
return;
}
Poco::JSON::Object UserInfoObject;
UInfo.to_json(UserInfoObject);
ReturnObject(Request, UserInfoObject, Response);
Logger_.information(Poco::format("User '%s' has been added by '%s')",UInfo.email, UserInfo_.userinfo.email));
return;
} catch (const Poco::Exception &E ) {
Logger_.log(E);
}
BadRequest(Request, Response);
}
void RESTAPI_user_handler::DoPut(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) {
try {
std::string Id = GetBinding("id", "");
if(Id.empty()) {
BadRequest(Request, Response, "You must supply the ID of the user.");
return;
}
SecurityObjects::UserInfo LocalObject;
if(!Storage()->GetUserById(Id,LocalObject)) {
NotFound(Request, Response);
return;
}
Poco::JSON::Parser IncomingParser;
auto RawObject = IncomingParser.parse(Request.stream()).extract<Poco::JSON::Object::Ptr>();
// The only valid things to change are: changePassword, name,
if(RawObject->has("name"))
LocalObject.name = RawObject->get("name").toString();
if(RawObject->has("description"))
LocalObject.description = RawObject->get("description").toString();
if(RawObject->has("avatar"))
LocalObject.avatar = RawObject->get("avatar").toString();
if(RawObject->has("changePassword"))
LocalObject.changePassword = RawObject->get("changePassword").toString()=="true";
if(RawObject->has("owner"))
LocalObject.owner = RawObject->get("owner").toString();
if(RawObject->has("location"))
LocalObject.location = RawObject->get("location").toString();
if(RawObject->has("locale"))
LocalObject.locale = RawObject->get("locale").toString();
if(RawObject->has("userRole"))
LocalObject.location = RawObject->get("userRole").toString();
if(RawObject->has("suspended"))
LocalObject.suspended = RawObject->get("suspended").toString()=="true";
if(RawObject->has("blackListed"))
LocalObject.blackListed = RawObject->get("blackListed").toString()=="true";
if(RawObject->has("notes")) {
SecurityObjects::NoteInfoVec NIV;
NIV = RESTAPI_utils::to_object_array<SecurityObjects::NoteInfo>(RawObject->get("notes").toString());
for(auto const &i:NIV) {
SecurityObjects::NoteInfo ii{.created=(uint64_t)std::time(nullptr), .createdBy=UserInfo_.userinfo.email, .note=i.note};
LocalObject.notes.push_back(ii);
}
}
if(RawObject->has("currentPassword")) {
if(!AuthService()->SetPassword(RawObject->get("currentPassword").toString(),LocalObject)) {
BadRequest(Request, Response, "Password was rejected. This maybe an old password.");
return;
}
}
if(Storage()->UpdateUserInfo(UserInfo_.userinfo.email,Id,LocalObject)) {
Poco::JSON::Object ModifiedObject;
LocalObject.to_json(ModifiedObject);
ReturnObject(Request, ModifiedObject, Response);
return;
}
} catch( const Poco::Exception &E) {
Logger_.log(E);
}
BadRequest(Request, Response);
}
}

View File

@@ -20,7 +20,10 @@ namespace uCentral {
Poco::Net::HTTPRequest::HTTP_OPTIONS}) {}
void handleRequest(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) override;
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/user/{id}"}; };
void DoGet(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response);
void DoDelete(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response);
void DoPost(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response);
void DoPut(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response);
private:
};

View File

@@ -3,9 +3,43 @@
//
#include "RESTAPI_users_handler.h"
#include "StorageService.h"
#include "RESTAPI_protocol.h"
namespace uCentral {
void RESTAPI_users_handler::handleRequest(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) {
if (!ContinueProcessing(Request, Response))
return;
if (!IsAuthorized(Request, Response))
return;
ParseParameters(Request);
if(Request.getMethod()==Poco::Net::HTTPRequest::HTTP_GET)
DoGet(Request, Response);
else
BadRequest(Request, Response);
}
void RESTAPI_users_handler::DoGet(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) {
try {
std::vector<SecurityObjects::UserInfo> Users;
InitQueryBlock();
if (Storage()->GetUsers(QB_.Offset, QB_.Limit, Users)) {
Poco::JSON::Array ArrayObj;
for (const auto &i : Users) {
Poco::JSON::Object Obj;
i.to_json(Obj);
ArrayObj.add(Obj);
}
Poco::JSON::Object RetObj;
RetObj.set(uCentral::RESTAPI::Protocol::USERS, ArrayObj);
ReturnObject(Request, RetObj, Response);
return;
}
} catch ( const Poco::Exception &E ) {
Logger_.log(E);
}
BadRequest(Request, Response);
}
}

View File

@@ -17,6 +17,7 @@ namespace uCentral {
Poco::Net::HTTPRequest::HTTP_OPTIONS}) {}
void handleRequest(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response) override;
static const std::list<const char *> PathName() { return std::list<const char *>{"/api/v1/users"}; };
void DoGet(Poco::Net::HTTPServerRequest &Request, Poco::Net::HTTPServerResponse &Response);
};
};

View File

@@ -4,9 +4,12 @@
#ifndef UCENTRALGW_RESTAPI_UTILS_H
#define UCENTRALGW_RESTAPI_UTILS_H
#include <functional>
#include "Poco/JSON/Object.h"
#include "Poco/JSON/Parser.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "uCentralTypes.h"
#include "Utils.h"
@@ -37,6 +40,20 @@ namespace uCentral::RESTAPI_utils {
Obj.set(Field,A);
}
template<typename T> void field_to_json(Poco::JSON::Object &Obj,
const char *Field,
const T &V,
std::function<std::string(const T &)> F) {
Obj.set(Field, F(V));
}
template<typename T> bool field_from_json(Poco::JSON::Object::Ptr Obj, const char *Field, T & V,
std::function<T(const std::string &)> F) {
if(Obj->has(Field))
V = F(Obj->get(Field).toString());
return true;
}
inline void field_from_json(Poco::JSON::Object::Ptr Obj, const char *Field, std::string &S) {
if(Obj->has(Field))
S = Obj->get(Field).toString();
@@ -91,6 +108,18 @@ namespace uCentral::RESTAPI_utils {
}
}
inline std::string to_string(const Types::StringVec & ObjectArray) {
Poco::JSON::Array OutputArr;
if(ObjectArray.empty())
return "[]";
for(auto const &i:ObjectArray) {
OutputArr.add(i);
}
std::ostringstream OS;
Poco::JSON::Stringifier::condense(OutputArr,OS);
return OS.str();
}
template<class T> std::string to_string(const std::vector<T> & ObjectArray) {
Poco::JSON::Array OutputArr;
if(ObjectArray.empty())
@@ -113,6 +142,24 @@ namespace uCentral::RESTAPI_utils {
return OS.str();
}
inline Types::StringVec to_object_array(const std::string & ObjectString) {
Types::StringVec Result;
if(ObjectString.empty())
return Result;
try {
Poco::JSON::Parser P;
auto Object = P.parse(ObjectString).template extract<Poco::JSON::Array::Ptr>();
for (auto const i : *Object) {
Result.push_back(i.toString());
}
} catch (...) {
}
return Result;
}
template<class T> std::vector<T> to_object_array(const std::string & ObjectString) {
std::vector<T> Result;
@@ -146,6 +193,13 @@ namespace uCentral::RESTAPI_utils {
return Result;
}
template<class T> bool from_request(T & Obj, Poco::Net::HTTPServerRequest &Request) {
Poco::JSON::Parser IncomingParser;
auto RawObject = IncomingParser.parse(Request.stream()).extract<Poco::JSON::Object::Ptr>();
Obj.from_json(RawObject);
return true;
}
}
#endif // UCENTRALGW_RESTAPI_UTILS_H

View File

@@ -48,7 +48,6 @@ namespace uCentral {
Logger_.setLevel(Poco::Message::PRIO_NOTICE);
Logger_.notice("Starting.");
std::string DBType = Daemon()->ConfigGetString("storage.type");
if (DBType == "sqlite") {
Setup_SQLite();
} else if (DBType == "postgresql") {

View File

@@ -25,6 +25,71 @@
namespace uCentral {
static const std::string AllUsersFieldsForCreation{
"Id varchar(36),"
"name varchar,"
"description varchar,"
"avatar varchar,"
"email varchar,"
"validated int,"
"validationEmail varchar,"
"validationDate bigint,"
"creationDate bigint,"
"validationURI varchar,"
"changePassword int,"
"lastLogin bigint,"
"currentLoginURI varchar,"
"lastPasswordChange bigint,"
"lastEmailCheck bigint,"
"waitingForEmailCheck int,"
"locale varchar,"
"notes text,"
"location varchar,"
"owner varchar,"
"suspended int,"
"blackListed int,"
"userRole varchar,"
"userTypeProprietaryInfo text,"
"securityPolicy text,"
"securityPolicyChange bigint,"
"currentPassword varchar,"
"lastPasswords varchar,"
"oauthType varchar,"
"oauthUserInfo text"};
static const std::string AllUsersFieldsForSelect{
"Id,"
"name,"
"description,"
"avatar,"
"email,"
"validated,"
"validationEmail,"
"validationDate,"
"creationDate,"
"validationURI,"
"changePassword,"
"lastLogin,"
"currentLoginURI,"
"lastPasswordChange,"
"lastEmailCheck,"
"waitingForEmailCheck,"
"locale,"
"notes,"
"location,"
"owner,"
"suspended,"
"blackListed,"
"userRole,"
"userTypeProprietaryInfo,"
"securityPolicy,"
"securityPolicyChange,"
"currentPassword,"
"lastPasswords,"
"oauthType,"
"oauthUserInfo"};
class Storage : public SubSystemServer {
public:
@@ -42,13 +107,16 @@ namespace uCentral {
PASSWORD_DOES_NOT_MATCH,
PASSWORD_ALREADY_USED,
USERNAME_PENDING_VERIFICATION,
PASSWORD_INVALID
PASSWORD_INVALID,
INTERNAL_ERROR
};
enum USER_TYPE {
UNKNOWN, ROOT, ADMIN, SUBSCRIBER, CSR, SYSTEM, SPECIAL
};
typedef std::string USER_ID_TYPE;
static USER_TYPE to_userType(const std::string &U) {
if (U=="root")
return ROOT;
@@ -90,45 +158,16 @@ namespace uCentral {
// all passwords passed here are all plaintext
bool CreateUser(const std::string & Admin, SecurityObjects::UserInfo & NewUser);
bool DeleteUser(const std::string & Admin, uint64_t Id);
bool SetOwner(const std::string & Admin, uint64_t Id, const std::string &Owner);
bool SetLocation(const std::string & Admin, uint64_t Id, const std::string &Location);
AUTH_ERROR ChangePassword(const std::string & Admin, uint64_t Id, const std::string &OldPassword, const std::string &NewPassword);
bool AddNotes(const std::string & Admin, uint64_t Id, const std::string &Notes);
bool SetPolicyChange(const std::string & Admin, const std::string &NewPolicy);
bool IdentityExists(std::string & Identity, AuthService::ACCESS_TYPE Type);
bool AddIdentity(std::string & Identity, std::string & Password, AuthService::ACCESS_TYPE Type, SecurityObjects::AclTemplate & ACL);
bool GetIdentity(std::string & Identity, std::string & Password,AuthService::ACCESS_TYPE Type, SecurityObjects::AclTemplate & ACL);
bool UpdateIdentity(std::string & Identity, std::string & Password, AuthService::ACCESS_TYPE Type, SecurityObjects::AclTemplate & ACL);
bool DeleteIdentity(std::string & Identity, AuthService::ACCESS_TYPE Type);
bool ListIdentities(uint64_t Offset, uint64_t HowMany, std::vector<std::string> & Identities, AuthService::ACCESS_TYPE Type);
bool GetIdentityRights(std::string &Identity, SecurityObjects::AclTemplate &ACL);
bool GetUserByEmail(std::string & email, SecurityObjects::UserInfo & User);
bool GetUserById(USER_ID_TYPE & Id, SecurityObjects::UserInfo & User);
bool DeleteUser(const std::string & Admin, USER_ID_TYPE & Id);
bool SetOwner(const std::string & Admin, USER_ID_TYPE & Id, const std::string &Owner);
bool SetLocation(const std::string & Admin, USER_ID_TYPE & Id, const std::string &Location);
AUTH_ERROR ChangePassword(const std::string & Admin, USER_ID_TYPE & Id, const std::string &OldPassword, const std::string &NewPassword);
bool AddNotes(const std::string & Admin, USER_ID_TYPE & Id, const std::string &Notes);
bool SetPolicyChange(const std::string & Admin, USER_ID_TYPE & Id, const std::string &NewPolicy);
bool UpdateUserInfo(const std::string & Admin, USER_ID_TYPE & Id, SecurityObjects::UserInfo &UInfo);
bool GetUsers( uint64_t Offset, uint64_t Limit, SecurityObjects::UserInfoVec & Users);
private:
static Storage *instance_;

View File

@@ -12,6 +12,8 @@
#include "Poco/Net/X509Certificate.h"
#include "Poco/DateTimeFormatter.h"
#include "Poco/DateTimeFormat.h"
#include "Poco/Net/PrivateKeyPassphraseHandler.h"
#include "Poco/Net/SSLManager.h"
#include "openssl/ssl.h"
@@ -87,6 +89,21 @@ void SubSystemServer::reinitialize(Poco::Util::Application &self) {
void SubSystemServer::defineOptions(Poco::Util::OptionSet &options) {}
class MyPrivateKeyPassphraseHandler : public Poco::Net::PrivateKeyPassphraseHandler {
public:
explicit MyPrivateKeyPassphraseHandler(const std::string &Password, Poco::Logger & Logger):
PrivateKeyPassphraseHandler(true),
Logger_(Logger),
Password_(Password) {}
void onPrivateKeyRequested(const void * pSender,std::string & privateKey) {
Logger_.information("Returning key passphrase.");
privateKey = Password_;
};
private:
std::string Password_;
Poco::Logger & Logger_;
};
Poco::Net::SecureServerSocket PropertiesFileServerEntry::CreateSecureSocket(Poco::Logger &L) const {
Poco::Net::Context::Params P;
@@ -97,7 +114,12 @@ Poco::Net::SecureServerSocket PropertiesFileServerEntry::CreateSecureSocket(Poco
P.dhUse2048Bits = true;
P.caLocation = cas_;
auto Context = new Poco::Net::Context(Poco::Net::Context::TLS_SERVER_USE, P);
auto Context = Poco::AutoPtr<Poco::Net::Context>(new Poco::Net::Context(Poco::Net::Context::TLS_SERVER_USE, P));
if(!key_file_password_.empty()) {
auto PassphraseHandler = Poco::SharedPtr<MyPrivateKeyPassphraseHandler>( new MyPrivateKeyPassphraseHandler(KeyFilePassword(),L));
Poco::Net::SSLManager::instance().initializeServer(PassphraseHandler, nullptr,Context);
}
if (!cert_file_.empty() && !key_file_.empty()) {
Poco::Crypto::X509Certificate Cert(cert_file_);

View File

@@ -8,6 +8,7 @@
#include <stdexcept>
#include <fstream>
#include <cstdlib>
#include <regex>
#include "Utils.h"
@@ -390,4 +391,12 @@ namespace uCentral::Utils {
}
}
bool ValidEMailAddress(const std::string &email) {
// define a regular expression
const std::regex pattern
("(\\w+)(\\.|_)?(\\w*)@(\\w+)(\\.(\\w+))+");
// try to match the string with the regular expression
return std::regex_match(email, pattern);
}
}

View File

@@ -48,5 +48,7 @@ namespace uCentral::Utils {
[[nodiscard]] uint64_t GetDefaultMacAsInt64();
[[nodiscard]] uint64_t GetSystemId();
[[nodiscard]] bool ValidEMailAddress(const std::string &E);
}
#endif // UCENTRALGW_UTILS_H

View File

@@ -1,125 +0,0 @@
//
// License type: BSD 3-Clause License
// License copy: https://github.com/Telecominfraproject/wlan-cloud-ucentralgw/blob/master/LICENSE
//
// Created by Stephane Bourque on 2021-03-04.
// Arilia Wireless Inc.
//
#include "StorageService.h"
namespace uCentral {
/*
"Identity VARCHAR(128) PRIMARY KEY, "
"Password VARCHAR(128), "
"AccessType INT, "
"Created BIGINT, "
"Modified BIGINT, "
"Expires BIGINT, "
"CreatedBy VARCHAR(128), "
"ACLRead INT, "
"ACLReadWrite INT, "
"ACLReadWriteCreate INT, "
"ACLDelete INT, "
"ACLPortal INT "
") ", Poco::Data::Keywords::now;
*/
bool Storage::IdentityExists(std::string & Identity, AuthService::ACCESS_TYPE Type) {
try {
int TT = AuthService::AccessTypeToInt(Type);
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Select(Sess);
std::string Tmp;
std::string st{"SELECT Identity FROM Authentication WHERE Identity=? AND AccessType=?"};
Select << ConvertParams(st),
Poco::Data::Keywords::into(Tmp),
Poco::Data::Keywords::use(Identity),
Poco::Data::Keywords::use(TT);
Select.execute();
return !Identity.empty();
} catch (const Poco::Exception &E ) {
Logger_.log(E);
}
return false;
}
bool Storage::AddIdentity(std::string & Identity, std::string & Password, AuthService::ACCESS_TYPE Type, SecurityObjects::AclTemplate & ACL) {
try {
} catch(const Poco::Exception &E )
{
Logger_.log(E);
}
return false;
}
bool Storage::GetIdentity(std::string & Identity, std::string & Password,AuthService::ACCESS_TYPE Type, SecurityObjects::AclTemplate & ACL) {
try {
} catch(const Poco::Exception &E )
{
Logger_.log(E);
}
return false;
}
bool Storage::UpdateIdentity(std::string & Identity, std::string & Password, AuthService::ACCESS_TYPE Type, SecurityObjects::AclTemplate & ACL) {
try {
} catch(const Poco::Exception &E )
{
Logger_.log(E);
}
return false;
}
bool Storage::DeleteIdentity(std::string & Identity, AuthService::ACCESS_TYPE Type) {
try {
int TT = AuthService::AccessTypeToInt(Type);
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Delete(Sess);
std::string Tmp;
std::string st{"DELETE FROM Authentication WHERE Identity=? AND AccessType=?"};
Delete << ConvertParams(st),
Poco::Data::Keywords::use(Identity),
Poco::Data::Keywords::use(TT);
Delete.execute();
return true;
} catch(const Poco::Exception &E )
{
Logger_.log(E);
}
return false;
}
bool Storage::ListIdentities(uint64_t Offset, uint64_t HowMany, std::vector<std::string> & Identities, AuthService::ACCESS_TYPE Type) {
try {
} catch(const Poco::Exception &E )
{
Logger_.log(E);
}
return false;
}
bool Storage::GetIdentityRights(std::string &Identity, SecurityObjects::AclTemplate &ACL) {
try {
} catch(const Poco::Exception &E )
{
Logger_.log(E);
}
return false;
}
}

View File

@@ -3,10 +3,12 @@
//
#include "StorageService.h"
#include "Utils.h"
namespace uCentral {
int Storage::Create_Tables() {
Create_UserTable();
return 0;
}
@@ -14,70 +16,15 @@ namespace uCentral {
Poco::Data::Session Sess = Pool_->get();
try {
if (dbType_ == mysql) {
Sess << "CREATE TABLE IF NOT EXISTS Users ("
"Id Id unique primary key, "
"name varchar, "
"description varchar, "
"avatar varchar, "
"email varchar, "
"validated int, "
"validationEmail varchar, "
"validationDate bigint, "
"creationDate bigint, "
"validationURI text, "
"changePassword int, "
"lastLogin bigint, "
"currentLoginURI varchar, "
"lastPasswordChange bigint, "
"lastEmailCheck bigint, "
"currentPassword varchar, "
"lastPasswords varchar,"
"waitingForEmailCheck int, "
"locale varchar, "
"notes text, "
"location text, "
"owner varchar, "
"suspended int, "
"blackListed int, "
"userRole varchar, "
"securityPolicy text, "
"securityPolicyChange bigint, "
"userTypeProprietaryInfo text"
Sess << "CREATE TABLE IF NOT EXISTS Users (" +
AllUsersFieldsForCreation +
" ,INDEX emailindex (email ASC)"
" ,INDEX nameindex (name ASC))",
Poco::Data::Keywords::now;
} else {
Sess << "CREATE TABLE IF NOT EXISTS Users ("
"Id Id unique primary key, "
"name varchar, "
"description varchar, "
"avatar varchar, "
"email varchar, "
"validated int, "
"validationEmail varchar, "
"validationDate bigint, "
"creationDate bigint, "
"validationURI text, "
"changePassword int, "
"lastLogin bigint, "
"currentLoginURI varchar, "
"lastPasswordChange bigint, "
"lastEmailCheck bigint, "
"currentPassword varchar, "
"lastPasswords varchar,"
"waitingForEmailCheck int, "
"locale varchar, "
"notes text, "
"location text, "
"owner varchar, "
"suspended int, "
"blackListed int, "
"userRole varchar, "
"securityPolicy text, "
"securityPolicyChange bigint, "
"userTypeProprietaryInfo text"
Sess << "CREATE TABLE IF NOT EXISTS Users (" +
AllUsersFieldsForCreation +
")",
Poco::Data::Keywords::now;
Sess << "CREATE INDEX IF NOT EXISTS emailindex ON Users (email ASC)", Poco::Data::Keywords::now;

View File

@@ -3,35 +3,369 @@
//
#include "StorageService.h"
#include "RESTAPI_utils.h"
#include "Daemon.h"
#include "Poco/Tuple.h"
namespace uCentral {
typedef Poco::Tuple<
std::string, // Id = 0;
std::string, // name;
std::string, // description;
std::string, // avatar;
std::string, // email;
uint64_t, // bool validated = false;
std::string, // validationEmail;
uint64_t, // validationDate = 0;
uint64_t, // creationDate = 0;
std::string, // validationURI;
uint64_t, // bool changePassword = true;
uint64_t, // lastLogin = 0;
std::string, // currentLoginURI;
uint64_t, // lastPasswordChange = 0;
uint64_t, // lastEmailCheck = 0;
uint64_t , // bool waitingForEmailCheck = false;
std::string, // locale;
std::string, // notes;
std::string, // location;
std::string, // owner;
uint64_t, // bool suspended = false;
uint64_t, // bool blackListed = false;
std::string, // userRole;
std::string, // userTypeProprietaryInfo;
std::string, // securityPolicy;
uint64_t , // securityPolicyChange;
std::string, // currentPassword;
std::string, // lastPasswords;
std::string, // oauthType;
std::string // oauthUserInfo;
> UserInfoRecord;
typedef std::vector<UserInfoRecord> UserInfoRecordList;
bool Convert(const UserInfoRecord &T, SecurityObjects::UserInfo &U) {
U.Id = T.get<0>();
U.name = T.get<1>();
U.description = T.get<2>();
U.avatar = T.get<3>();
U.email = T.get<4>();
U.validated = T.get<5>();
U.validationEmail = T.get<6>();
U.validationDate = T.get<7>();
U.creationDate = T.get<8>();
U.validationURI = T.get<9>();
U.changePassword = T.get<10>();
U.lastLogin = T.get<11>();
U.currentLoginURI = T.get<12>();
U.lastPasswordChange = T.get<13>();
U.lastEmailCheck = T.get<14>();
U.waitingForEmailCheck = T.get<15>();
U.locale = T.get<16>();
U.notes = RESTAPI_utils::to_object_array<SecurityObjects::NoteInfo>(T.get<17>());
U.location = T.get<18>();
U.owner = T.get<19>();
U.suspended = T.get<20>();
U.blackListed = T.get<21>();
U.userRole = SecurityObjects::UserTypeFromString(T.get<22>());
U.userTypeProprietaryInfo = T.get<23>();
U.securityPolicy = T.get<24>();
U.securityPolicyChange = T.get<25>();
U.currentPassword = T.get<26>();
U.lastPasswords = RESTAPI_utils::to_object_array(T.get<27>());
U.oauthType = T.get<28>();
U.oauthUserInfo = T.get<29>();
return true;
}
bool Convert(const SecurityObjects::UserInfo &U, UserInfoRecord &T) {
T.set<0>(U.Id);
T.set<1>(U.name);
T.set<2>(U.description);
T.set<3>(U.avatar);
T.set<4>(U.email);
T.set<5>(U.validated);
T.set<6>(U.validationEmail);
T.set<7>(U.validationDate);
T.set<8>(U.creationDate);
T.set<9>(U.validationURI);
T.set<10>(U.changePassword);
T.set<11>(U.lastLogin);
T.set<12>(U.currentLoginURI);
T.set<13>(U.lastPasswordChange);
T.set<14>(U.lastEmailCheck);
T.set<15>(U.waitingForEmailCheck);
T.set<16>(U.locale);
T.set<17>(RESTAPI_utils::to_string(U.notes));
T.set<18>(U.location);
T.set<19>(U.owner);
T.set<20>(U.suspended);
T.set<21>(U.blackListed);
T.set<22>(SecurityObjects::UserTypeToString(U.userRole));
T.set<23>(U.userTypeProprietaryInfo);
T.set<24>(U.securityPolicy);
T.set<25>(U.securityPolicyChange);
T.set<26>(U.currentPassword);
T.set<27>(RESTAPI_utils::to_string(U.lastPasswords));
T.set<28>(U.oauthType);
T.set<29>(U.oauthUserInfo);
return true;
}
bool Storage::CreateUser(const std::string & Admin, SecurityObjects::UserInfo & NewUser) {
return true;
try {
Poco::Data::Session Sess = Pool_->get();
Poco::toLowerInPlace(NewUser.email);
// if the user exists, must return an error
std::string St1{"select " + AllUsersFieldsForSelect + " from users where email=?"};
UserInfoRecordList Records;
try {
Poco::Data::Statement Statement(Sess);
Statement << ConvertParams(St1),
Poco::Data::Keywords::into(Records),
Poco::Data::Keywords::use(NewUser.email);
Statement.execute();
} catch (const Poco::Exception &E) {
}
bool Storage::DeleteUser(const std::string & Admin, uint64_t Id) {
return true;
if(!Records.empty())
return false;
NewUser.Id = Daemon()->CreateUUID();
NewUser.creationDate = std::time(nullptr);
// if there is a password, we assume that we do not want email verification,
// if there is no password, we will do email verification
if(NewUser.currentPassword.empty()) {
} else {
NewUser.currentPassword = AuthService()->ComputePasswordHash(NewUser.email,NewUser.currentPassword);
NewUser.lastPasswords.clear();
NewUser.lastPasswords.push_back(NewUser.currentPassword);
NewUser.lastPasswordChange = std::time(nullptr);
NewUser.validated = true;
}
bool Storage::SetOwner(const std::string & Admin, uint64_t Id, const std::string &Owner) {
auto Notes = RESTAPI_utils::to_string(NewUser.notes);
auto UserType = SecurityObjects::UserTypeToString(NewUser.userRole);
auto OldPasswords = RESTAPI_utils::to_string(NewUser.lastPasswords);
St1 = "INSERT INTO Users (" + AllUsersFieldsForSelect + ") VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
Poco::Data::Statement Statement(Sess);
Statement << ConvertParams(St1),
Poco::Data::Keywords::use(NewUser.Id),
Poco::Data::Keywords::use(NewUser.name),
Poco::Data::Keywords::use(NewUser.description),
Poco::Data::Keywords::use(NewUser.avatar),
Poco::Data::Keywords::use(NewUser.email),
Poco::Data::Keywords::use(NewUser.validated),
Poco::Data::Keywords::use(NewUser.validationEmail),
Poco::Data::Keywords::use(NewUser.validationDate),
Poco::Data::Keywords::use(NewUser.creationDate),
Poco::Data::Keywords::use(NewUser.validationURI),
Poco::Data::Keywords::use(NewUser.changePassword),
Poco::Data::Keywords::use(NewUser.lastLogin),
Poco::Data::Keywords::use(NewUser.currentLoginURI),
Poco::Data::Keywords::use(NewUser.lastPasswordChange),
Poco::Data::Keywords::use(NewUser.lastEmailCheck),
Poco::Data::Keywords::use(NewUser.waitingForEmailCheck),
Poco::Data::Keywords::use(NewUser.locale),
Poco::Data::Keywords::use(Notes),
Poco::Data::Keywords::use(NewUser.location),
Poco::Data::Keywords::use(NewUser.owner),
Poco::Data::Keywords::use(NewUser.suspended),
Poco::Data::Keywords::use(NewUser.blackListed),
Poco::Data::Keywords::use(UserType),
Poco::Data::Keywords::use(NewUser.userTypeProprietaryInfo),
Poco::Data::Keywords::use(NewUser.securityPolicy),
Poco::Data::Keywords::use(NewUser.securityPolicyChange),
Poco::Data::Keywords::use(NewUser.currentPassword),
Poco::Data::Keywords::use(OldPasswords),
Poco::Data::Keywords::use(NewUser.oauthType),
Poco::Data::Keywords::use(NewUser.oauthUserInfo);
Statement.execute();
return true;
} catch (const Poco::Exception &E) {
std::cout << "What: " << E.what() << " name: " << E.name() << std::endl;
Logger_.log(E);
}
return false;
}
bool Storage::SetLocation(const std::string & Admin, uint64_t Id, const std::string &Location) {
bool Storage::GetUserByEmail(std::string & email, SecurityObjects::UserInfo & User) {
std::string St1;
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Select(Sess);
Poco::toLowerInPlace(email);
// if the user exists, must return an error
St1 = "select " + AllUsersFieldsForSelect + " from users where email=?";
UserInfoRecordList Records;
Select << ConvertParams(St1) ,
Poco::Data::Keywords::into(Records),
Poco::Data::Keywords::use(email);
Select.execute();
if(Records.empty())
return false;
Convert(Records[0],User);
return true;
} catch (const Poco::Exception &E) {
std::cout << "Statement: " << St1 << std::endl;
std::cout << "What:" << E.what() << " name: " << E.name() << std::endl;
Logger_.log(E);
}
return false;
}
Storage::AUTH_ERROR Storage::ChangePassword(const std::string & Admin, uint64_t Id, const std::string &OldPassword, const std::string &NewPassword) {
bool Storage::GetUserById(std::string &Id, SecurityObjects::UserInfo &User) {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Select(Sess);
// if the user exists, must return an error
std::string St1{"select " + AllUsersFieldsForSelect + " from users where id=?"};
UserInfoRecordList Records;
Select << ConvertParams(St1) ,
Poco::Data::Keywords::into(Records),
Poco::Data::Keywords::use(Id);
Select.execute();
if(Records.empty())
return false;
Convert(Records[0],User);
return true;
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
return false;
}
bool Storage::GetUsers( uint64_t Offset, uint64_t Limit, SecurityObjects::UserInfoVec & Users) {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Select(Sess);
UserInfoRecordList Records;
std::string St1{"select " + AllUsersFieldsForSelect + " from users"};
Select << ConvertParams(St1) ,
Poco::Data::Keywords::into(Records),
Poco::Data::Keywords::range(Offset, Offset + Limit);
Select.execute();
for(const auto &R:Records) {
SecurityObjects::UserInfo U;
Convert(R,U);
Users.push_back(U);
}
return true;
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
return false;
}
bool Storage::UpdateUserInfo(const std::string & Admin, USER_ID_TYPE & Id, SecurityObjects::UserInfo &UInfo) {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Insert(Sess);
return true;
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
return false;
}
bool Storage::DeleteUser(const std::string & Admin, USER_ID_TYPE & Id) {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Delete(Sess);
std::string St1{"delete from users where id=?"};
Delete << ConvertParams(St1),
Poco::Data::Keywords::use(Id);
Delete.execute();
return true;
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
return false;
}
bool Storage::SetOwner(const std::string & Admin, USER_ID_TYPE & Id, const std::string &Owner) {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Insert(Sess);
return true;
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
return false;
}
bool Storage::SetLocation(const std::string & Admin, USER_ID_TYPE & Id, const std::string &Location) {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Insert(Sess);
return true;
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
return false;
}
Storage::AUTH_ERROR Storage::ChangePassword(const std::string & Admin, USER_ID_TYPE & Id, const std::string &OldPassword, const std::string &NewPassword) {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Insert(Sess);
return SUCCESS;
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
return INTERNAL_ERROR;
}
bool Storage::AddNotes(const std::string & Admin, uint64_t Id, const std::string &Notes) {
bool Storage::AddNotes(const std::string & Admin, USER_ID_TYPE & Id, const std::string &Notes) {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Insert(Sess);
return true;
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
return false;
}
bool Storage::SetPolicyChange(const std::string & Admin, const std::string &NewPolicy) {
bool Storage::SetPolicyChange(const std::string & Admin, USER_ID_TYPE & Id, const std::string &NewPolicy) {
try {
Poco::Data::Session Sess = Pool_->get();
Poco::Data::Statement Insert(Sess);
return true;
} catch (const Poco::Exception &E) {
Logger_.log(E);
}
return false;
}
}

View File

@@ -34,8 +34,10 @@ fi
token=""
result_file=result.json
username="tip@ucentral.com"
password="openwifi"
#username="tip@ucentral.com"
#password="openwifi"
username="stephb@incognito.com"
password="blabla"
browser_list=(firefox sensible-browser xdg-open w3m links links2 lynx youtube-dl)
browser=""
@@ -114,498 +116,53 @@ listendpoints() {
done
}
listcommands() {
curl ${FLAGS} -X GET "https://${UCENTRALSEC}/api/v1/commands?serialNumber=$1&limit=3000" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" > ${result_file}
jq < ${result_file}
}
newestcommands() {
curl ${FLAGS} -X GET "https://${UCENTRALSEC}/api/v1/commands?serialNumber=$1&newest=true&limit=50" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" > ${result_file}
jq < ${result_file}
}
deletecommands() {
curl ${FLAGS} -X DELETE "https://${UCENTRALSEC}/api/v1/commands?serialNumber=$1" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}"
}
getcapabilities() {
curl -${FLAGS} -X GET "https://${UCENTRALSEC}/api/v1/device/$1/capabilities" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" > ${result_file}
jq < ${result_file}
}
deletecapabilities() {
curl ${FLAGS} -X DELETE "https://${UCENTRALSEC}/api/v1/device/$1/capabilities" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}"
}
listdevices() {
curl ${FLAGS} -X GET "https://${UCENTRALSEC}/api/v1/devices" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" > ${result_file}
jq < ${result_file}
}
deletedevice() {
curl ${FLAGS} -X DELETE "https://${UCENTRALSEC}/api/v1/device/$1" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}"
}
createdevice() {
payload="{ \"serialNumber\": \"$1\", \"UUID\": 1234456, \"configuration\" : $(cat "$2") , \"deviceType\": \"AP_Default\",\"location\": \"\", \"macAddress\": \"$3\", \"manufacturer\": \"Linksys EA8300 (Dallas)\", \"notes\": \"auto created device.\", \"owner\": \"\" }"
curl ${FLAGS} -X POST "https://${UCENTRALSEC}/api/v1/device/$1" \
createuser() {
payload="{ \"id\": \"0\", \"email\" : \"$1\", \"currentPassword\" : \"$2\" }"
curl ${FLAGS} -X POST "https://${UCENTRALSEC}/api/v1/user/0" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" \
-d "$payload" > ${result_file}
jq < ${result_file}
}
reboot() {
payload="{ \"serialNumber\" : \"$1\" }"
curl ${FLAGS} -X POST "https://${UCENTRALSEC}/api/v1/device/$1/reboot" \
deleteuser() {
curl ${FLAGS} -X DELETE "https://${UCENTRALSEC}/api/v1/user/$1" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" \
-d "$payload" > ${result_file}
jq < ${result_file}
}
setloglevel() {
payload="{ \"command\" : \"setloglevel\" , \"parameters\" : [ { \"tag\" : \"$1\" , \"value\" : \"$2\" } ] }"
curl ${FLAGS} -X POST "https://${UCENTRALSEC}/api/v1/system" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" \
-d "$payload"
}
getloglevels() {
payload="{ \"command\" : \"getloglevels\" }"
curl ${FLAGS} -X POST "https://${UCENTRALSEC}/api/v1/system" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" \
-d "$payload"
}
getloglevelnames() {
payload="{ \"command\" : \"getloglevelnames\" }"
curl ${FLAGS} -X POST "https://${UCENTRALSEC}/api/v1/system" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" \
-d "$payload"
}
getsubsystemnames() {
payload="{ \"command\" : \"getsubsystemnames\" }"
curl ${FLAGS} -X POST "https://${UCENTRALSEC}/api/v1/system" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" \
-d "$payload"
}
getdevicestatus() {
curl ${FLAGS} -X GET "https://${UCENTRALSEC}/api/v1/device/$1/status" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" > ${result_file}
jq < ${result_file}
}
upgrade() {
payload="{ \"serialNumber\" : \"$1\" , \"uri\" : \"$2\" }"
curl ${FLAGS} -X POST "https://${UCENTRALSEC}/api/v1/device/$1/upgrade" \
getuser() {
curl ${FLAGS} -X GET "https://${UCENTRALSEC}/api/v1/user/$1" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" \
-d "$payload" > ${result_file}
jq < ${result_file}
}
leds() {
payload="{ \"serialNumber\" : \"$1\" , \"duration\" : $3, \"pattern\" : \"$2\" }"
curl ${FLAGS} -X POST "https://${UCENTRALSEC}/api/v1/device/$1/leds" \
listusers() {
curl ${FLAGS} -X GET "https://${UCENTRALSEC}/api/v1/users" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" \
-d "$payload" > ${result_file}
jq < ${result_file}
}
factory() {
payload="{ \"serialNumber\" : \"$1\" , \"keepRedirector\" : $2 }"
curl ${FLAGS} -X POST "https://${UCENTRALSEC}/api/v1/device/$1/factory" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" \
-d "$payload" > ${result_file}
jq < ${result_file}
}
configure() {
payload="{ \"serialNumber\" : \"$1\", \"UUID\" : 123456 , \"configuration\" : $(cat "$2") }"
curl ${FLAGS} -X POST "https://${UCENTRALSEC}/api/v1/device/$1/configure" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" \
-d "$payload" > ${result_file}
jq < ${result_file}
}
request() {
payload="{ \"serialNumber\" : \"$1\" , \"message\" : \"$2\" }"
curl ${FLAGS} -X POST "https://${UCENTRALSEC}/api/v1/device/$1/request" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" \
-d "$payload" > ${result_file}
jq < ${result_file}
}
wifiscan() {
payload="{ \"serialNumber\" : \"$1\" , \"verbose\" : $2 }"
curl ${FLAGS} -X POST "https://${UCENTRALSEC}/api/v1/device/$1/wifiscan" \
--max-time 20 \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" \
-d "$payload" > ${result_file}
jq < ${result_file}
}
activescan() {
payload="{ \"serialNumber\" : \"$1\" , \"verbose\" : $2, \"activeScan\" : true}"
curl ${FLAGS} -X POST "https://${UCENTRALSEC}/api/v1/device/$1/wifiscan" \
--max-time 20 \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" \
-d "$payload" > ${result_file}
jq < ${result_file}
}
trace() {
payload="{ \"serialNumber\" : \"$1\" , \"duration\" : $2, \"network\" : \"$3\" }"
curl ${FLAGS} -X POST "https://${UCENTRALSEC}/api/v1/device/$1/trace" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" \
-d "$payload" > ${result_file}
jq < ${result_file}
}
getstats() {
curl ${FLAGS} -X GET "https://${UCENTRALSEC}/api/v1/device/$1/statistics" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" > ${result_file}
jq < ${result_file}
}
getlogs() {
curl ${FLAGS} -X GET "https://${UCENTRALSEC}/api/v1/device/$1/logs" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" > ${result_file}
jq < ${result_file}
}
deletelogs() {
curl ${FLAGS} -X DELETE "https://${UCENTRALSEC}/api/v1/device/$1/logs" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}"
}
gethealthchecks() {
curl ${FLAGS} -X GET "https://${UCENTRALSEC}/api/v1/device/$1/healthchecks" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" > ${result_file}
jq < ${result_file}
}
createdefaultconfig() {
payload="{ \"name\": \"$1\", \"modelIds\" : \"$2\", \"configuration\" : $(cat "$3")}"
curl ${FLAGS} -X POST "https://${UCENTRALSEC}/api/v1/default_configuration/$1" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" \
-d "$payload" > ${result_file}
jq < ${result_file}
}
listdefaultconfigs() {
curl ${FLAGS} -X GET "https://${UCENTRALSEC}/api/v1/default_configurations" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" > ${result_file}
jq < ${result_file}
}
addblacklistdevice() {
payload="{ \"devices\" : [ {\"serialNumber\": \"$1\" , \"reason\" : \"$2\" } ] }"
curl ${FLAGS} -X POST "https://${UCENTRALSEC}/api/v1/blacklist" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" \
-d "$payload"
}
deleteblacklistdevice() {
curl ${FLAGS} -X DELETE "https://${UCENTRALSEC}/api/v1/blacklist?serialNumber=$1" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}"
}
getblacklist() {
curl ${FLAGS} -X GET "https://${UCENTRALSEC}/api/v1/blacklist" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" > ${result_file}
jq < ${result_file}
}
eventqueue() {
payload="{ \"serialNumber\" : \"$1\" , \"types\" : [ \"dhcp\", \"rrm\" ] }"
curl ${FLAGS} -X POST "https://${UCENTRALSEC}/api/v1/device/$1/eventqueue" \
--max-time 20 \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" \
-d "$payload" > ${result_file}
jq < ${result_file}
}
selectdevices() {
curl ${FLAGS} -X GET "https://${UCENTRALSEC}/api/v1/devices?select=$1" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" > ${result_file}
jq < ${result_file}
}
deviceserialnumbers() {
curl ${FLAGS} -X GET "https://${UCENTRALSEC}/api/v1/devices?serialOnly=true" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" > ${result_file}
jq < ${result_file}
}
deviceswithstatus() {
curl ${FLAGS} -X GET "https://${UCENTRALSEC}/api/v1/devices?deviceWithStatus=true" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" > ${result_file}
jq < ${result_file}
}
devicecount() {
curl ${FLAGS} -X GET "https://${UCENTRALSEC}/api/v1/devices?countOnly=true" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" > ${result_file}
jq < ${result_file}
}
getfile() {
curl ${FLAGS} -X GET "https://${UCENTRALSEC}/api/v1/file/$2?serialNumber=$1" \
-H "accept: application/octet-stream" \
-H "Authorization: Bearer ${token}" \
-o "$2.pcap"
}
rtty() {
curl ${FLAGS} -X GET "https://${UCENTRALSEC}/api/v1/device/$1/rtty" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" > ${result_file}
jq < ${result_file}
cid=$(cat ${result_file} | jq -r '.connectionId')
vport=$(cat ${result_file} | jq -r '.viewport')
server=$(cat ${result_file} | jq -r '.server')
url=https://${server}:${vport}/connect/${cid}
findbrowser
if [[ "${browser}" != "" ]]
then
${browser} ${url}
fi
}
lifetimestats() {
curl ${FLAGS} -X GET "https://${UCENTRALSEC}/api/v1/device/$1/statistics?lifetime=true" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" > ${result_file}
jq < ${result_file}
}
laststats() {
curl ${FLAGS} -X GET "https://${UCENTRALSEC}/api/v1/device/$1/statistics?lastOnly=true" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" > ${result_file}
jq < ${result_file}
}
lasthealthcheck() {
curl ${FLAGS} -X GET "https://${UCENTRALSEC}/api/v1/device/$1/healthchecks?lastOnly=true" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" > ${result_file}
jq < ${result_file}
}
neweststats() {
curl ${FLAGS} -X GET "https://${UCENTRALSEC}/api/v1/device/$1/statistics?newest=true&limit=50" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" > ${result_file}
jq < ${result_file}
}
newestlogs() {
curl ${FLAGS} -X GET "https://${UCENTRALSEC}/api/v1/device/$1/logs?newest=true&limit=50" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" > ${result_file}
jq < ${result_file}
}
newesthealthchecks() {
curl ${FLAGS} -X GET "https://${UCENTRALSEC}/api/v1/device/$1/healthchecks?newest=true&limit=50" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" > ${result_file}
jq < ${result_file}
}
ouilookup() {
curl ${FLAGS} -X GET "https://${UCENTRALSEC}/api/v1/ouis?macList=$1" \
-H "accept: application/json" \
-H "Authorization: Bearer ${token}" > ${result_file}
jq < ${result_file}
}
help() {
echo
echo "listendpoints Get all the system endpoints."
echo "deletedevice <serial> Delete the device."
echo "createdevice <serial> <cfg> <MAC> Create a device using the default configuration."
echo " cfg: JSON config file name"
echo " <MAC>: string MAC Address"
echo "getdevicestatus <serial> Get the device status JSON document."
echo "getstats <serial> Get statistics for the device."
echo "gethealthchecks <serial> Get healthchecks for a device."
echo "newesthealthchecks <serial> Get newest healthchecks for a device."
echo "lasthealthcheck <serial> Get the last healthcheck"
echo
echo "getcapababilities <serial> Get the device capabilities JSON document."
echo "deletecapababilities <serial> Delete the device capabilities JSON."
echo
echo "reboot <serial> Reboot the device."
echo "upgrade <serial> <URI> Do firmware upgrade for a device."
echo "leds <serial> <pattern> <d> Activate LEDs a device."
echo " pattern: on/off/blink"
echo " d: number in seconds"
echo "configure <serial> <cfg> Change configuration for a device."
echo " cfg must be valid JSON config."
echo "factory <serial> <true/false> Do factory reset for device. true=keep redirector, false=reset redirector"
echo "request <serial> <message> Force a message from the device."
echo " message=state/healthcheck"
echo "wifiscan <serial> <verbose> Do wifiscan for a device."
echo " verbose=true/false"
echo "active <serial> <verbose> Do an active wifiscan for a device."
echo " verbose=true/false"
echo "trace <serial> <d> <n> Launch a remote trace for a device."
echo " d=number of seconds"
echo " n=lan/wan"
echo
echo "getcommand <command-uuid> Get the command JSON document."
echo "deletecommand <command-uuid> Delete the command."
echo "newestcommands <serial> Get the newest commands for a device."
echo "listdevices List devices"
echo "listcommands <serial> List commands for a specific device"
echo "deletecommands <serial> Delete commands for a device."
echo
echo "getlogs <serial> Get logs for the device."
echo "newestlogs <serial> Get the latest logs for the device."
echo "deletelogs <serial> Delete logs for the device."
echo "eventqueue <serial> Request event queue for the device."
echo
echo "listdefaultconfigs List a default configurations"
echo "createdefaultconfig <name> <ids> <cfg> Create a default configuration"
echo " name=unique name, no spaces"
echo " ids=coma separated list of models"
echo " cfg=config file name"
echo
echo "addblacklistdevice <serial> <r> Add a device to the black list"
echo " <r> Reason for blacklisting"
echo "getblacklist List all blacklisted devices"
echo "deleteblacklistdevice <serial> Add a device to the black list"
echo
echo "devicecount Get the number of devices in the DB"
echo "deviceserialnumbers Get only the serial numbers"
echo "selectdevices <serial list> get a list of serial numbers (must be comma separated)"
echo "deviceswithstatus Get devices with their status"
echo
echo "setloglevel <sys> <level> Set the logging system level for individual subsystems."
echo " sys:ufileuploader/websocket/storage/restapi/commandmanager/auth/deviceregistry/all"
echo " level:none/fatal/critical/error/warning/notice/information/debug/trace"
echo "getloglevels Get the log levels of all the subsystems"
echo "getloglevelnames Get the list of log level names possible"
echo "getsubsystemnames Get the subsystems that can be used when setting log levels."
echo "getfile <serial> <uuid> <name> Get the file associated with trace command <uuid> for device <serial>"
echo " The file will be saved with the name <name>"
echo
echo "rtty <serial> Get the details for an rtty session."
echo
echo "lifetimestats <serial> Get the lifetime stats counters for a device"
echo "laststats <serial> Get the last statistics for a device"
echo "neweststats <serial> Get the newest statistics for a device"
echo
echo "ouilookup <serial> Lookup an OUI"
echo
echo
echo "To pass additional flags to the CURL command, create an environment variable called FLAGS and git ve the values you"
echo "want. For example, for force all call to use IPv6, set FLAGS=\"-6\", for verbose mode and IPv6, set FLAGS=\"-6 -v\""
echo
echo
}
shopt -s nocasematch
case "$1" in
"createuser") login; createuser "$2" "$3"; logout;;
"deleteuser") login; deleteuser "$2" ; logout;;
"getuser") login; getuser "$2" ; logout;;
"listusers") login; listusers ; logout ;;
"listendpoints") login; listendpoints ; logout ;;
"help") login; help ; logout ;;
"getcommand") login; getcommand "$2" ; logout ;;
"deletecommand") login; deletecommand "$2" ; logout ;;
"getcapabilities") login; getcapabilities "$2" ; logout ;;
"deletecapabilities") login; deletecapabilities "$2" ; logout ;;
"listdevices") login; listdevices ; logout ;;
"deletedevice") login; deletedevice "$2" ; logout ;;
"createdevice") login; createdevice "$2" "$3" ; logout ;;
"reboot") login; reboot "$2" ; logout ;;
"setloglevel") login; setloglevel "$2" "$3" ; logout ;;
"getdevicestatus") login; getdevicestatus "$2" ; logout ;;
"upgrade") login; upgrade "$2" "$3" ; logout ;;
"factory") login; factory "$2" "$3" ; logout ;;
"leds") login; leds "$2" "$3" "$4" ; logout ;;
"listcommands") login; listcommands "$2" ; logout ;;
"deletecommands") login; deletecommands "$2" ; logout ;;
"configure") login; configure "$2" "$3" ; logout ;;
"request") login; request "$2" "$3" ; logout ;;
"wifiscan") login; wifiscan "$2" "$3" ; logout ;;
"activescan") login; activescan "$2" "$3" ; logout ;;
"trace") login; trace "$2" "$3" "$4" ; logout ;;
"getstats") login; getstats "$2" ; logout ;;
"getlogs") login; getlogs "$2" ; logout ;;
"deletelogs") login; deletelogs "$2" ; logout ;;
"gethealthchecks") login; gethealthchecks "$2" ; logout ;;
"createdefaultconfig") login; createdefaultconfig "$2" "$3" "$4" ; logout ;;
"listdefaultconfigs") login; listdefaultconfigs "$2" ; logout ;;
"addblacklistdevice") login; addblacklistdevice "$2" "$3" ; logout ;;
"deleteblacklistdevice") login; deleteblacklistdevice "$2" ; logout ;;
"getblacklist") login; getblacklist ; logout ;;
"eventqueue") login; eventqueue "$2" ; logout ;;
"selectdevices") login; selectdevices "$2" ; logout ;;
"deviceserialnumbers") login; deviceserialnumbers ; logout ;;
"devicecount") login; devicecount ; logout ;;
"deviceswithstatus") login; deviceswithstatus ; logout ;;
"getfile") login; getfile "$2" "$3" ; logout ;;
"rtty") login; rtty "$2" ; logout ;;
"lifetimestats") login; lifetimestats "$2"; logout;;
"laststats") login; laststats "$2"; logout;;
"newestcommands") login; newestcommands "$2"; logout;;
"neweststats") login; neweststats "$2"; logout;;
"newestlogs") login; newestlogs "$2"; logout;;
"newesthealthchecks") login; newesthealthchecks "$2"; logout;;
"lasthealthcheck") login; lasthealthcheck "$2"; logout;;
"login") login ;;
"findbrowser") findbrowser; echo "Browser: ${browser}" ;;
"getloglevels") login; getloglevels; logout ;;
"getloglevelnames") login; getloglevelnames; logout ;;
"getsubsystemnames") login; getsubsystemnames; logout ;;
"ouilookup") login; ouilookup "$2"; logout;;
*) help ;;
esac