Skip to content

Commit ac7d311

Browse files
committed
enable odata api
1 parent ca70058 commit ac7d311

File tree

4 files changed

+146
-4
lines changed

4 files changed

+146
-4
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Configuration;
4+
using System.Linq;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
8+
namespace CxAnalytix.Configuration.Impls
9+
{
10+
public sealed class CxSASTAPIOverrides : ConfigurationElement
11+
{
12+
13+
[ConfigurationProperty("Project", IsRequired = false, DefaultValue = false)]
14+
public bool Project
15+
{
16+
get => (bool)this["Project"];
17+
set => this["Project"] = value;
18+
}
19+
}
20+
}

Libs/Configuration/Impls/CxSASTConnection.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,11 @@ public String MNOUrl
1414
set { this["mnoURL"] = value; }
1515
}
1616

17+
[ConfigurationProperty("UseOdata", IsRequired = false)]
18+
public CxSASTAPIOverrides Overrides
19+
{
20+
get => (CxSASTAPIOverrides)this["UseOdata"];
21+
set => this["UseOdata"] = value;
22+
}
1723
}
1824
}

Libs/CxRestClient/SAST/CxProjects.cs

Lines changed: 118 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@ public class CxProjects
1818
{
1919
private static ILog _log = LogManager.GetLogger(typeof(CxProjects));
2020

21-
private static String URL_SUFFIX = "cxrestapi/projects";
21+
private static readonly String REST_URL_SUFFIX = "cxrestapi/projects";
22+
23+
private static readonly int ODATA_TOP = 25;
24+
private static readonly String ODATA_URL_SUFFIX = "cxwebinterface/odata/v1/Projects?$expand=CustomFields&$select=OwningTeamId,PresetId,Id,Name,IsPublic" +
25+
$"&$orderby=Id asc&$top={ODATA_TOP}";
2226

2327
private static String _apiVersion = null;
2428

@@ -41,29 +45,94 @@ private static String GetApiVersion(CxSASTRestContext ctx, CancellationToken tok
4145
private CxProjects()
4246
{ }
4347

48+
#region DTOs
49+
4450
[JsonObject(MemberSerialization.OptIn)]
4551
public class ProjectCustomFields
4652
{
4753
[JsonProperty(PropertyName = "name")]
4854
public String FieldName { get; internal set; }
55+
56+
[JsonProperty(PropertyName = "FieldName")]
57+
private String odata_FieldName
58+
{
59+
get => FieldName;
60+
set => FieldName = value;
61+
}
62+
63+
4964
[JsonProperty(PropertyName = "value")]
5065
public String FieldValue { get; internal set; }
66+
67+
[JsonProperty(PropertyName = "FieldValue")]
68+
private String odata_FieldValue
69+
{
70+
get => FieldValue;
71+
set => FieldValue = value;
72+
}
73+
5174
}
5275

5376
[JsonObject(MemberSerialization.OptIn)]
5477
public class Project
5578
{
5679
[JsonProperty(PropertyName = "teamId")]
5780
public String TeamId { get; internal set; }
81+
[JsonProperty(PropertyName = "OwningTeamId")]
82+
private String odata_TeamId
83+
{
84+
get => TeamId;
85+
set => TeamId = value;
86+
}
87+
88+
89+
5890
public int PresetId { get; internal set; }
91+
92+
5993
[JsonProperty(PropertyName = "id")]
6094
public int ProjectId { get; internal set; }
95+
[JsonProperty(PropertyName = "Id")]
96+
private int odata_ProjectId
97+
{
98+
get => ProjectId;
99+
set => ProjectId = value;
100+
}
101+
102+
61103
[JsonProperty(PropertyName = "name")]
62104
public String ProjectName { get; internal set; }
105+
[JsonProperty(PropertyName = "Name")]
106+
private String odata_ProjectName
107+
{
108+
get => ProjectName;
109+
set => ProjectName = value;
110+
}
111+
112+
113+
114+
63115
[JsonProperty(PropertyName = "isPublic")]
64116
public bool IsPublic { get; internal set; }
117+
[JsonProperty(PropertyName = "IsPublic")]
118+
private bool odata_IsPublic
119+
{
120+
get => IsPublic;
121+
set => IsPublic = value;
122+
}
123+
124+
125+
65126
[JsonProperty(PropertyName = "customFields")]
66127
public List<ProjectCustomFields> CustomFields { get; internal set; }
128+
[JsonProperty(PropertyName = "CustomFields")]
129+
private List<ProjectCustomFields> odata_CustomFields
130+
{
131+
get => CustomFields;
132+
set => CustomFields = value;
133+
}
134+
135+
67136

68137
[JsonProperty(PropertyName = "isBranched")]
69138
public bool IsBranched { get; internal set; }
@@ -78,6 +147,7 @@ public class Project
78147
public override string ToString() =>
79148
$"{ProjectId}:{ProjectName} [TeamId: {TeamId} Public: {IsPublic} CustomFields: {CustomFields.Count}]";
80149
}
150+
#endregion
81151

82152
private class ProjectReader : IEnumerable<Project>, IEnumerator<Project>, IDisposable
83153
{
@@ -161,12 +231,57 @@ public void Reset()
161231
{
162232
throw new NotImplementedException();
163233
}
234+
}
164235

236+
private static IEnumerable<Project> GetProjects_odata(CxSASTRestContext ctx, CancellationToken token)
237+
{
238+
List<Project> returnedResults = new();
239+
240+
var filter = new Dictionary<String, String>();
241+
List<Project> fetchedPage = null;
242+
243+
do
244+
{
245+
String requestUrl = UrlUtils.MakeUrl(ctx.Sast.ApiUrl, ODATA_URL_SUFFIX, filter);
165246

247+
using (var projectReader = WebOperation.ExecuteGet<ProjectReader>(
248+
ctx.Sast.Json.CreateClient
249+
, (response) =>
250+
{
251+
using (var sr = new StreamReader(response.Content.ReadAsStreamAsync().Result))
252+
using (var jtr = new JsonTextReader(sr))
253+
{
254+
JToken jt = JToken.Load(jtr);
255+
256+
return new ProjectReader(jt["value"], ctx, token);
257+
}
258+
}
259+
, requestUrl
260+
, ctx.Sast
261+
, token))
262+
fetchedPage = new List<Project>(projectReader);
263+
264+
if (fetchedPage != null)
265+
{
266+
returnedResults.AddRange(fetchedPage);
267+
filter["$filter"] = $"id gt {fetchedPage[fetchedPage.Count - 1].ProjectId}";
268+
}
269+
270+
271+
} while (fetchedPage != null && fetchedPage.Count == ODATA_TOP);
272+
273+
return returnedResults;
166274
}
167275

276+
public static IEnumerable<Project> GetProjects(CxSASTRestContext ctx, CancellationToken token, bool useOData)
277+
{
278+
if (useOData)
279+
return GetProjects_odata(ctx, token);
280+
else
281+
return GetProjects_rest(ctx, token);
282+
}
168283

169-
public static IEnumerable<Project> GetProjects(CxSASTRestContext ctx, CancellationToken token)
284+
private static IEnumerable<Project> GetProjects_rest(CxSASTRestContext ctx, CancellationToken token)
170285
{
171286
using (var projectReader = WebOperation.ExecuteGet<ProjectReader>(
172287
ctx.Sast.Json.CreateClient
@@ -180,7 +295,7 @@ public static IEnumerable<Project> GetProjects(CxSASTRestContext ctx, Cancellati
180295
return new ProjectReader(jt, ctx, token);
181296
}
182297
}
183-
, UrlUtils.MakeUrl(ctx.Sast.ApiUrl, URL_SUFFIX)
298+
, UrlUtils.MakeUrl(ctx.Sast.ApiUrl, REST_URL_SUFFIX)
184299
, ctx.Sast
185300
, token, apiVersion: GetApiVersion(ctx, token) ))
186301
return new List<Project>(projectReader);

XForm/SastTransformer/Transformer.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,8 @@ private async Task ResolveScans()
326326

327327
_sastVersionTask = GetSASTVersion();
328328

329-
var projectsTask = Task.Run(() => CxProjects.GetProjects(RestContext, ThreadOpts.CancellationToken), ThreadOpts.CancellationToken);
329+
var projectsTask = Task.Run(() => CxProjects.GetProjects(RestContext, ThreadOpts.CancellationToken,
330+
Config.GetConfig<CxSASTConnection>().Overrides.Project), ThreadOpts.CancellationToken);
330331

331332
Policies = await policyTask;
332333
Teams = await teamsTask;

0 commit comments

Comments
 (0)