diff --git a/src/ApiService/ApiService/OneFuzzTypes/Model.cs b/src/ApiService/ApiService/OneFuzzTypes/Model.cs index 0c7df87bf3..a23666d1d4 100644 --- a/src/ApiService/ApiService/OneFuzzTypes/Model.cs +++ b/src/ApiService/ApiService/OneFuzzTypes/Model.cs @@ -307,7 +307,7 @@ public record InstanceConfig //# if admins are set, only admins can update instance configs. Guid[]? Admins, //# if set, only admins can manage pools or scalesets - bool AllowPoolManagement, + bool? AllowPoolManagement, string[] AllowedAadTenants, NetworkConfig NetworkConfig, NetworkSecurityGroupConfig ProxyNsgConfig, diff --git a/src/ApiService/ApiService/Program.cs b/src/ApiService/ApiService/Program.cs index 7f912b7e68..6f1732ce32 100644 --- a/src/ApiService/ApiService/Program.cs +++ b/src/ApiService/ApiService/Program.cs @@ -81,6 +81,7 @@ public static void Main() .AddScoped() .AddScoped() .AddScoped() + .AddScoped() //TODO: move out expensive resources into separate class, and add those as Singleton // ArmClient, Table Client(s), Queue Client(s), HttpClient, etc. diff --git a/src/ApiService/ApiService/UserCredentials.cs b/src/ApiService/ApiService/UserCredentials.cs index 22b0ce3027..6ecc3d13e3 100644 --- a/src/ApiService/ApiService/UserCredentials.cs +++ b/src/ApiService/ApiService/UserCredentials.cs @@ -6,11 +6,25 @@ namespace Microsoft.OneFuzz.Service; -public class UserCredentials +public interface IUserCredentials { + public string? GetBearerToken(HttpRequestData req); + public string? GetAuthToken(HttpRequestData req); + public Task> ParseJwtToken(LogTracer log, HttpRequestData req); +} + +public class UserCredentials : IUserCredentials +{ + ILogTracer _log; + IConfigOperations _instanceConfig; + public UserCredentials(ILogTracer log, IConfigOperations instanceConfig) + { + _log = log; + _instanceConfig = instanceConfig; + } - public static string? GetBearerToken(HttpRequestData req) + public string? GetBearerToken(HttpRequestData req) { var authHeader = req.Headers.GetValues("Authorization"); if (authHeader.IsNullOrEmpty()) @@ -28,7 +42,7 @@ public class UserCredentials } } - public static string? GetAuthToken(HttpRequestData req) + public string? GetAuthToken(HttpRequestData req) { var token = GetBearerToken(req); if (token is not null) @@ -50,25 +64,17 @@ public class UserCredentials } - static Task> GetAllowedTenants() + async Task> GetAllowedTenants() { - return Async.Task.FromResult(OneFuzzResult.Ok(Array.Empty())); - } - - /* - TODO: GetAllowedTenants blocked on Models and ORM since this requires - let getAllowedTenants() = - task { - match! InstanceConfig.fetch() with - | Result.Ok(config, _) -> - let entries = config.AllowedAadTenants |> Array.map(fun x->sprintf "https://sts.windows.net/%s/" x) - return Result.Ok entries - | Result.Error err -> return Result.Error err - } - */ + var r = await _instanceConfig.Fetch(); + var allowedAddTenantsQuery = + from t in r.AllowedAadTenants + select $"https://sts.windows.net/{t}/"; + return OneFuzzResult.Ok(allowedAddTenantsQuery.ToArray()); + } - static async Task> ParseJwtToken(LogTracer log, HttpRequestData req) + public async Task> ParseJwtToken(LogTracer log, HttpRequestData req) { var authToken = GetAuthToken(req); if (authToken is null) diff --git a/src/ApiService/ApiService/onefuzzlib/orm/EntityConverter.cs b/src/ApiService/ApiService/onefuzzlib/orm/EntityConverter.cs index b839b96c77..f8fbe12980 100644 --- a/src/ApiService/ApiService/onefuzzlib/orm/EntityConverter.cs +++ b/src/ApiService/ApiService/onefuzzlib/orm/EntityConverter.cs @@ -250,7 +250,7 @@ public TableEntity ToTableEntity(T typedEntity) where T : EntityBase { return entity.GetString(fieldName); } - else if (ef.type == typeof(bool)) + else if (ef.type == typeof(bool) || ef.type == typeof(bool?)) { return entity.GetBoolean(fieldName); } @@ -262,7 +262,7 @@ public TableEntity ToTableEntity(T typedEntity) where T : EntityBase { return entity.GetDateTime(fieldName); } - else if (ef.type == typeof(double)) + else if (ef.type == typeof(double) || ef.type == typeof(double?)) { return entity.GetDouble(fieldName); } @@ -270,11 +270,11 @@ public TableEntity ToTableEntity(T typedEntity) where T : EntityBase { return (object?)Guid.Parse(entity.GetString(fieldName)); } - else if (ef.type == typeof(int)) + else if (ef.type == typeof(int) || ef.type == typeof(short) || ef.type == typeof(int?) || ef.type == typeof(short?)) { return entity.GetInt32(fieldName); } - else if (ef.type == typeof(Int64)) + else if (ef.type == typeof(long) || ef.type == typeof(long?)) { return entity.GetInt64(fieldName); } diff --git a/src/ApiService/Tests/OrmModelsTest.cs b/src/ApiService/Tests/OrmModelsTest.cs index 66676b5c82..16b651c109 100644 --- a/src/ApiService/Tests/OrmModelsTest.cs +++ b/src/ApiService/Tests/OrmModelsTest.cs @@ -140,7 +140,7 @@ public static Gen NetworkSecurityGroupConfig() public static Gen InstanceConfig() { return Arb.Generate, + Tuple, Tuple?, IDictionary?, IDictionary?, IDictionary?>>>().Select( arg => new InstanceConfig( @@ -594,15 +594,14 @@ public bool Notification(Notification n) } - + /* //Sample function on how repro a failing test run, using Replay //functionality of FsCheck. Feel free to - /* [Property] void Replay() { - var seed = FsCheck.Random.StdGen.NewStdGen(1384212554,297026222); - var p = Prop.ForAll((Task x) => Task(x) ); + var seed = FsCheck.Random.StdGen.NewStdGen(515508280, 297027790); + var p = Prop.ForAll((InstanceConfig x) => InstanceConfig(x) ); p.Check(new Configuration { Replay = seed }); } */