diff --git a/src/ApiService/ApiService/OneFuzzTypes/Model.cs b/src/ApiService/ApiService/OneFuzzTypes/Model.cs index 0c7df87bf..a23666d1d 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 7f912b7e6..6f1732ce3 100644 --- a/src/ApiService/ApiService/Program.cs +++ b/src/ApiService/ApiService/Program.cs @@ -81,6 +81,7 @@ public class Program .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 22b0ce302..6ecc3d13e 100644 --- a/src/ApiService/ApiService/UserCredentials.cs +++ b/src/ApiService/ApiService/UserCredentials.cs @@ -6,11 +6,25 @@ using Microsoft.IdentityModel.Tokens; 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 static string? GetBearerToken(HttpRequestData req) + public UserCredentials(ILogTracer log, IConfigOperations instanceConfig) + { + _log = log; + _instanceConfig = instanceConfig; + } + + 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())); + var r = await _instanceConfig.Fetch(); + var allowedAddTenantsQuery = + from t in r.AllowedAadTenants + select $"https://sts.windows.net/{t}/"; + + return OneFuzzResult.Ok(allowedAddTenantsQuery.ToArray()); } - /* - 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 - } - */ - - - 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 b839b96c7..f8fbe1298 100644 --- a/src/ApiService/ApiService/onefuzzlib/orm/EntityConverter.cs +++ b/src/ApiService/ApiService/onefuzzlib/orm/EntityConverter.cs @@ -250,7 +250,7 @@ public class EntityConverter { 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 class EntityConverter { 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 class EntityConverter { 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 66676b5c8..16b651c10 100644 --- a/src/ApiService/Tests/OrmModelsTest.cs +++ b/src/ApiService/Tests/OrmModelsTest.cs @@ -140,7 +140,7 @@ namespace Tests public static Gen InstanceConfig() { return Arb.Generate, + Tuple, Tuple?, IDictionary?, IDictionary?, IDictionary?>>>().Select( arg => new InstanceConfig( @@ -594,15 +594,14 @@ namespace Tests } - + /* //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 }); } */