mirror of
https://github.com/outbackdingo/sysadm.git
synced 2026-01-27 02:20:17 +00:00
Merge branch 'master' of github.com:pcbsd/sysadm
This commit is contained in:
@@ -15,18 +15,28 @@
|
||||
#define DEBUG 0
|
||||
#define SCLISTDELIM QString("::::") //SysCache List Delimiter
|
||||
|
||||
RestOutputStruct::ExitCode WebSocket::EvaluateBackendRequest(QString name, const QJsonValue args, QJsonObject *out){
|
||||
RestOutputStruct::ExitCode WebSocket::EvaluateBackendRequest(QString namesp, QString name, const QJsonValue args, QJsonObject *out){
|
||||
/*Inputs:
|
||||
"namesp" - namespace for the request
|
||||
"name" - name of the request
|
||||
"args" - JSON input arguments structure
|
||||
"out" - JSON output arguments structure
|
||||
*/
|
||||
namesp = namesp.toLower(); name = name.toLower();
|
||||
//Go through and forward this request to the appropriate sub-system
|
||||
if(name.toLower()=="syscache"){
|
||||
if(namesp=="rpc" && name=="syscache"){
|
||||
return EvaluateSyscacheRequest(args, out);
|
||||
}else if(name.toLower()=="dispatcher"){
|
||||
}else if(namesp=="rpc" && name=="dispatcher"){
|
||||
return EvaluateSyscacheRequest(args, out);
|
||||
}else if(namesp=="sysadm" && name=="network"){
|
||||
return EvaluateSysadmNetworkRequest(args, out);
|
||||
}else{
|
||||
return RestOutputStruct::BADREQUEST;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//==== SYSCACHE ====
|
||||
RestOutputStruct::ExitCode WebSocket::EvaluateSyscacheRequest(const QJsonValue in_args, QJsonObject *out){
|
||||
//syscache only needs a list of sub-commands at the moment (might change later)
|
||||
QStringList in_req;
|
||||
@@ -59,6 +69,7 @@ RestOutputStruct::ExitCode WebSocket::EvaluateSyscacheRequest(const QJsonValue i
|
||||
return RestOutputStruct::OK;
|
||||
}
|
||||
|
||||
//==== DISPATCHER ====
|
||||
RestOutputStruct::ExitCode WebSocket::EvaluateDispatcherRequest(const QJsonValue in_args, QJsonObject *out){
|
||||
//dispatcher only needs a list of sub-commands at the moment (might change later)
|
||||
QStringList in_req;
|
||||
@@ -80,3 +91,42 @@ RestOutputStruct::ExitCode WebSocket::EvaluateDispatcherRequest(const QJsonValue
|
||||
return RestOutputStruct::OK;
|
||||
}
|
||||
|
||||
//==== SYSADM -- Network ====
|
||||
RestOutputStruct::ExitCode WebSocket::EvaluateSysadmNetworkRequest(const QJsonValue in_args, QJsonObject *out){
|
||||
if(in_args.isObject()){
|
||||
QStringList keys = in_args.toObject().keys();
|
||||
bool ok = false;
|
||||
if(keys.contains("action")){
|
||||
QString act = JsonValueToString(in_args.toObject().value("action"));
|
||||
if(act=="list-devices"){
|
||||
ok = true;
|
||||
QStringList devs = sysadm::NetDevice::listNetDevices();
|
||||
for(int i=0; i<devs.length(); i++){
|
||||
sysadm::NetDevice D(devs[i]);
|
||||
QJsonObject obj;
|
||||
//assemble the information about this device into an output object
|
||||
obj.insert("ipv4", D.ipAsString());
|
||||
obj.insert("ipv6", D.ipv6AsString());
|
||||
obj.insert("netmask", D.netmaskAsString());
|
||||
obj.insert("description", D.desc());
|
||||
obj.insert("MAC", D.macAsString());
|
||||
obj.insert("status", D.mediaStatusAsString());
|
||||
obj.insert("is_active", D.isUp() ? "true" : "false" );
|
||||
obj.insert("is_dhcp", D.usesDHCP() ? "true" : "false" );
|
||||
obj.insert("is_wireless", D.isWireless() ? "true" : "false" );
|
||||
//Add this device info to the main output structure
|
||||
out->insert(devs[i], obj);
|
||||
}
|
||||
}
|
||||
|
||||
} //end of "action" key usage
|
||||
|
||||
//If nothing done - return the proper code
|
||||
if(!ok){
|
||||
return RestOutputStruct::BADREQUEST;
|
||||
}
|
||||
}else{ // if(in_args.isArray()){
|
||||
return RestOutputStruct::BADREQUEST;
|
||||
}
|
||||
return RestOutputStruct::OK;
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ void WebSocket::EvaluateREST(QString msg){
|
||||
qDebug() << " - Name:" << IN.name;
|
||||
qDebug() << " - Namespace:" << IN.namesp;
|
||||
qDebug() << " - ID:" << IN.id;
|
||||
qDebug() << " - Has Args:" << IN.args.isNull();
|
||||
qDebug() << " - Has Args:" << !IN.args.isNull();
|
||||
}
|
||||
//Now check for the REST-specific verbs/actions
|
||||
if(IN.VERB == "OPTIONS" || IN.VERB == "HEAD"){
|
||||
@@ -113,27 +113,7 @@ void WebSocket::EvaluateRequest(const RestInputStruct &REQ){
|
||||
out.CODE = RestOutputStruct::BADREQUEST;
|
||||
}else{
|
||||
//Now check the body of the message and do what it needs
|
||||
/*QJsonDocument doc = QJsonDocument::fromJson(REQ.Body.toUtf8());
|
||||
if(doc.isNull()){ qWarning() << "Empty JSON Message Body!!" << REQ.Body.toUtf8(); }
|
||||
//Define the output structures
|
||||
QJsonObject ret; //return message
|
||||
|
||||
//Objects contain other key/value pairs - this is 99% of cases
|
||||
if(doc.isObject()){
|
||||
//First check/set all the various required fields (both in and out)
|
||||
bool good = doc.object().contains("namespace") \
|
||||
&& doc.object().contains("name") \
|
||||
&& doc.object().contains("id") \
|
||||
&& doc.object().contains("args");
|
||||
//Can add some fallbacks for missing fields here - but not implemented yet
|
||||
*/
|
||||
//parse the message and do something
|
||||
//if(good && (JsonValueToString(doc.object().value("namespace"))=="rpc") ){
|
||||
if(out.in_struct.namesp.toLower() == "rpc"){
|
||||
//Now fetch the outputs from the appropriate subsection
|
||||
//Note: Each subsection needs to set the "name", "namespace", and "args" output objects
|
||||
//QString name = JsonValueToString(doc.object().value("name")).toLower();
|
||||
//QJsonValue args = doc.object().value("args");
|
||||
if(out.in_struct.name.startsWith("auth")){
|
||||
//Now perform authentication based on type of auth given
|
||||
//Note: This sets/changes the current SockAuthToken
|
||||
@@ -156,43 +136,32 @@ void WebSocket::EvaluateRequest(const RestInputStruct &REQ){
|
||||
//Now check the auth and respond appropriately
|
||||
if(AUTHSYSTEM->checkAuth(SockAuthToken)){
|
||||
//Good Authentication - return the new token
|
||||
//ret.insert("namespace", QJsonValue("rpc"));
|
||||
//ret.insert("name", QJsonValue("response"));
|
||||
//ret.insert("id", doc.object().value("id")); //use the same ID for the return message
|
||||
QJsonArray array;
|
||||
array.append(SockAuthToken);
|
||||
array.append(AUTHSYSTEM->checkAuthTimeoutSecs(SockAuthToken));
|
||||
out.out_args = array;
|
||||
out.CODE = RestOutputStruct::OK;
|
||||
}else{
|
||||
SockAuthToken.clear(); //invalid token
|
||||
//Bad Authentication - return error
|
||||
out.CODE = RestOutputStruct::UNAUTHORIZED;
|
||||
//SetOutputError(&ret, JsonValueToString(out.in_struct.id), 401, "Unauthorized");
|
||||
}
|
||||
|
||||
}else if( AUTHSYSTEM->checkAuth(SockAuthToken) ){ //validate current Authentication token
|
||||
//Now provide access to the various subsystems
|
||||
//Pre-set any output fields
|
||||
QJsonObject outargs;
|
||||
//ret.insert("namespace", QJsonValue("rpc"));
|
||||
//ret.insert("name", QJsonValue("response"));
|
||||
//ret.insert("id", doc.object().value("id")); //use the same ID for the return message
|
||||
out.CODE = EvaluateBackendRequest(out.in_struct.name, out.in_struct.args, &outargs);
|
||||
out.out_args = outargs; //ret.insert("args",outargs);
|
||||
out.CODE = EvaluateBackendRequest(out.in_struct.namesp, out.in_struct.name, out.in_struct.args, &outargs);
|
||||
out.out_args = outargs;
|
||||
}else{
|
||||
out.CODE = RestOutputStruct::UNAUTHORIZED;
|
||||
//Bad/No authentication
|
||||
//SetOutputError(&ret, JsonValueToString(doc.object().value("id")), 401, "Unauthorized");
|
||||
out.CODE = RestOutputStruct::UNAUTHORIZED;
|
||||
}
|
||||
|
||||
//}else if(good && (JsonValueToString(doc.object().value("namespace"))=="events") ){
|
||||
}else if(out.in_struct.namesp.toLower() == "events"){
|
||||
if( AUTHSYSTEM->checkAuth(SockAuthToken) ){ //validate current Authentication token
|
||||
//Pre-set any output fields
|
||||
QJsonObject outargs;
|
||||
//ret.insert("namespace", QJsonValue("events"));
|
||||
//ret.insert("name", QJsonValue("response"));
|
||||
//ret.insert("id", doc.object().value("id")); //use the same ID for the return message
|
||||
//Assemble the list of input events
|
||||
QStringList evlist;
|
||||
if(out.in_struct.args.isObject()){ evlist << JsonValueToString(out.in_struct.args); }
|
||||
@@ -212,86 +181,32 @@ void WebSocket::EvaluateRequest(const RestInputStruct &REQ){
|
||||
}else{
|
||||
outargs.insert("unknown",QJsonValue("unknown"));
|
||||
}
|
||||
//ret.insert("args",outargs);
|
||||
out.out_args = outargs;
|
||||
}else{
|
||||
//Bad/No authentication
|
||||
out.CODE = RestOutputStruct::UNAUTHORIZED;
|
||||
//SetOutputError(&ret, JsonValueToString(doc.object().value("id")), 401, "Unauthorized");
|
||||
}
|
||||
}else{
|
||||
//Other namespace - check whether auth has already been established before continuing
|
||||
}else if( AUTHSYSTEM->checkAuth(SockAuthToken) ){ //validate current Authentication token
|
||||
//Now provide access to the various subsystems
|
||||
//Pre-set any output fields
|
||||
QJsonObject outargs;
|
||||
out.CODE = EvaluateBackendRequest(out.in_struct.namesp, out.in_struct.name, out.in_struct.args, &outargs);
|
||||
out.out_args = outargs;
|
||||
}else{
|
||||
//Error in inputs - assemble the return error message
|
||||
out.CODE = RestOutputStruct::BADREQUEST;
|
||||
/*QString id = "error";
|
||||
if(doc.object().contains("id")){ id = JsonValueToString(doc.object().value("id")); } //use the same ID
|
||||
SetOutputError(&ret, id, 400, "Bad Request");*/
|
||||
}
|
||||
//Assemble the outputs for this "GET" request
|
||||
out.CODE = RestOutputStruct::OK;
|
||||
//Assemble the output JSON document/text
|
||||
//QJsonDocument retdoc;
|
||||
//retdoc.setObject(ret);
|
||||
//out.Body = retdoc.toJson();
|
||||
out.Header << "Content-Type: text/json; charset=utf-8";
|
||||
}
|
||||
//If this is a REST input - go ahead and format the output header
|
||||
if(out.CODE == RestOutputStruct::OK){
|
||||
out.Header << "Content-Type: text/json; charset=utf-8";
|
||||
}
|
||||
}
|
||||
//Return any information
|
||||
if(SOCKET!=0){ SOCKET->sendTextMessage(out.assembleMessage()); }
|
||||
if(SOCKET!=0){ SOCKET->sendTextMessage(out.assembleMessage()); }
|
||||
else if(TSOCKET!=0){ TSOCKET->write(out.assembleMessage().toUtf8().data()); }
|
||||
}
|
||||
|
||||
// === SYSCACHE REQUEST INTERACTION ===
|
||||
/*void WebSocket::EvaluateBackendRequest(QString name, const QJsonValue args, QJsonObject *out){
|
||||
QJsonObject obj; //output object
|
||||
if(args.isObject()){
|
||||
//For the moment: all arguments are full syscache DB calls - no special ones
|
||||
QStringList reqs = args.toObject().keys();
|
||||
if(!reqs.isEmpty()){
|
||||
if(DEBUG){ qDebug() << "Parsing Inputs:" << reqs; }
|
||||
for(int r=0; r<reqs.length(); r++){
|
||||
QString req = JsonValueToString(args.toObject().value(reqs[r]));
|
||||
if(DEBUG){ qDebug() << " ["+reqs[r]+"]="+req; }
|
||||
QStringList values;
|
||||
if(name.toLower()=="syscache"){values = SysCacheClient::parseInputs( QStringList() << req ); }
|
||||
else if(name.toLower()=="dispatcher"){values = DispatcherClient::parseInputs( QStringList() << req, AUTHSYSTEM); }
|
||||
values.removeAll("");
|
||||
//Quick check if a list of outputs was returned
|
||||
if(values.length()==1 && name.toLower()=="syscache"){
|
||||
values = values[0].split(SCLISTDELIM); //split up the return list (if necessary)
|
||||
values.removeAll("");
|
||||
}
|
||||
if(DEBUG){ qDebug() << " - Returns:" << values; }
|
||||
if(values.length()<2){ out->insert(req, QJsonValue(values.join("")) ); }
|
||||
else{
|
||||
//This is an array of outputs
|
||||
QJsonArray arr;
|
||||
for(int i=0; i<values.length(); i++){ arr.append(values[i]); }
|
||||
out->insert(req,arr);
|
||||
}
|
||||
}
|
||||
} //end of special "request" objects
|
||||
}else if(args.isArray()){
|
||||
QStringList inputs = JsonArrayToStringList(args.toArray());
|
||||
if(DEBUG){ qDebug() << "Parsing Array inputs:" << inputs; }
|
||||
QStringList values;
|
||||
if(name.toLower()=="syscache"){values = SysCacheClient::parseInputs( inputs ); }
|
||||
else if(name.toLower()=="dispatcher"){values = DispatcherClient::parseInputs( inputs , AUTHSYSTEM); }
|
||||
if(DEBUG){ qDebug() << " - Returns:" << values; }
|
||||
for(int i=0; i<values.length(); i++){
|
||||
if(name.toLower()=="syscache" && values[i].contains(SCLISTDELIM)){
|
||||
//This is an array of values from syscache
|
||||
QStringList vals = values[i].split(SCLISTDELIM);
|
||||
vals.removeAll("");
|
||||
QJsonArray arr;
|
||||
for(int j=0; j<vals.length(); j++){ arr.append(vals[j]); }
|
||||
out->insert(inputs[i],arr);
|
||||
}else{
|
||||
out->insert(inputs[i],values[i]);
|
||||
}
|
||||
}
|
||||
} //end array of inputs
|
||||
|
||||
}*/
|
||||
|
||||
// === GENERAL PURPOSE UTILITY FUNCTIONS ===
|
||||
QString WebSocket::JsonValueToString(QJsonValue val){
|
||||
//Note: Do not use this on arrays - only use this on single-value values
|
||||
@@ -314,23 +229,13 @@ QString WebSocket::JsonValueToString(QJsonValue val){
|
||||
QStringList WebSocket::JsonArrayToStringList(QJsonArray array){
|
||||
//Note: This assumes that the array is only values, not additional objects
|
||||
QStringList out;
|
||||
qDebug() << "Array to List:" << array.count();
|
||||
if(DEBUG){ qDebug() << "Array to List:" << array.count(); }
|
||||
for(int i=0; i<array.count(); i++){
|
||||
out << JsonValueToString(array.at(i));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
void WebSocket::SetOutputError(QJsonObject *ret, QString id, int err, QString msg){
|
||||
ret->insert("namespace", QJsonValue("rpc"));
|
||||
ret->insert("name", QJsonValue("error"));
|
||||
ret->insert("id",QJsonValue(id));
|
||||
QJsonObject obj;
|
||||
obj.insert("code", err);
|
||||
obj.insert("message", QJsonValue(msg));
|
||||
ret->insert("args",obj);
|
||||
}
|
||||
|
||||
// =====================
|
||||
// PRIVATE SLOTS
|
||||
// =====================
|
||||
@@ -366,7 +271,7 @@ void WebSocket::EvaluateMessage(const QByteArray &msg){
|
||||
if(idletimer->isActive()){ idletimer->stop(); }
|
||||
EvaluateREST( QString(msg) );
|
||||
idletimer->start();
|
||||
qDebug() << "Done with Message";
|
||||
qDebug() << " - Done with Binary Message";
|
||||
}
|
||||
|
||||
void WebSocket::EvaluateMessage(const QString &msg){
|
||||
@@ -374,7 +279,7 @@ void WebSocket::EvaluateMessage(const QString &msg){
|
||||
if(idletimer->isActive()){ idletimer->stop(); }
|
||||
EvaluateREST(msg);
|
||||
idletimer->start();
|
||||
qDebug() << "Done with Message";
|
||||
qDebug() << " - Done with Text Message";
|
||||
}
|
||||
|
||||
void WebSocket::EvaluateTcpMessage(){
|
||||
@@ -383,7 +288,7 @@ void WebSocket::EvaluateTcpMessage(){
|
||||
if(idletimer->isActive()){ idletimer->stop(); }
|
||||
EvaluateREST( QString(TSOCKET->readAll()) );
|
||||
idletimer->start();
|
||||
qDebug() << "Done with Message";
|
||||
qDebug() << " - Done with TCP Message";
|
||||
}
|
||||
|
||||
// ======================
|
||||
@@ -398,23 +303,14 @@ void WebSocket::AppCafeStatusUpdate(QString msg){
|
||||
out.CODE = RestOutputStruct::OK;
|
||||
out.in_struct.name = "event";
|
||||
out.in_struct.namesp = "events";
|
||||
//Define the output structures
|
||||
//QJsonObject ret; //return message
|
||||
//Pre-set any output fields
|
||||
QJsonObject outargs;
|
||||
//ret.insert("namespace", QJsonValue("events"));
|
||||
//ret.insert("name", QJsonValue("event"));
|
||||
//ret.insert("id", QJsonValue(""));
|
||||
outargs.insert("name", "dispatcher");
|
||||
outargs.insert("args",QJsonValue(msg));
|
||||
out.out_args = outargs;
|
||||
//ret.insert("args",outargs);
|
||||
out.out_args = outargs;
|
||||
|
||||
//Assemble the output JSON document/text
|
||||
//QJsonDocument retdoc;
|
||||
//retdoc.setObject(ret);
|
||||
//out.Body = retdoc.toJson();
|
||||
out.Header << "Content-Type: text/json; charset=utf-8";
|
||||
//Assemble the output JSON document/text
|
||||
out.Header << "Content-Type: text/json; charset=utf-8"; //REST header info
|
||||
//Now send the message back through the socket
|
||||
if(SOCKET!=0){ SOCKET->sendTextMessage(out.assembleMessage()); }
|
||||
else if(TSOCKET!=0){ TSOCKET->write(out.assembleMessage().toUtf8().data()); }
|
||||
|
||||
@@ -45,15 +45,16 @@ private:
|
||||
//Simplification functions
|
||||
QString JsonValueToString(QJsonValue);
|
||||
QStringList JsonArrayToStringList(QJsonArray);
|
||||
void SetOutputError(QJsonObject *ret, QString id, int err, QString msg);
|
||||
|
||||
//Backend request/reply functions (contained in WebBackend.cpp)
|
||||
// -- Main subsystem parser
|
||||
RestOutputStruct::ExitCode EvaluateBackendRequest(QString name, const QJsonValue in_args, QJsonObject *out);
|
||||
RestOutputStruct::ExitCode EvaluateBackendRequest(QString namesp, QString name, const QJsonValue in_args, QJsonObject *out);
|
||||
// -- Individual subsystems
|
||||
RestOutputStruct::ExitCode EvaluateSyscacheRequest(const QJsonValue in_args, QJsonObject *out);
|
||||
RestOutputStruct::ExitCode EvaluateDispatcherRequest(const QJsonValue in_args, QJsonObject *out);
|
||||
|
||||
// -- sysadm library/subsystems
|
||||
RestOutputStruct::ExitCode EvaluateSysadmNetworkRequest(const QJsonValue in_args, QJsonObject *out);
|
||||
|
||||
private slots:
|
||||
void checkIdle(); //see if the currently-connected client is idle
|
||||
void SocketClosing();
|
||||
|
||||
Reference in New Issue
Block a user