Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
using GSF.Data;
using GSF.Data.Model;
using GSF.Web.Model;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using openXDA.Model;
using SystemCenter.Model;
Expand All @@ -57,16 +58,24 @@ private class extendedAssetGroupView: AssetGroupView

}

[HttpGet, Route("{assetGroupID:int}/Assets")]
public IHttpActionResult GetAssets(int assetGroupID)
[HttpPost, Route("{assetGroupID:int}/Assets/{page:int}")]
public IHttpActionResult GetAssets([FromBody] PostData postData, [FromUri] int assetGroupID, [FromUri] int page)
{
if (GetRoles == string.Empty || User.IsInRole(GetRoles))
{

HashSet<string> validSortFields = new HashSet<string> { "assetname", "assetkey", "assettype" };

if (!validSortFields.Contains(postData.OrderBy.ToLower()))
return BadRequest($"{postData.OrderBy} is not a valid sort field.");

using (AdoDataConnection connection = new AdoDataConnection(Connection))
{
try
{
string sql = @"SELECT
int recordsPerPage = PageSize ?? 50;

string sql = @$"SELECT
DISTINCT
Asset.ID,
AssetAssetGroup.AssetGroupID,
Expand All @@ -91,9 +100,30 @@ GROUP BY
Asset.VoltageKV,
AssetType.Name,
AssetAssetGroup.AssetGroupID
HAVING AssetAssetGroup.AssetGroupID = {0}";
HAVING AssetAssetGroup.AssetGroupID = {{0}}
ORDER BY {postData.OrderBy} {(postData.Ascending ? "ASC" : "DESC")}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This introduces SQLInjection {postData.OrderBy}

OFFSET {recordsPerPage * page} ROWS
FETCH NEXT {recordsPerPage} ROWS ONLY
";

return Ok(connection.RetrieveData(sql,assetGroupID));
string countSql = @"SELECT
COUNT(DISTINCT AssetID)
FROM
AssetAssetGroup
WHERE
AssetGroupID = {0}";

int count = connection.ExecuteScalar<int>(countSql, assetGroupID);

DataTable results = connection.RetrieveData(sql, assetGroupID);

return Ok(new PagedResults()
{
Data = JsonConvert.SerializeObject(results),
NumberOfPages = (count + recordsPerPage - 1) / recordsPerPage,
TotalRecords = count,
RecordsPerPage = recordsPerPage
});
}
catch (Exception ex)
{
Expand Down Expand Up @@ -159,16 +189,23 @@ public IHttpActionResult RemoveAsset(int assetGroupID, int assetID)
}
}

[HttpGet, Route("{assetGroupID:int}/Meters")]
public IHttpActionResult GetMeters(int assetGroupID)
[HttpPost, Route("{assetGroupID:int}/Meters/{page:int}")]
public IHttpActionResult GetMeters([FromBody] PostData postData, [FromUri] int assetGroupID, [FromUri] int page)
{
if (GetRoles == string.Empty || User.IsInRole(GetRoles))
{
string[] validSortFields = { "name", "location" };

if (!validSortFields.Any(field => String.Equals(field, postData.OrderBy.ToLower())))
return BadRequest($"{postData.OrderBy} is not a valid sort field.");

using (AdoDataConnection connection = new AdoDataConnection(Connection))
{
try
{
string sql = @"SELECT DISTINCT
int recordsPerPage = PageSize ?? 50;

string sql = @$"SELECT DISTINCT
Meter.ID,
MeterAssetGroup.AssetGroupID,
Meter.AssetKey,
Expand All @@ -177,6 +214,28 @@ public IHttpActionResult GetMeters(int assetGroupID)
Meter.Model,
Location.Name as Location,
COUNT(DISTINCT MeterAsset.AssetID) as MappedAssets
FROM
Meter LEFT JOIN
Location ON Meter.LocationID = Location.ID LEFT JOIN
MeterAsset ON Meter.ID = MeterAsset.MeterID LEFT JOIN
Asset ON MeterAsset.AssetID = Asset.ID LEFT JOIN
MeterAssetGroup ON Meter.ID = MeterAssetGroup.MeterID
GROUP BY
Meter.ID,
Meter.AssetKey,
Meter.Name,
Meter.Make,
Meter.Model,
Location.Name,
MeterAssetGroup.AssetGroupID
HAVING MeterAssetGroup.AssetGroupID = {{0}}
ORDER BY {postData.OrderBy} {(postData.Ascending ? "ASC" : "DESC")}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This introduces SQLInjection {postData.OrderBy}

OFFSET {recordsPerPage * page} ROWS
FETCH NEXT {recordsPerPage} ROWS ONLY"
;

string countSql = @"SELECT
COUNT(DISTINCT Meter.ID)
FROM
Meter LEFT JOIN
Location ON Meter.LocationID = Location.ID LEFT JOIN
Expand All @@ -193,7 +252,17 @@ GROUP BY
MeterAssetGroup.AssetGroupID
HAVING MeterAssetGroup.AssetGroupID = {0}";

return Ok(connection.RetrieveData(sql,assetGroupID));
int count = connection.ExecuteScalar<int>(countSql, assetGroupID);

DataTable results = connection.RetrieveData(sql, assetGroupID);

return Ok(new PagedResults()
{
Data = JsonConvert.SerializeObject(results),
TotalRecords = count,
RecordsPerPage = recordsPerPage,
NumberOfPages = (count + recordsPerPage - 1) / recordsPerPage
});
}
catch (Exception ex)
{
Expand Down Expand Up @@ -283,18 +352,32 @@ public IHttpActionResult GetUserAccounts(int assetGroupID)
return Unauthorized();
}

[HttpGet, Route("{assetGroupID:int}/AssetGroups")]
public IHttpActionResult GetSubGroups(int assetGroupID)
[HttpPost, Route("{assetGroupID:int}/AssetGroups/{page:int}")]
public IHttpActionResult GetSubGroupsPaged([FromBody] PostData postData, [FromUri] int assetGroupID, [FromUri] int page)
{
if (GetRoles == string.Empty || User.IsInRole(GetRoles))
{
using (AdoDataConnection connection = new AdoDataConnection(Connection))
{
try
{
IEnumerable<AssetGroupView> records = new TableOperations<AssetGroupView>(connection).QueryRecordsWhere("ID in (SELECT ChildAssetGroupID FROM AssetGroupAssetGroupView WHERE ParentAssetGroupID = {0})", assetGroupID);
int recordsPerPage = PageSize ?? 50;

return Ok(records);
TableOperations<AssetGroupView> table = new TableOperations<AssetGroupView>(connection);

RecordRestriction recordRestriction = new RecordRestriction("ID in (SELECT ChildAssetGroupID FROM AssetGroupAssetGroupView WHERE ParentAssetGroupID = {0})", assetGroupID);

int count = table.QueryRecordCount(recordRestriction);

IEnumerable<AssetGroupView> records = new TableOperations<AssetGroupView>(connection).QueryRecords(postData.OrderBy, postData.Ascending, page + 1, recordsPerPage, recordRestriction);

return Ok(new PagedResults()
{
Data = JsonConvert.SerializeObject(records),
TotalRecords = count,
RecordsPerPage = recordsPerPage,
NumberOfPages = (count + recordsPerPage - 1) / recordsPerPage
});
}
catch (Exception ex)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public IHttpActionResult GetAssetLocationsPaged([FromBody] PostData postData, [F
if (!GetAuthCheck())
return Unauthorized();

int recordsPerPage = Take ?? 50;
int recordsPerPage = PageSize ?? 50;

PagedResults results = new PagedResults();

Expand Down Expand Up @@ -164,7 +164,7 @@ public IHttpActionResult GetAssetMetersPaged([FromBody] PostData postData, [From
{
try
{
int recordsPerPage = Take ?? 50;
int recordsPerPage = PageSize ?? 50;

string[] sortFields = { "AssetKey", "Name", "Make", "Model" };

Expand Down Expand Up @@ -200,11 +200,16 @@ public IHttpActionResult GetAssetAssetConnections([FromBody] PostData postData,
{
if (GetRoles == string.Empty || User.IsInRole(GetRoles))
{
HashSet<string> validSortFields = new HashSet<string> { "assetname", "assetkey", "name" };

if (!validSortFields.Contains(postData.OrderBy.ToLower()))
return BadRequest($"{postData.OrderBy} is not a valid sort field.");

using (AdoDataConnection connection = new AdoDataConnection(Connection))
{
try
{
int recordsPerPage = Take ?? 50;
int recordsPerPage = PageSize ?? 50;

string[] sortFields = { "AssetName", "AssetKey", "Name" };

Expand Down Expand Up @@ -686,15 +691,17 @@ public IHttpActionResult PostExistingMeterForAsset(int assetID, int meterID)
}
}

[HttpGet, Route("{assetID:int}/ConnectedChannels")]
public IHttpActionResult GetAssetChannels(int assetID)
[HttpPost, Route("{assetID:int}/ConnectedChannels/{page:int}")]
public IHttpActionResult GetAssetChannels([FromBody] PostData postData, [FromUri] int assetID, [FromUri] int page)
{
if (GetRoles == string.Empty || User.IsInRole(GetRoles))
{
try
{
using (AdoDataConnection connection = new AdoDataConnection(Connection))
{
int recordsPerPage = PageSize ?? 50;

Asset asset = new TableOperations<Asset>(connection).QueryRecordWhere("ID={0}", assetID);
if (asset is null)
throw (new Exception($"Asset ID={assetID} not found in OpenXDA database"));
Expand All @@ -706,17 +713,43 @@ public IHttpActionResult GetAssetChannels(int assetID)

if (connectedChannels.Count > 0)
{
TableOperations<ChannelDetail> tableOp = new TableOperations<ChannelDetail>(connection);
// Channels get triplicated from Series Type ID in ChannelDetail View
IEnumerable<ChannelDetail> uniqueChannels = new TableOperations<ChannelDetail>(connection)
.QueryRecordsWhere($"ID in ({string.Join(", ", connectedChannels.Select(channels => channels.ID))})")
.DistinctBy(c => c.ID);

return Ok(uniqueChannels);
string countSql = $@"
SELECT COUNT(*)
FROM ChannelDetail
WHERE ID in ({string.Join(", ", connectedChannels.Select(channels => channels.ID))})
";

string sql = @$"
SELECT *
FROM ChannelDetail
WHERE ID in ({string.Join(", ", connectedChannels.Select(channels => channels.ID))})
ORDER BY {postData.OrderBy} {(postData.Ascending ? "ASC" : "DESC")}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This introduces SQLInjection {postData.OrderBy}

OFFSET {page * recordsPerPage} ROWS
FETCH NEXT {recordsPerPage} ROWS ONLY
";

int count = connection.ExecuteScalar<int>(countSql);

DataTable results = connection.RetrieveData(sql);

return Ok(new PagedResults()
{
Data = JsonConvert.SerializeObject(results),
RecordsPerPage = recordsPerPage,
TotalRecords = count,
NumberOfPages = (count + recordsPerPage - 1) / recordsPerPage
});
}
else
{
return Ok(new List<ChannelDetail>());
return Ok(new PagedResults()
{
Data = JsonConvert.SerializeObject(new List<string>()), // just return an empty list
RecordsPerPage = recordsPerPage,
TotalRecords = 0,
NumberOfPages = 0
});
}
}
} catch (Exception ex)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
using GSF.Data;
using GSF.Data.Model;
using GSF.Web.Model;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using openXDA.Model;
using SystemCenter.Model;
Expand Down Expand Up @@ -94,6 +95,38 @@ record = record.Concat(new TableOperations<LineSegment>(connection).QueryRecords

}

[HttpPost, Route("{lineID:int}/LineSegments/{page:int}")]
public IHttpActionResult GetLineSegmentsForLinePaged([FromBody] PostData postData, [FromUri] int lineID, [FromUri] int page)
{
if (GetRoles == string.Empty || User.IsInRole(GetRoles))
{
int recordsPerPage = PageSize ?? 50;

using (AdoDataConnection connection = new AdoDataConnection(Connection))
{
RecordRestriction restriction = new RecordRestriction(@"ID in (select ChildID from AssetRelationship where AssetRelationshipTypeID = (SELECT ID FROM AssetRelationshipType WHERE Name = 'Line-LineSegment') AND ParentID = {0})
OR ID in (select ParentID from AssetRelationship where AssetRelationshipTypeID = (SELECT ID FROM AssetRelationshipType WHERE Name = 'Line-LineSegment') AND ChildID = {0})", lineID);

TableOperations<LineSegment> tbl = new TableOperations<LineSegment>(connection);

int count = tbl.QueryRecordCount(restriction);

IEnumerable<LineSegment> records = tbl.QueryRecords(postData.OrderBy, postData.Ascending, page + 1, recordsPerPage, restriction);

return Ok(new PagedResults()
{
Data = JsonConvert.SerializeObject(records),
RecordsPerPage = recordsPerPage,
TotalRecords = count,
NumberOfPages = (count + recordsPerPage - 1) / recordsPerPage
});
}
}
else
return Unauthorized();

}

public override IHttpActionResult Post([FromBody] JObject record)
{
if (PostRoles == string.Empty || User.IsInRole(PostRoles))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public class OpenXDAMeterConfigurationController : ModelController<MeterConfigur
[HttpGet, Route("Meter/{meterID:int}/{page:int}")]
public IHttpActionResult GetMeterConfigurationsForMeter(int meterID, int page)
{
int recordsPerPage = 50;
int recordsPerPage = PageSize ?? 50;
if (GetRoles == string.Empty || User.IsInRole(GetRoles))
{
using (AdoDataConnection connection = new AdoDataConnection(Connection))
Expand Down Expand Up @@ -93,7 +93,7 @@ ORDER BY
[HttpGet, Route("{meterConfigurationID:int}/FilesProcessed/{page:int}")]
public IHttpActionResult GetFilesProcessedForMeterConfigurations(int meterConfigurationID, int page)
{
int recordsPerPage = 50;
int recordsPerPage = PageSize ?? 50;
if (GetRoles == string.Empty || User.IsInRole(GetRoles))
{
using (AdoDataConnection connection = new AdoDataConnection(Connection))
Expand Down
Loading