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,