mirror of
https://github.com/Telecominfraproject/wlan-cloud-ucentralsec.git
synced 2025-11-01 19:27:59 +00:00
Initial checkin for username creation
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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:
|
||||
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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") {
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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_);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user