From a361df811b49be1aecda2d55331d7efad9ec4579 Mon Sep 17 00:00:00 2001 From: James Gunn Date: Tue, 17 Oct 2023 16:07:29 +0100 Subject: [PATCH] Add service configuration to block prohibited teachers (#743) --- .../Events/Client.cs | 7 +- .../Events/ClientUpdatedEvent.cs | 3 +- ..._ClientBlockProhibitedTeachers.Designer.cs | 1008 +++++++++++++++++ ...017142236_ClientBlockProhibitedTeachers.cs | 29 + ...herIdentityServerDbContextModelSnapshot.cs | 4 + .../Models/Application.cs | 3 + .../Oidc/ClientConfiguration.cs | 1 + .../Oidc/ClientConfigurationHelper.cs | 1 + .../TeacherIdentityApplicationDescriptor.cs | 3 + .../Oidc/TeacherIdentityApplicationManager.cs | 2 + .../Oidc/TeacherIdentityApplicationStore.cs | 22 + .../Pages/Admin/AddClient.cshtml | 20 +- .../Pages/Admin/AddClient.cshtml.cs | 6 +- .../Pages/Admin/EditClient.cshtml | 20 +- .../Pages/Admin/EditClient.cshtml.cs | 12 +- .../EndpointTests/Admin/AddClientTests.cs | 2 + .../EndpointTests/Admin/EditClientTests.cs | 1 + 17 files changed, 1127 insertions(+), 17 deletions(-) create mode 100644 dotnet-authserver/src/TeacherIdentity.AuthServer/Migrations/20231017142236_ClientBlockProhibitedTeachers.Designer.cs create mode 100644 dotnet-authserver/src/TeacherIdentity.AuthServer/Migrations/20231017142236_ClientBlockProhibitedTeachers.cs diff --git a/dotnet-authserver/src/TeacherIdentity.AuthServer/Events/Client.cs b/dotnet-authserver/src/TeacherIdentity.AuthServer/Events/Client.cs index d9b3af336..245045a49 100644 --- a/dotnet-authserver/src/TeacherIdentity.AuthServer/Events/Client.cs +++ b/dotnet-authserver/src/TeacherIdentity.AuthServer/Events/Client.cs @@ -11,6 +11,7 @@ public record Client public required string? ServiceUrl { get; init; } public required TrnRequirementType TrnRequirementType { get; init; } public required TrnMatchPolicy TrnMatchPolicy { get; set; } + public required bool BlockProhibitedTeachers { get; set; } public required bool RaiseTrnResolutionSupportTickets { get; init; } public required string[] RedirectUris { get; init; } public required string[] PostLogoutRedirectUris { get; init; } @@ -23,6 +24,7 @@ public record Client ServiceUrl = descriptor.ServiceUrl, TrnRequirementType = descriptor.TrnRequirementType, TrnMatchPolicy = descriptor.TrnMatchPolicy, + BlockProhibitedTeachers = descriptor.BlockProhibitedTeachers, RaiseTrnResolutionSupportTickets = descriptor.RaiseTrnResolutionSupportTickets, RedirectUris = descriptor.RedirectUris.Select(u => u.ToString()).ToArray(), PostLogoutRedirectUris = descriptor.PostLogoutRedirectUris.Select(u => u.ToString()).ToArray(), @@ -32,18 +34,19 @@ public record Client .ToArray() }; - public static Client FromModel(Models.Application model) => new() + public static Client FromModel(Application model) => new() { ClientId = model.ClientId!, DisplayName = model.DisplayName, ServiceUrl = model.ServiceUrl, TrnRequirementType = model.TrnRequirementType, TrnMatchPolicy = model.TrnMatchPolicy, + BlockProhibitedTeachers = model.BlockProhibitedTeachers, RaiseTrnResolutionSupportTickets = model.RaiseTrnResolutionSupportTickets, RedirectUris = model.GetRedirectUris(), PostLogoutRedirectUris = model.GetPostLogoutRedirectUris(), Scopes = model.GetScopes() }; - public static implicit operator Client(Models.Application model) => FromModel(model); + public static implicit operator Client(Application model) => FromModel(model); } diff --git a/dotnet-authserver/src/TeacherIdentity.AuthServer/Events/ClientUpdatedEvent.cs b/dotnet-authserver/src/TeacherIdentity.AuthServer/Events/ClientUpdatedEvent.cs index 4d3756358..d50070569 100644 --- a/dotnet-authserver/src/TeacherIdentity.AuthServer/Events/ClientUpdatedEvent.cs +++ b/dotnet-authserver/src/TeacherIdentity.AuthServer/Events/ClientUpdatedEvent.cs @@ -20,5 +20,6 @@ public enum ClientUpdatedEventChanges GrantTypes = 1 << 6, TrnRequirementType = 1 << 7, RaiseTrnResolutionSupportTickets = 1 << 8, - TrnMatchPolicy = 1 << 9 + TrnMatchPolicy = 1 << 9, + BlockProhibitedTeachers = 1 << 10, } diff --git a/dotnet-authserver/src/TeacherIdentity.AuthServer/Migrations/20231017142236_ClientBlockProhibitedTeachers.Designer.cs b/dotnet-authserver/src/TeacherIdentity.AuthServer/Migrations/20231017142236_ClientBlockProhibitedTeachers.Designer.cs new file mode 100644 index 000000000..ee109a168 --- /dev/null +++ b/dotnet-authserver/src/TeacherIdentity.AuthServer/Migrations/20231017142236_ClientBlockProhibitedTeachers.Designer.cs @@ -0,0 +1,1008 @@ +// +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using TeacherIdentity.AuthServer.Models; + +#nullable disable + +namespace TeacherIdentity.AuthServer.Migrations +{ + [DbContext(typeof(TeacherIdentityServerDbContext))] + [Migration("20231017142236_ClientBlockProhibitedTeachers")] + partial class ClientBlockProhibitedTeachers + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("TeacherIdentity.AuthServer.Models.Application", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("text") + .HasColumnName("id"); + + b.Property("BlockProhibitedTeachers") + .HasColumnType("boolean") + .HasColumnName("block_prohibited_teachers"); + + b.Property("ClientId") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("client_id"); + + b.Property("ClientSecret") + .HasColumnType("text") + .HasColumnName("client_secret"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("concurrency_token"); + + b.Property("ConsentType") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("consent_type"); + + b.Property("DisplayName") + .HasColumnType("text") + .HasColumnName("display_name"); + + b.Property("DisplayNames") + .HasColumnType("text") + .HasColumnName("display_names"); + + b.Property("Permissions") + .HasColumnType("text") + .HasColumnName("permissions"); + + b.Property("PostLogoutRedirectUris") + .HasColumnType("text") + .HasColumnName("post_logout_redirect_uris"); + + b.Property("Properties") + .HasColumnType("text") + .HasColumnName("properties"); + + b.Property("RaiseTrnResolutionSupportTickets") + .HasColumnType("boolean") + .HasColumnName("raise_trn_resolution_support_tickets"); + + b.Property("RedirectUris") + .HasColumnType("text") + .HasColumnName("redirect_uris"); + + b.Property("Requirements") + .HasColumnType("text") + .HasColumnName("requirements"); + + b.Property("ServiceUrl") + .HasColumnType("text") + .HasColumnName("service_url"); + + b.Property("TrnMatchPolicy") + .HasColumnType("integer") + .HasColumnName("trn_match_policy"); + + b.Property("TrnRequirementType") + .HasColumnType("integer") + .HasColumnName("trn_requirement_type"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_applications"); + + b.HasAlternateKey("ClientId") + .HasName("ak_open_iddict_applications_client_id"); + + b.HasIndex("ClientId") + .IsUnique() + .HasDatabaseName("ix_applications_client_id"); + + b.ToTable("applications", (string)null); + }); + + modelBuilder.Entity("TeacherIdentity.AuthServer.Models.AuthenticationState", b => + { + b.Property("JourneyId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("journey_id"); + + b.Property("Created") + .HasColumnType("timestamp with time zone") + .HasColumnName("created"); + + b.Property("LastAccessed") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_accessed"); + + b.Property("Payload") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("payload"); + + b.HasKey("JourneyId") + .HasName("pk_authentication_states"); + + b.HasIndex("Payload") + .HasDatabaseName("ix_authentication_states_payload"); + + NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Payload"), "gin"); + + b.ToTable("authentication_states", (string)null); + }); + + modelBuilder.Entity("TeacherIdentity.AuthServer.Models.AuthenticationStateSnapshot", b => + { + b.Property("SnapshotId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("snapshot_id"); + + b.Property("Created") + .HasColumnType("timestamp with time zone") + .HasColumnName("created"); + + b.Property("JourneyId") + .HasColumnType("uuid") + .HasColumnName("journey_id"); + + b.Property("Payload") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("payload"); + + b.HasKey("SnapshotId") + .HasName("pk_authentication_state_snapshots"); + + b.HasIndex("Payload") + .HasDatabaseName("ix_authentication_state_snapshots_payload"); + + NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Payload"), "gin"); + + b.ToTable("authentication_state_snapshots", (string)null); + }); + + modelBuilder.Entity("TeacherIdentity.AuthServer.Models.Authorization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("text") + .HasColumnName("id"); + + b.Property("ApplicationId") + .HasColumnType("text") + .HasColumnName("application_id"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("concurrency_token"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("creation_date"); + + b.Property("Properties") + .HasColumnType("text") + .HasColumnName("properties"); + + b.Property("Scopes") + .HasColumnType("text") + .HasColumnName("scopes"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("status"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("character varying(400)") + .HasColumnName("subject"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_authorizations"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type") + .HasDatabaseName("ix_authorizations_application_id_status_subject_type"); + + b.ToTable("authorizations", (string)null); + }); + + modelBuilder.Entity("TeacherIdentity.AuthServer.Models.EmailConfirmationPin", b => + { + b.Property("EmailConfirmationPinId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("email_confirmation_pin_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EmailConfirmationPinId")); + + b.Property("Email") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("email"); + + b.Property("Expires") + .HasColumnType("timestamp with time zone") + .HasColumnName("expires"); + + b.Property("IsActive") + .HasColumnType("boolean") + .HasColumnName("is_active"); + + b.Property("Pin") + .IsRequired() + .HasMaxLength(6) + .HasColumnType("character(6)") + .HasColumnName("pin") + .IsFixedLength(); + + b.Property("VerifiedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("verified_on"); + + b.HasKey("EmailConfirmationPinId") + .HasName("pk_email_confirmation_pins"); + + b.HasIndex("Email", "Pin") + .IsUnique() + .HasDatabaseName("ix_email_confirmation_pins_email_pin"); + + b.ToTable("email_confirmation_pins", (string)null); + }); + + modelBuilder.Entity("TeacherIdentity.AuthServer.Models.EstablishmentDomain", b => + { + b.Property("DomainName") + .HasColumnType("text") + .HasColumnName("domain_name") + .UseCollation("case_insensitive"); + + b.HasKey("DomainName") + .HasName("pk_establishment_domains"); + + b.ToTable("establishment_domains", (string)null); + }); + + modelBuilder.Entity("TeacherIdentity.AuthServer.Models.Event", b => + { + b.Property("EventId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("event_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("EventId")); + + b.Property("Created") + .HasColumnType("timestamp with time zone") + .HasColumnName("created"); + + b.Property("EventName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("event_name"); + + b.Property("Payload") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("payload"); + + b.Property("Published") + .HasColumnType("boolean") + .HasColumnName("published"); + + b.HasKey("EventId") + .HasName("pk_events"); + + b.HasIndex("Payload") + .HasDatabaseName("ix_events_payload"); + + NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Payload"), "gin"); + + b.ToTable("events", (string)null); + }); + + modelBuilder.Entity("TeacherIdentity.AuthServer.Models.JourneyTrnLookupState", b => + { + b.Property("JourneyId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("journey_id"); + + b.Property("Created") + .HasColumnType("timestamp with time zone") + .HasColumnName("created"); + + b.Property("DateOfBirth") + .HasColumnType("date") + .HasColumnName("date_of_birth"); + + b.Property("Locked") + .HasColumnType("timestamp with time zone") + .HasColumnName("locked"); + + b.Property("NationalInsuranceNumber") + .HasMaxLength(9) + .HasColumnType("character(9)") + .HasColumnName("national_insurance_number") + .IsFixedLength(); + + b.Property("OfficialFirstName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("official_first_name"); + + b.Property("OfficialLastName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("official_last_name"); + + b.Property("PreferredFirstName") + .HasColumnType("text") + .HasColumnName("preferred_first_name"); + + b.Property("PreferredLastName") + .HasColumnType("text") + .HasColumnName("preferred_last_name"); + + b.Property("SupportTicketCreated") + .HasColumnType("boolean") + .HasColumnName("support_ticket_created"); + + b.Property("Trn") + .HasMaxLength(7) + .HasColumnType("character(7)") + .HasColumnName("trn") + .IsFixedLength(); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("JourneyId") + .HasName("pk_journey_trn_lookup_states"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_journey_trn_lookup_states_user_id"); + + b.ToTable("journey_trn_lookup_states", (string)null); + }); + + modelBuilder.Entity("TeacherIdentity.AuthServer.Models.Scope", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("text") + .HasColumnName("id"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("concurrency_token"); + + b.Property("Description") + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("Descriptions") + .HasColumnType("text") + .HasColumnName("descriptions"); + + b.Property("DisplayName") + .HasColumnType("text") + .HasColumnName("display_name"); + + b.Property("DisplayNames") + .HasColumnType("text") + .HasColumnName("display_names"); + + b.Property("Name") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("name"); + + b.Property("Properties") + .HasColumnType("text") + .HasColumnName("properties"); + + b.Property("Resources") + .HasColumnType("text") + .HasColumnName("resources"); + + b.HasKey("Id") + .HasName("pk_scopes"); + + b.HasIndex("Name") + .IsUnique() + .HasDatabaseName("ix_scopes_name"); + + b.ToTable("scopes", (string)null); + }); + + modelBuilder.Entity("TeacherIdentity.AuthServer.Models.SmsConfirmationPin", b => + { + b.Property("SmsConfirmationPinId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("sms_confirmation_pin_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("SmsConfirmationPinId")); + + b.Property("Expires") + .HasColumnType("timestamp with time zone") + .HasColumnName("expires"); + + b.Property("IsActive") + .HasColumnType("boolean") + .HasColumnName("is_active"); + + b.Property("MobileNumber") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("mobile_number"); + + b.Property("Pin") + .IsRequired() + .HasMaxLength(6) + .HasColumnType("character(6)") + .HasColumnName("pin") + .IsFixedLength(); + + b.Property("VerifiedOn") + .HasColumnType("timestamp with time zone") + .HasColumnName("verified_on"); + + b.HasKey("SmsConfirmationPinId") + .HasName("pk_sms_confirmation_pins"); + + b.HasIndex("MobileNumber", "Pin") + .IsUnique() + .HasDatabaseName("ix_sms_confirmation_pins_mobile_number_pin"); + + b.ToTable("sms_confirmation_pins", (string)null); + }); + + modelBuilder.Entity("TeacherIdentity.AuthServer.Models.Token", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("text") + .HasColumnName("id"); + + b.Property("ApplicationId") + .HasColumnType("text") + .HasColumnName("application_id"); + + b.Property("AuthorizationId") + .HasColumnType("text") + .HasColumnName("authorization_id"); + + b.Property("ConcurrencyToken") + .IsConcurrencyToken() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("concurrency_token"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("creation_date"); + + b.Property("ExpirationDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_date"); + + b.Property("Payload") + .HasColumnType("text") + .HasColumnName("payload"); + + b.Property("Properties") + .HasColumnType("text") + .HasColumnName("properties"); + + b.Property("RedemptionDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("redemption_date"); + + b.Property("ReferenceId") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("reference_id"); + + b.Property("Status") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("status"); + + b.Property("Subject") + .HasMaxLength(400) + .HasColumnType("character varying(400)") + .HasColumnName("subject"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_tokens"); + + b.HasIndex("AuthorizationId") + .HasDatabaseName("ix_tokens_authorization_id"); + + b.HasIndex("ReferenceId") + .IsUnique() + .HasDatabaseName("ix_tokens_reference_id"); + + b.HasIndex("ApplicationId", "Status", "Subject", "Type") + .HasDatabaseName("ix_tokens_application_id_status_subject_type"); + + b.ToTable("tokens", (string)null); + }); + + modelBuilder.Entity("TeacherIdentity.AuthServer.Models.TrnTokenModel", b => + { + b.Property("TrnToken") + .HasMaxLength(128) + .HasColumnType("character varying(128)") + .HasColumnName("trn_token"); + + b.Property("CreatedUtc") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_utc"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("email") + .UseCollation("case_insensitive"); + + b.Property("ExpiresUtc") + .HasColumnType("timestamp with time zone") + .HasColumnName("expires_utc"); + + b.Property("Trn") + .IsRequired() + .HasMaxLength(7) + .HasColumnType("character(7)") + .HasColumnName("trn") + .IsFixedLength(); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("TrnToken") + .HasName("pk_trn_tokens"); + + b.HasIndex("Email") + .HasDatabaseName("ix_trn_tokens_email_address"); + + b.ToTable("trn_tokens", (string)null); + }); + + modelBuilder.Entity("TeacherIdentity.AuthServer.Models.User", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("CompletedTrnLookup") + .HasColumnType("timestamp with time zone") + .HasColumnName("completed_trn_lookup"); + + b.Property("Created") + .HasColumnType("timestamp with time zone") + .HasColumnName("created"); + + b.Property("DateOfBirth") + .ValueGeneratedOnAdd() + .HasColumnType("date") + .HasColumnName("date_of_birth") + .HasDefaultValueSql("NULL"); + + b.Property("EmailAddress") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("email_address") + .UseCollation("case_insensitive"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("first_name"); + + b.Property("IsDeleted") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("is_deleted"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("last_name"); + + b.Property("LastSignedIn") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_signed_in"); + + b.Property("MergedWithUserId") + .HasColumnType("uuid") + .HasColumnName("merged_with_user_id"); + + b.Property("MiddleName") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("middle_name"); + + b.Property("MobileNumber") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("mobile_number"); + + b.Property("NationalInsuranceNumber") + .HasColumnType("text") + .HasColumnName("national_insurance_number"); + + b.Property("NormalizedMobileNumber") + .HasMaxLength(15) + .HasColumnType("character varying(15)") + .HasColumnName("normalized_mobile_number"); + + b.Property("PreferredName") + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("preferred_name"); + + b.Property("RegisteredWithClientId") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("registered_with_client_id"); + + b.Property("StaffRoles") + .IsRequired() + .HasColumnType("varchar[]") + .HasColumnName("staff_roles"); + + b.Property("Trn") + .HasMaxLength(7) + .HasColumnType("character(7)") + .HasColumnName("trn") + .IsFixedLength(); + + b.Property("TrnAssociationSource") + .HasColumnType("integer") + .HasColumnName("trn_association_source"); + + b.Property("TrnLookupStatus") + .HasColumnType("integer") + .HasColumnName("trn_lookup_status"); + + b.Property("TrnLookupSupportTicketCreated") + .HasColumnType("boolean") + .HasColumnName("trn_lookup_support_ticket_created"); + + b.Property("TrnVerificationLevel") + .HasColumnType("integer") + .HasColumnName("trn_verification_level"); + + b.Property("Updated") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated"); + + b.Property("UserType") + .HasColumnType("integer") + .HasColumnName("user_type"); + + b.HasKey("UserId") + .HasName("pk_users"); + + b.HasIndex("EmailAddress") + .IsUnique() + .HasDatabaseName("ix_users_email_address") + .HasFilter("is_deleted = false"); + + b.HasIndex("MergedWithUserId") + .HasDatabaseName("ix_users_merged_with_user_id"); + + b.HasIndex("NormalizedMobileNumber") + .IsUnique() + .HasDatabaseName("ix_users_mobile_number") + .HasFilter("is_deleted = false and normalized_mobile_number is not null"); + + b.HasIndex("RegisteredWithClientId") + .HasDatabaseName("ix_users_registered_with_client_id"); + + b.HasIndex("Trn") + .IsUnique() + .HasDatabaseName("ix_users_trn") + .HasFilter("is_deleted = false and trn is not null"); + + b.ToTable("users", (string)null); + }); + + modelBuilder.Entity("TeacherIdentity.AuthServer.Models.UserImportJob", b => + { + b.Property("UserImportJobId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_import_job_id"); + + b.Property("Imported") + .HasColumnType("timestamp with time zone") + .HasColumnName("imported"); + + b.Property("OriginalFilename") + .IsRequired() + .HasColumnType("text") + .HasColumnName("original_filename"); + + b.Property("StoredFilename") + .IsRequired() + .HasColumnType("text") + .HasColumnName("stored_filename"); + + b.Property("Uploaded") + .HasColumnType("timestamp with time zone") + .HasColumnName("uploaded"); + + b.Property("UploadedByUserId") + .HasColumnType("uuid") + .HasColumnName("uploaded_by_user_id"); + + b.Property("UserImportJobStatus") + .HasColumnType("integer") + .HasColumnName("user_import_job_status"); + + b.HasKey("UserImportJobId") + .HasName("pk_user_import_jobs"); + + b.ToTable("user_import_jobs", (string)null); + }); + + modelBuilder.Entity("TeacherIdentity.AuthServer.Models.UserImportJobRow", b => + { + b.Property("UserImportJobId") + .HasColumnType("uuid") + .HasColumnName("user_import_job_id"); + + b.Property("RowNumber") + .HasColumnType("integer") + .HasColumnName("row_number"); + + b.Property("Id") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("id"); + + b.Property>("Notes") + .HasColumnType("varchar[]") + .HasColumnName("notes"); + + b.Property("RawData") + .HasColumnType("text") + .HasColumnName("raw_data"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("UserImportRowResult") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("user_import_row_result"); + + b.HasKey("UserImportJobId", "RowNumber") + .HasName("pk_user_import_job_rows"); + + b.ToTable("user_import_job_rows", (string)null); + }); + + modelBuilder.Entity("TeacherIdentity.AuthServer.Models.UserSearchAttribute", b => + { + b.Property("UserSearchAttributeId") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasColumnName("user_search_attribute_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("UserSearchAttributeId")); + + b.Property("AttributeType") + .IsRequired() + .HasColumnType("text") + .HasColumnName("attribute_type"); + + b.Property("AttributeValue") + .IsRequired() + .HasColumnType("text") + .HasColumnName("attribute_value") + .UseCollation("case_insensitive"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("UserSearchAttributeId") + .HasName("pk_user_search_attributes"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_user_search_attributes_user_id"); + + b.HasIndex("AttributeType", "AttributeValue") + .HasDatabaseName("ix_user_search_attributes_attribute_type_and_value"); + + b.ToTable("user_search_attributes", (string)null); + }); + + modelBuilder.Entity("TeacherIdentity.AuthServer.Models.WebHook", b => + { + b.Property("WebHookId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("web_hook_id"); + + b.Property("Created") + .HasColumnType("timestamp with time zone") + .HasColumnName("created"); + + b.Property("Enabled") + .HasColumnType("boolean") + .HasColumnName("enabled"); + + b.Property("Endpoint") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("endpoint"); + + b.Property("Secret") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("character varying(64)") + .HasColumnName("secret"); + + b.Property("Updated") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated"); + + b.Property("WebHookMessageTypes") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("web_hook_message_types"); + + b.HasKey("WebHookId") + .HasName("pk_webhooks"); + + b.ToTable("webhooks", (string)null); + }); + + modelBuilder.Entity("TeacherIdentity.AuthServer.Models.Authorization", b => + { + b.HasOne("TeacherIdentity.AuthServer.Models.Application", "Application") + .WithMany("Authorizations") + .HasForeignKey("ApplicationId") + .HasConstraintName("fk_authorizations_applications_application_id"); + + b.Navigation("Application"); + }); + + modelBuilder.Entity("TeacherIdentity.AuthServer.Models.JourneyTrnLookupState", b => + { + b.HasOne("TeacherIdentity.AuthServer.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .HasConstraintName("fk_journey_trn_lookup_states_users_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("TeacherIdentity.AuthServer.Models.Token", b => + { + b.HasOne("TeacherIdentity.AuthServer.Models.Application", "Application") + .WithMany("Tokens") + .HasForeignKey("ApplicationId") + .HasConstraintName("fk_tokens_applications_application_id"); + + b.HasOne("TeacherIdentity.AuthServer.Models.Authorization", "Authorization") + .WithMany("Tokens") + .HasForeignKey("AuthorizationId") + .HasConstraintName("fk_tokens_authorizations_authorization_id"); + + b.Navigation("Application"); + + b.Navigation("Authorization"); + }); + + modelBuilder.Entity("TeacherIdentity.AuthServer.Models.User", b => + { + b.HasOne("TeacherIdentity.AuthServer.Models.User", "MergedWithUser") + .WithMany("MergedUsers") + .HasForeignKey("MergedWithUserId") + .HasConstraintName("fk_users_users_merged_with_user_id"); + + b.HasOne("TeacherIdentity.AuthServer.Models.Application", "RegisteredWithClient") + .WithMany() + .HasForeignKey("RegisteredWithClientId") + .HasPrincipalKey("ClientId") + .HasConstraintName("fk_users_application_registered_with_client_id"); + + b.Navigation("MergedWithUser"); + + b.Navigation("RegisteredWithClient"); + }); + + modelBuilder.Entity("TeacherIdentity.AuthServer.Models.UserImportJobRow", b => + { + b.HasOne("TeacherIdentity.AuthServer.Models.UserImportJob", "UserImportJob") + .WithMany("UserImportJobRows") + .HasForeignKey("UserImportJobId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_import_job_rows_user_import_jobs_user_import_job_id"); + + b.Navigation("UserImportJob"); + }); + + modelBuilder.Entity("TeacherIdentity.AuthServer.Models.Application", b => + { + b.Navigation("Authorizations"); + + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("TeacherIdentity.AuthServer.Models.Authorization", b => + { + b.Navigation("Tokens"); + }); + + modelBuilder.Entity("TeacherIdentity.AuthServer.Models.User", b => + { + b.Navigation("MergedUsers"); + }); + + modelBuilder.Entity("TeacherIdentity.AuthServer.Models.UserImportJob", b => + { + b.Navigation("UserImportJobRows"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/dotnet-authserver/src/TeacherIdentity.AuthServer/Migrations/20231017142236_ClientBlockProhibitedTeachers.cs b/dotnet-authserver/src/TeacherIdentity.AuthServer/Migrations/20231017142236_ClientBlockProhibitedTeachers.cs new file mode 100644 index 000000000..28459c74d --- /dev/null +++ b/dotnet-authserver/src/TeacherIdentity.AuthServer/Migrations/20231017142236_ClientBlockProhibitedTeachers.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace TeacherIdentity.AuthServer.Migrations +{ + /// + public partial class ClientBlockProhibitedTeachers : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "block_prohibited_teachers", + table: "applications", + type: "boolean", + nullable: false, + defaultValue: false); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "block_prohibited_teachers", + table: "applications"); + } + } +} diff --git a/dotnet-authserver/src/TeacherIdentity.AuthServer/Migrations/TeacherIdentityServerDbContextModelSnapshot.cs b/dotnet-authserver/src/TeacherIdentity.AuthServer/Migrations/TeacherIdentityServerDbContextModelSnapshot.cs index e38bd3114..017c31613 100644 --- a/dotnet-authserver/src/TeacherIdentity.AuthServer/Migrations/TeacherIdentityServerDbContextModelSnapshot.cs +++ b/dotnet-authserver/src/TeacherIdentity.AuthServer/Migrations/TeacherIdentityServerDbContextModelSnapshot.cs @@ -30,6 +30,10 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("text") .HasColumnName("id"); + b.Property("BlockProhibitedTeachers") + .HasColumnType("boolean") + .HasColumnName("block_prohibited_teachers"); + b.Property("ClientId") .IsRequired() .HasMaxLength(100) diff --git a/dotnet-authserver/src/TeacherIdentity.AuthServer/Models/Application.cs b/dotnet-authserver/src/TeacherIdentity.AuthServer/Models/Application.cs index dac582b03..79598f61f 100644 --- a/dotnet-authserver/src/TeacherIdentity.AuthServer/Models/Application.cs +++ b/dotnet-authserver/src/TeacherIdentity.AuthServer/Models/Application.cs @@ -48,6 +48,9 @@ public static bool MatchUriPattern(string pattern, string uri, bool ignorePath) public TrnMatchPolicy TrnMatchPolicy { get; set; } + [DefaultValue(false)] + public bool BlockProhibitedTeachers { get; set; } + [DefaultValue(false)] public bool RaiseTrnResolutionSupportTickets { get; set; } diff --git a/dotnet-authserver/src/TeacherIdentity.AuthServer/Oidc/ClientConfiguration.cs b/dotnet-authserver/src/TeacherIdentity.AuthServer/Oidc/ClientConfiguration.cs index cd87ec068..aa2b026f4 100644 --- a/dotnet-authserver/src/TeacherIdentity.AuthServer/Oidc/ClientConfiguration.cs +++ b/dotnet-authserver/src/TeacherIdentity.AuthServer/Oidc/ClientConfiguration.cs @@ -13,6 +13,7 @@ public class ClientConfiguration public required string DisplayName { get; set; } public string? ServiceUrl { get; set; } public required TrnRequirementType TrnRequirementType { get; set; } + public bool BlockProhibitedTeachers { get; set; } public required TrnMatchPolicy TrnMatchPolicy { get; set; } public bool RaiseTrnResolutionSupportTickets { get; set; } public string[]? Scopes { get; set; } diff --git a/dotnet-authserver/src/TeacherIdentity.AuthServer/Oidc/ClientConfigurationHelper.cs b/dotnet-authserver/src/TeacherIdentity.AuthServer/Oidc/ClientConfigurationHelper.cs index 8ac4ec377..0d9a678fe 100644 --- a/dotnet-authserver/src/TeacherIdentity.AuthServer/Oidc/ClientConfigurationHelper.cs +++ b/dotnet-authserver/src/TeacherIdentity.AuthServer/Oidc/ClientConfigurationHelper.cs @@ -26,6 +26,7 @@ public async Task UpsertClients(IEnumerable clients) clientConfig.DisplayName, clientConfig.ServiceUrl, clientConfig.TrnRequirementType, + clientConfig.BlockProhibitedTeachers, clientConfig.TrnMatchPolicy, clientConfig.RaiseTrnResolutionSupportTickets, clientConfig.EnableAuthorizationCodeGrant, diff --git a/dotnet-authserver/src/TeacherIdentity.AuthServer/Oidc/TeacherIdentityApplicationDescriptor.cs b/dotnet-authserver/src/TeacherIdentity.AuthServer/Oidc/TeacherIdentityApplicationDescriptor.cs index 8d53d6079..971369bdf 100644 --- a/dotnet-authserver/src/TeacherIdentity.AuthServer/Oidc/TeacherIdentityApplicationDescriptor.cs +++ b/dotnet-authserver/src/TeacherIdentity.AuthServer/Oidc/TeacherIdentityApplicationDescriptor.cs @@ -27,6 +27,7 @@ public class TeacherIdentityApplicationDescriptor : OpenIddictApplicationDescrip public string? ServiceUrl { get; set; } public TrnRequirementType TrnRequirementType { get; set; } public TrnMatchPolicy TrnMatchPolicy { get; set; } + public bool BlockProhibitedTeachers { get; set; } public bool RaiseTrnResolutionSupportTickets { get; set; } public static TeacherIdentityApplicationDescriptor Create( @@ -35,6 +36,7 @@ public static TeacherIdentityApplicationDescriptor Create( string? displayName, string? serviceUrl, TrnRequirementType trnRequirementType, + bool blockProhibitedTeachers, TrnMatchPolicy trnMatchProperty, bool raiseTrnResolutionSupportTickets, bool enableAuthorizationCodeGrant, @@ -53,6 +55,7 @@ public static TeacherIdentityApplicationDescriptor Create( ServiceUrl = serviceUrl, TrnRequirementType = trnRequirementType, TrnMatchPolicy = trnMatchProperty, + BlockProhibitedTeachers = blockProhibitedTeachers, RaiseTrnResolutionSupportTickets = raiseTrnResolutionSupportTickets, Requirements = { diff --git a/dotnet-authserver/src/TeacherIdentity.AuthServer/Oidc/TeacherIdentityApplicationManager.cs b/dotnet-authserver/src/TeacherIdentity.AuthServer/Oidc/TeacherIdentityApplicationManager.cs index 7701b4f4d..243a11e80 100644 --- a/dotnet-authserver/src/TeacherIdentity.AuthServer/Oidc/TeacherIdentityApplicationManager.cs +++ b/dotnet-authserver/src/TeacherIdentity.AuthServer/Oidc/TeacherIdentityApplicationManager.cs @@ -62,6 +62,7 @@ public override async ValueTask PopulateAsync(Application application, OpenIddic { await Store.SetServiceUrlAsync(application, teacherIdentityApplicationDescriptor.ServiceUrl); await Store.SetTrnRequirementTypeAsync(application, teacherIdentityApplicationDescriptor.TrnRequirementType); + await Store.SetBlockProhibitedTeachersAsync(application, teacherIdentityApplicationDescriptor.BlockProhibitedTeachers); await Store.SetTrnMatchPolicyAsync(application, teacherIdentityApplicationDescriptor.TrnMatchPolicy); await Store.SetRaiseTrnResolutionSupportTicketsAsync(application, teacherIdentityApplicationDescriptor.RaiseTrnResolutionSupportTickets); } @@ -75,6 +76,7 @@ public override async ValueTask PopulateAsync(OpenIddictApplicationDescriptor de { teacherIdentityApplicationDescriptor.ServiceUrl = await Store.GetServiceUrlAsync(application); teacherIdentityApplicationDescriptor.TrnRequirementType = await Store.GetTrnRequirementTypeAsync(application); + teacherIdentityApplicationDescriptor.BlockProhibitedTeachers = await Store.GetBlockProhibitedTeachersAsync(application); teacherIdentityApplicationDescriptor.TrnMatchPolicy = await Store.GetTrnMatchPolicyAsync(application); teacherIdentityApplicationDescriptor.RaiseTrnResolutionSupportTickets = await Store.GetRaiseTrnResolutionSupportTicketsAsync(application); } diff --git a/dotnet-authserver/src/TeacherIdentity.AuthServer/Oidc/TeacherIdentityApplicationStore.cs b/dotnet-authserver/src/TeacherIdentity.AuthServer/Oidc/TeacherIdentityApplicationStore.cs index 87207781d..e4ee408db 100644 --- a/dotnet-authserver/src/TeacherIdentity.AuthServer/Oidc/TeacherIdentityApplicationStore.cs +++ b/dotnet-authserver/src/TeacherIdentity.AuthServer/Oidc/TeacherIdentityApplicationStore.cs @@ -87,6 +87,28 @@ public ValueTask SetTrnRequirementTypeAsync(Application application, TrnRequirem return default; } + public ValueTask GetBlockProhibitedTeachersAsync(Application application) + { + if (application is null) + { + throw new ArgumentNullException(nameof(application)); + } + + return new ValueTask(application.BlockProhibitedTeachers); + } + + public ValueTask SetBlockProhibitedTeachersAsync(Application application, bool blockProhibitedTeachers) + { + if (application is null) + { + throw new ArgumentNullException(nameof(application)); + } + + application.BlockProhibitedTeachers = blockProhibitedTeachers; + + return default; + } + public ValueTask GetTrnMatchPolicyAsync(Application application) { ArgumentNullException.ThrowIfNull(nameof(application)); diff --git a/dotnet-authserver/src/TeacherIdentity.AuthServer/Pages/Admin/AddClient.cshtml b/dotnet-authserver/src/TeacherIdentity.AuthServer/Pages/Admin/AddClient.cshtml index e5c2f4d2b..f8cc3163c 100644 --- a/dotnet-authserver/src/TeacherIdentity.AuthServer/Pages/Admin/AddClient.cshtml +++ b/dotnet-authserver/src/TeacherIdentity.AuthServer/Pages/Admin/AddClient.cshtml @@ -17,12 +17,20 @@ - - - TRN - @Html.DisplayNameFor(m => m.TrnRequired) - - + + + + + Required + + + @Html.DisplayNameFor(m => m.BlockProhibitedTeachers) + + + + Optional + + diff --git a/dotnet-authserver/src/TeacherIdentity.AuthServer/Pages/Admin/AddClient.cshtml.cs b/dotnet-authserver/src/TeacherIdentity.AuthServer/Pages/Admin/AddClient.cshtml.cs index fc7e6225d..180f91bd3 100644 --- a/dotnet-authserver/src/TeacherIdentity.AuthServer/Pages/Admin/AddClient.cshtml.cs +++ b/dotnet-authserver/src/TeacherIdentity.AuthServer/Pages/Admin/AddClient.cshtml.cs @@ -40,9 +40,12 @@ public AddClientModel( [Display(Name = "Service URL", Description = "The link used in the header to go back to the client")] public string? ServiceUrl { get; set; } - [Display(Name = "TRN required", Description = "Whether the client requires a TRN")] + [Display(Name = "TRN requirement")] public bool? TrnRequired { get; set; } + [Display(Name = "Block prohibited teachers")] + public bool? BlockProhibitedTeachers { get; set; } + [Display(Name = "Raise TRN resolution support tickets")] public bool RaiseTrnResolutionSupportTickets { get; set; } @@ -113,6 +116,7 @@ public async Task OnPost() DisplayName!, ServiceUrl!, TrnRequired == true ? TrnRequirementType.Required : TrnRequirementType.Optional, + TrnRequired == true ? BlockProhibitedTeachers!.Value : false, TrnMatchPolicy!.Value, RaiseTrnResolutionSupportTickets, EnableAuthorizationCodeFlow, diff --git a/dotnet-authserver/src/TeacherIdentity.AuthServer/Pages/Admin/EditClient.cshtml b/dotnet-authserver/src/TeacherIdentity.AuthServer/Pages/Admin/EditClient.cshtml index ee1ed1c53..16b058657 100644 --- a/dotnet-authserver/src/TeacherIdentity.AuthServer/Pages/Admin/EditClient.cshtml +++ b/dotnet-authserver/src/TeacherIdentity.AuthServer/Pages/Admin/EditClient.cshtml @@ -23,12 +23,20 @@ - - - TRN - @Html.DisplayNameFor(m => m.TrnRequired) - - + + + + + Required + + + @Html.DisplayNameFor(m => m.BlockProhibitedTeachers) + + + + Optional + + diff --git a/dotnet-authserver/src/TeacherIdentity.AuthServer/Pages/Admin/EditClient.cshtml.cs b/dotnet-authserver/src/TeacherIdentity.AuthServer/Pages/Admin/EditClient.cshtml.cs index 5370cf93b..0b146533f 100644 --- a/dotnet-authserver/src/TeacherIdentity.AuthServer/Pages/Admin/EditClient.cshtml.cs +++ b/dotnet-authserver/src/TeacherIdentity.AuthServer/Pages/Admin/EditClient.cshtml.cs @@ -46,9 +46,12 @@ public EditClientModel( [Display(Name = "Service URL", Description = "The link used in the header to go back to the client")] public string? ServiceUrl { get; set; } - [Display(Name = "TRN required", Description = "Whether the client requires a TRN")] + [Display(Name = "TRN requirement")] public bool? TrnRequired { get; set; } + [Display(Name = "Block prohibited teachers")] + public bool BlockProhibitedTeachers { get; set; } + [Display(Name = "Raise TRN resolution support tickets")] public bool RaiseTrnResolutionSupportTickets { get; set; } @@ -82,6 +85,7 @@ public async Task OnGet() DisplayName = client.DisplayName; ServiceUrl = client.ServiceUrl; TrnRequired = client.TrnRequirementType == TrnRequirementType.Required; + BlockProhibitedTeachers = client.BlockProhibitedTeachers; TrnMatchPolicy = client.TrnMatchPolicy; RaiseTrnResolutionSupportTickets = client.RaiseTrnResolutionSupportTickets; EnableAuthorizationCodeFlow = client.GetPermissions().Contains(OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode); @@ -180,6 +184,12 @@ public async Task OnPost() await _applicationStore.SetTrnRequirementTypeAsync(client, trnRequirementType); } + if (TrnRequired == true && BlockProhibitedTeachers != client.BlockProhibitedTeachers) + { + changes |= ClientUpdatedEventChanges.BlockProhibitedTeachers; + await _applicationStore.SetBlockProhibitedTeachersAsync(client, BlockProhibitedTeachers); + } + if (TrnMatchPolicy != client.TrnMatchPolicy) { changes |= ClientUpdatedEventChanges.TrnMatchPolicy; diff --git a/dotnet-authserver/tests/TeacherIdentity.AuthServer.Tests/EndpointTests/Admin/AddClientTests.cs b/dotnet-authserver/tests/TeacherIdentity.AuthServer.Tests/EndpointTests/Admin/AddClientTests.cs index 1527572ca..acddfd19e 100644 --- a/dotnet-authserver/tests/TeacherIdentity.AuthServer.Tests/EndpointTests/Admin/AddClientTests.cs +++ b/dotnet-authserver/tests/TeacherIdentity.AuthServer.Tests/EndpointTests/Admin/AddClientTests.cs @@ -117,6 +117,7 @@ public async Task Post_ValidRequest_CreatesClientEmitsEventAndRedirects() { "DisplayName", displayName }, { "ServiceUrl", serviceUrl }, { "TrnRequired", trnRequirementType == TrnRequirementType.Required }, + { "BlockProhibitedTeachers", bool.TrueString }, { "TrnMatchPolicy", trnMatchPolicy}, { "RaiseTrnResolutionSupportTickets", raiseTrnResolutionSupportTickets.ToString() }, { "EnableAuthorizationCodeFlow", bool.TrueString }, @@ -143,6 +144,7 @@ public async Task Post_ValidRequest_CreatesClientEmitsEventAndRedirects() Assert.Equal(displayName, application.DisplayName); Assert.Equal(serviceUrl, application.ServiceUrl); Assert.Equal(trnRequirementType, application.TrnRequirementType); + Assert.True(application.BlockProhibitedTeachers); Assert.Equal(trnMatchPolicy, application.TrnMatchPolicy); Assert.Equal(raiseTrnResolutionSupportTickets, application.RaiseTrnResolutionSupportTickets); Assert.Collection( diff --git a/dotnet-authserver/tests/TeacherIdentity.AuthServer.Tests/EndpointTests/Admin/EditClientTests.cs b/dotnet-authserver/tests/TeacherIdentity.AuthServer.Tests/EndpointTests/Admin/EditClientTests.cs index 3ef5b98a9..76278b1ee 100644 --- a/dotnet-authserver/tests/TeacherIdentity.AuthServer.Tests/EndpointTests/Admin/EditClientTests.cs +++ b/dotnet-authserver/tests/TeacherIdentity.AuthServer.Tests/EndpointTests/Admin/EditClientTests.cs @@ -214,6 +214,7 @@ private async Task CreateClient() displayName, serviceUrl, TrnRequirementType.Required, + blockProhibitedTeachers: false, TrnMatchPolicy.Default, raiseTrnResolutionSupportTickets: false, enableAuthorizationCodeGrant: true,