style: format backend with dotnet format
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -9,223 +9,223 @@ namespace BigRegister.Tests;
|
||||
|
||||
public class EndpointTests(WebApplicationFactory<Program> factory) : IClassFixture<WebApplicationFactory<Program>>
|
||||
{
|
||||
private readonly HttpClient _client = factory.CreateClient();
|
||||
private readonly HttpClient _client = factory.CreateClient();
|
||||
|
||||
[Fact]
|
||||
public async Task DashboardView_computes_eligibility_decision()
|
||||
{
|
||||
var dto = await _client.GetFromJsonAsync<DashboardViewDto>("/api/v1/dashboard-view");
|
||||
Assert.NotNull(dto);
|
||||
Assert.Equal("19012345601", dto.Registration.BigNummer);
|
||||
Assert.Equal("Geregistreerd", dto.Registration.Status.Tag);
|
||||
// seed deadline 2027-03-01 is within 12 months of "today" (2026) → eligible
|
||||
Assert.True(dto.Decisions.EligibleForHerregistratie);
|
||||
Assert.NotNull(dto.Decisions.HerregistratieReason);
|
||||
}
|
||||
[Fact]
|
||||
public async Task DashboardView_computes_eligibility_decision()
|
||||
{
|
||||
var dto = await _client.GetFromJsonAsync<DashboardViewDto>("/api/v1/dashboard-view");
|
||||
Assert.NotNull(dto);
|
||||
Assert.Equal("19012345601", dto.Registration.BigNummer);
|
||||
Assert.Equal("Geregistreerd", dto.Registration.Status.Tag);
|
||||
// seed deadline 2027-03-01 is within 12 months of "today" (2026) → eligible
|
||||
Assert.True(dto.Decisions.EligibleForHerregistratie);
|
||||
Assert.NotNull(dto.Decisions.HerregistratieReason);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Notes_returns_seeded_aantekeningen()
|
||||
{
|
||||
var notes = await _client.GetFromJsonAsync<List<AantekeningDto>>("/api/v1/notes");
|
||||
Assert.Equal(3, notes!.Count);
|
||||
}
|
||||
[Fact]
|
||||
public async Task Notes_returns_seeded_aantekeningen()
|
||||
{
|
||||
var notes = await _client.GetFromJsonAsync<List<AantekeningDto>>("/api/v1/notes");
|
||||
Assert.Equal(3, notes!.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Brp_returns_address()
|
||||
{
|
||||
var dto = await _client.GetFromJsonAsync<BrpAddressDto>("/api/v1/brp/address");
|
||||
Assert.True(dto!.Gevonden);
|
||||
Assert.Equal("2514 EA", dto.Adres!.Postcode);
|
||||
}
|
||||
[Fact]
|
||||
public async Task Brp_returns_address()
|
||||
{
|
||||
var dto = await _client.GetFromJsonAsync<BrpAddressDto>("/api/v1/brp/address");
|
||||
Assert.True(dto!.Gevonden);
|
||||
Assert.Equal("2514 EA", dto.Adres!.Postcode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Duo_lookup_carries_server_decided_questions_and_professions()
|
||||
{
|
||||
var dto = await _client.GetFromJsonAsync<DuoLookupDto>("/api/v1/duo/diplomas");
|
||||
Assert.NotNull(dto);
|
||||
[Fact]
|
||||
public async Task Duo_lookup_carries_server_decided_questions_and_professions()
|
||||
{
|
||||
var dto = await _client.GetFromJsonAsync<DuoLookupDto>("/api/v1/duo/diplomas");
|
||||
Assert.NotNull(dto);
|
||||
|
||||
var english = dto.Diplomas.Single(d => d.Id == "d2");
|
||||
Assert.Equal("Arts", english.Beroep);
|
||||
Assert.Contains(english.PolicyQuestions, q => q.Id == "nl-taalvaardigheid");
|
||||
var english = dto.Diplomas.Single(d => d.Id == "d2");
|
||||
Assert.Equal("Arts", english.Beroep);
|
||||
Assert.Contains(english.PolicyQuestions, q => q.Id == "nl-taalvaardigheid");
|
||||
|
||||
var dutch = dto.Diplomas.Single(d => d.Id == "d1");
|
||||
Assert.Empty(dutch.PolicyQuestions);
|
||||
var dutch = dto.Diplomas.Single(d => d.Id == "d1");
|
||||
Assert.Empty(dutch.PolicyQuestions);
|
||||
|
||||
// DUO "not found" fallback: an unlisted diploma → user uses the manual path,
|
||||
// which the same lookup provides (maximal question set + declarable professions).
|
||||
Assert.DoesNotContain(dto.Diplomas, d => d.Id == "unknown-id");
|
||||
Assert.Equal(3, dto.Handmatig.PolicyQuestions.Count);
|
||||
Assert.Equal(5, dto.Handmatig.Beroepen.Count);
|
||||
}
|
||||
// DUO "not found" fallback: an unlisted diploma → user uses the manual path,
|
||||
// which the same lookup provides (maximal question set + declarable professions).
|
||||
Assert.DoesNotContain(dto.Diplomas, d => d.Id == "unknown-id");
|
||||
Assert.Equal(3, dto.Handmatig.PolicyQuestions.Count);
|
||||
Assert.Equal(5, dto.Handmatig.Beroepen.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task IntakePolicy_returns_scholing_threshold()
|
||||
{
|
||||
var dto = await _client.GetFromJsonAsync<IntakePolicyDto>("/api/v1/intake/policy");
|
||||
Assert.Equal(1000, dto!.ScholingThreshold);
|
||||
}
|
||||
[Fact]
|
||||
public async Task IntakePolicy_returns_scholing_threshold()
|
||||
{
|
||||
var dto = await _client.GetFromJsonAsync<IntakePolicyDto>("/api/v1/intake/policy");
|
||||
Assert.Equal(1000, dto!.ScholingThreshold);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Registration_with_duo_diploma_succeeds()
|
||||
{
|
||||
var res = await _client.PostAsJsonAsync("/api/v1/registrations", new RegistratieRequest("duo"));
|
||||
res.EnsureSuccessStatusCode();
|
||||
var body = await res.Content.ReadFromJsonAsync<ReferentieResponse>();
|
||||
Assert.StartsWith("BIG-2026-", body!.Referentie);
|
||||
}
|
||||
[Fact]
|
||||
public async Task Registration_with_duo_diploma_succeeds()
|
||||
{
|
||||
var res = await _client.PostAsJsonAsync("/api/v1/registrations", new RegistratieRequest("duo"));
|
||||
res.EnsureSuccessStatusCode();
|
||||
var body = await res.Content.ReadFromJsonAsync<ReferentieResponse>();
|
||||
Assert.StartsWith("BIG-2026-", body!.Referentie);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Registration_with_manual_diploma_is_rejected_with_problem_details()
|
||||
{
|
||||
var res = await _client.PostAsJsonAsync("/api/v1/registrations", new RegistratieRequest("handmatig"));
|
||||
Assert.Equal(HttpStatusCode.UnprocessableEntity, res.StatusCode);
|
||||
Assert.Contains("application/problem+json", res.Content.Headers.ContentType!.ToString());
|
||||
}
|
||||
[Fact]
|
||||
public async Task Registration_with_manual_diploma_is_rejected_with_problem_details()
|
||||
{
|
||||
var res = await _client.PostAsJsonAsync("/api/v1/registrations", new RegistratieRequest("handmatig"));
|
||||
Assert.Equal(HttpStatusCode.UnprocessableEntity, res.StatusCode);
|
||||
Assert.Contains("application/problem+json", res.Content.Headers.ContentType!.ToString());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("/api/v1/intakes")]
|
||||
[InlineData("/api/v1/herregistraties")]
|
||||
public async Task Zero_hours_submission_is_rejected(string route)
|
||||
{
|
||||
var res = await _client.PostAsJsonAsync(route, new { uren = 0 });
|
||||
Assert.Equal(HttpStatusCode.UnprocessableEntity, res.StatusCode);
|
||||
}
|
||||
[Theory]
|
||||
[InlineData("/api/v1/intakes")]
|
||||
[InlineData("/api/v1/herregistraties")]
|
||||
public async Task Zero_hours_submission_is_rejected(string route)
|
||||
{
|
||||
var res = await _client.PostAsJsonAsync(route, new { uren = 0 });
|
||||
Assert.Equal(HttpStatusCode.UnprocessableEntity, res.StatusCode);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("/api/v1/intakes")]
|
||||
[InlineData("/api/v1/herregistraties")]
|
||||
public async Task Worked_hours_submission_succeeds(string route)
|
||||
{
|
||||
var res = await _client.PostAsJsonAsync(route, new { uren = 40 });
|
||||
res.EnsureSuccessStatusCode();
|
||||
}
|
||||
[Theory]
|
||||
[InlineData("/api/v1/intakes")]
|
||||
[InlineData("/api/v1/herregistraties")]
|
||||
public async Task Worked_hours_submission_succeeds(string route)
|
||||
{
|
||||
var res = await _client.PostAsJsonAsync(route, new { uren = 40 });
|
||||
res.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Change_request_with_valid_address_succeeds()
|
||||
{
|
||||
var res = await _client.PostAsJsonAsync("/api/v1/change-requests",
|
||||
new { straat = "Lange Voorhout 9", postcode = "2514 EA", woonplaats = "Den Haag" });
|
||||
res.EnsureSuccessStatusCode();
|
||||
var body = await res.Content.ReadFromJsonAsync<ReferentieResponse>();
|
||||
Assert.StartsWith("BIG-2026-", body!.Referentie);
|
||||
}
|
||||
[Fact]
|
||||
public async Task Change_request_with_valid_address_succeeds()
|
||||
{
|
||||
var res = await _client.PostAsJsonAsync("/api/v1/change-requests",
|
||||
new { straat = "Lange Voorhout 9", postcode = "2514 EA", woonplaats = "Den Haag" });
|
||||
res.EnsureSuccessStatusCode();
|
||||
var body = await res.Content.ReadFromJsonAsync<ReferentieResponse>();
|
||||
Assert.StartsWith("BIG-2026-", body!.Referentie);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Change_request_with_bad_postcode_is_rejected()
|
||||
{
|
||||
var res = await _client.PostAsJsonAsync("/api/v1/change-requests",
|
||||
new { straat = "Straat 1", postcode = "nope", woonplaats = "Den Haag" });
|
||||
Assert.Equal(HttpStatusCode.UnprocessableEntity, res.StatusCode);
|
||||
}
|
||||
[Fact]
|
||||
public async Task Change_request_with_bad_postcode_is_rejected()
|
||||
{
|
||||
var res = await _client.PostAsJsonAsync("/api/v1/change-requests",
|
||||
new { straat = "Straat 1", postcode = "nope", woonplaats = "Den Haag" });
|
||||
Assert.Equal(HttpStatusCode.UnprocessableEntity, res.StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Health_endpoint_is_ok()
|
||||
{
|
||||
var res = await _client.GetAsync("/health");
|
||||
res.EnsureSuccessStatusCode();
|
||||
}
|
||||
[Fact]
|
||||
public async Task Health_endpoint_is_ok()
|
||||
{
|
||||
var res = await _client.GetAsync("/health");
|
||||
res.EnsureSuccessStatusCode();
|
||||
}
|
||||
|
||||
// --- Document upload ---
|
||||
// --- Document upload ---
|
||||
|
||||
private static MultipartFormDataContent UploadForm(string localId, string categoryId, string wizardId, string fileName, string contentType)
|
||||
{
|
||||
var content = new MultipartFormDataContent();
|
||||
var file = new ByteArrayContent(new byte[] { 1, 2, 3 });
|
||||
file.Headers.ContentType = new MediaTypeHeaderValue(contentType);
|
||||
content.Add(file, "file", fileName);
|
||||
content.Add(new StringContent(categoryId), "categoryId");
|
||||
content.Add(new StringContent(localId), "localId");
|
||||
content.Add(new StringContent(wizardId), "wizardId");
|
||||
return content;
|
||||
}
|
||||
private static MultipartFormDataContent UploadForm(string localId, string categoryId, string wizardId, string fileName, string contentType)
|
||||
{
|
||||
var content = new MultipartFormDataContent();
|
||||
var file = new ByteArrayContent(new byte[] { 1, 2, 3 });
|
||||
file.Headers.ContentType = new MediaTypeHeaderValue(contentType);
|
||||
content.Add(file, "file", fileName);
|
||||
content.Add(new StringContent(categoryId), "categoryId");
|
||||
content.Add(new StringContent(localId), "localId");
|
||||
content.Add(new StringContent(wizardId), "wizardId");
|
||||
return content;
|
||||
}
|
||||
|
||||
private async Task<UploadResponse> Upload(string localId, string categoryId = "diploma", string type = "application/pdf", string file = "d.pdf")
|
||||
{
|
||||
var res = await _client.PostAsync("/api/v1/uploads", UploadForm(localId, categoryId, "registratie", file, type));
|
||||
Assert.Equal(HttpStatusCode.Created, res.StatusCode);
|
||||
return (await res.Content.ReadFromJsonAsync<UploadResponse>())!;
|
||||
}
|
||||
private async Task<UploadResponse> Upload(string localId, string categoryId = "diploma", string type = "application/pdf", string file = "d.pdf")
|
||||
{
|
||||
var res = await _client.PostAsync("/api/v1/uploads", UploadForm(localId, categoryId, "registratie", file, type));
|
||||
Assert.Equal(HttpStatusCode.Created, res.StatusCode);
|
||||
return (await res.Content.ReadFromJsonAsync<UploadResponse>())!;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Categories_are_server_owned_config()
|
||||
{
|
||||
// A manual diploma requires a diploma upload; identiteit is always required.
|
||||
var dto = await _client.GetFromJsonAsync<UploadCategoriesDto>("/api/v1/uploads/categories?wizardId=registratie&diplomaHerkomst=handmatig");
|
||||
Assert.Contains(dto!.Categories, c => c.CategoryId == "diploma" && c.Required && !c.AllowPostDelivery);
|
||||
Assert.Contains(dto.Categories, c => c.CategoryId == "identiteit" && c.AllowPostDelivery);
|
||||
}
|
||||
[Fact]
|
||||
public async Task Categories_are_server_owned_config()
|
||||
{
|
||||
// A manual diploma requires a diploma upload; identiteit is always required.
|
||||
var dto = await _client.GetFromJsonAsync<UploadCategoriesDto>("/api/v1/uploads/categories?wizardId=registratie&diplomaHerkomst=handmatig");
|
||||
Assert.Contains(dto!.Categories, c => c.CategoryId == "diploma" && c.Required && !c.AllowPostDelivery);
|
||||
Assert.Contains(dto.Categories, c => c.CategoryId == "identiteit" && c.AllowPostDelivery);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Upload_then_status_reports_complete_for_known_localId()
|
||||
{
|
||||
var localId = Guid.NewGuid().ToString();
|
||||
var doc = await Upload(localId);
|
||||
var status = await _client.GetFromJsonAsync<UploadStatusDto>($"/api/v1/uploads/status?localIds={localId},onbekend");
|
||||
Assert.Contains(status!.Results, r => r.LocalId == localId && r.Status == "complete" && r.DocumentId == doc.DocumentId);
|
||||
Assert.Contains(status.Results, r => r.LocalId == "onbekend" && r.Status == "unknown");
|
||||
}
|
||||
[Fact]
|
||||
public async Task Upload_then_status_reports_complete_for_known_localId()
|
||||
{
|
||||
var localId = Guid.NewGuid().ToString();
|
||||
var doc = await Upload(localId);
|
||||
var status = await _client.GetFromJsonAsync<UploadStatusDto>($"/api/v1/uploads/status?localIds={localId},onbekend");
|
||||
Assert.Contains(status!.Results, r => r.LocalId == localId && r.Status == "complete" && r.DocumentId == doc.DocumentId);
|
||||
Assert.Contains(status.Results, r => r.LocalId == "onbekend" && r.Status == "unknown");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Upload_content_is_served_back_with_its_type_inline_for_pdf()
|
||||
{
|
||||
var doc = await Upload(Guid.NewGuid().ToString());
|
||||
var res = await _client.GetAsync($"/api/v1/uploads/{doc.DocumentId}/content");
|
||||
res.EnsureSuccessStatusCode();
|
||||
Assert.Equal("application/pdf", res.Content.Headers.ContentType!.MediaType);
|
||||
Assert.Equal(new byte[] { 1, 2, 3 }, await res.Content.ReadAsByteArrayAsync());
|
||||
// pdf/image → inline (no attachment disposition) so the browser previews it
|
||||
Assert.NotEqual("attachment", res.Content.Headers.ContentDisposition?.DispositionType);
|
||||
}
|
||||
[Fact]
|
||||
public async Task Upload_content_is_served_back_with_its_type_inline_for_pdf()
|
||||
{
|
||||
var doc = await Upload(Guid.NewGuid().ToString());
|
||||
var res = await _client.GetAsync($"/api/v1/uploads/{doc.DocumentId}/content");
|
||||
res.EnsureSuccessStatusCode();
|
||||
Assert.Equal("application/pdf", res.Content.Headers.ContentType!.MediaType);
|
||||
Assert.Equal(new byte[] { 1, 2, 3 }, await res.Content.ReadAsByteArrayAsync());
|
||||
// pdf/image → inline (no attachment disposition) so the browser previews it
|
||||
Assert.NotEqual("attachment", res.Content.Headers.ContentDisposition?.DispositionType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Upload_content_404_for_unknown_document()
|
||||
{
|
||||
Assert.Equal(HttpStatusCode.NotFound, (await _client.GetAsync("/api/v1/uploads/demo-nope/content")).StatusCode);
|
||||
}
|
||||
[Fact]
|
||||
public async Task Upload_content_404_for_unknown_document()
|
||||
{
|
||||
Assert.Equal(HttpStatusCode.NotFound, (await _client.GetAsync("/api/v1/uploads/demo-nope/content")).StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Upload_rejects_wrong_type()
|
||||
{
|
||||
var res = await _client.PostAsync("/api/v1/uploads",
|
||||
UploadForm(Guid.NewGuid().ToString(), "diploma", "registratie", "d.txt", "text/plain"));
|
||||
Assert.Equal(HttpStatusCode.BadRequest, res.StatusCode);
|
||||
}
|
||||
[Fact]
|
||||
public async Task Upload_rejects_wrong_type()
|
||||
{
|
||||
var res = await _client.PostAsync("/api/v1/uploads",
|
||||
UploadForm(Guid.NewGuid().ToString(), "diploma", "registratie", "d.txt", "text/plain"));
|
||||
Assert.Equal(HttpStatusCode.BadRequest, res.StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task User_delete_succeeds_then_404()
|
||||
{
|
||||
var doc = await Upload(Guid.NewGuid().ToString());
|
||||
Assert.Equal(HttpStatusCode.NoContent, (await _client.DeleteAsync($"/api/v1/uploads/{doc.DocumentId}")).StatusCode);
|
||||
Assert.Equal(HttpStatusCode.NotFound, (await _client.DeleteAsync($"/api/v1/uploads/{doc.DocumentId}")).StatusCode);
|
||||
}
|
||||
[Fact]
|
||||
public async Task User_delete_succeeds_then_404()
|
||||
{
|
||||
var doc = await Upload(Guid.NewGuid().ToString());
|
||||
Assert.Equal(HttpStatusCode.NoContent, (await _client.DeleteAsync($"/api/v1/uploads/{doc.DocumentId}")).StatusCode);
|
||||
Assert.Equal(HttpStatusCode.NotFound, (await _client.DeleteAsync($"/api/v1/uploads/{doc.DocumentId}")).StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task User_delete_blocked_with_409_once_linked_to_submission()
|
||||
{
|
||||
var doc = await Upload(Guid.NewGuid().ToString());
|
||||
var submit = await _client.PostAsJsonAsync("/api/v1/registrations",
|
||||
new RegistratieRequest("duo", new[] { new DocumentRefDto("diploma", "digital", doc.DocumentId) }));
|
||||
submit.EnsureSuccessStatusCode();
|
||||
Assert.Equal(HttpStatusCode.Conflict, (await _client.DeleteAsync($"/api/v1/uploads/{doc.DocumentId}")).StatusCode);
|
||||
}
|
||||
[Fact]
|
||||
public async Task User_delete_blocked_with_409_once_linked_to_submission()
|
||||
{
|
||||
var doc = await Upload(Guid.NewGuid().ToString());
|
||||
var submit = await _client.PostAsJsonAsync("/api/v1/registrations",
|
||||
new RegistratieRequest("duo", new[] { new DocumentRefDto("diploma", "digital", doc.DocumentId) }));
|
||||
submit.EnsureSuccessStatusCode();
|
||||
Assert.Equal(HttpStatusCode.Conflict, (await _client.DeleteAsync($"/api/v1/uploads/{doc.DocumentId}")).StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Admin_delete_requires_admin_role()
|
||||
{
|
||||
var doc = await Upload(Guid.NewGuid().ToString());
|
||||
Assert.Equal(HttpStatusCode.Forbidden, (await _client.DeleteAsync($"/api/v1/admin/uploads/{doc.DocumentId}")).StatusCode);
|
||||
[Fact]
|
||||
public async Task Admin_delete_requires_admin_role()
|
||||
{
|
||||
var doc = await Upload(Guid.NewGuid().ToString());
|
||||
Assert.Equal(HttpStatusCode.Forbidden, (await _client.DeleteAsync($"/api/v1/admin/uploads/{doc.DocumentId}")).StatusCode);
|
||||
|
||||
var req = new HttpRequestMessage(HttpMethod.Delete, $"/api/v1/admin/uploads/{doc.DocumentId}");
|
||||
req.Headers.Add("X-Admin", "true");
|
||||
Assert.Equal(HttpStatusCode.NoContent, (await _client.SendAsync(req)).StatusCode);
|
||||
}
|
||||
var req = new HttpRequestMessage(HttpMethod.Delete, $"/api/v1/admin/uploads/{doc.DocumentId}");
|
||||
req.Headers.Add("X-Admin", "true");
|
||||
Assert.Equal(HttpStatusCode.NoContent, (await _client.SendAsync(req)).StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Audit_log_records_upload_and_delete_metadata_only()
|
||||
{
|
||||
var doc = await Upload(Guid.NewGuid().ToString());
|
||||
await _client.DeleteAsync($"/api/v1/uploads/{doc.DocumentId}");
|
||||
Assert.Contains(DocumentStore.AuditLog, a => a.DocumentId == doc.DocumentId && a.Action == "upload");
|
||||
Assert.Contains(DocumentStore.AuditLog, a => a.DocumentId == doc.DocumentId && a.Action == "delete-user");
|
||||
}
|
||||
[Fact]
|
||||
public async Task Audit_log_records_upload_and_delete_metadata_only()
|
||||
{
|
||||
var doc = await Upload(Guid.NewGuid().ToString());
|
||||
await _client.DeleteAsync($"/api/v1/uploads/{doc.DocumentId}");
|
||||
Assert.Contains(DocumentStore.AuditLog, a => a.DocumentId == doc.DocumentId && a.Action == "upload");
|
||||
Assert.Contains(DocumentStore.AuditLog, a => a.DocumentId == doc.DocumentId && a.Action == "delete-user");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user