aravind changes

This commit is contained in:
2026-08-25 16:37:05 +05:30
parent cadea4bd92
commit b6f8655909
27 changed files with 5058 additions and 163 deletions

View File

@@ -1,12 +1,20 @@
package service
import (
"errors"
"net/url"
"testing"
"github.com/krow/krow-backend/go-api/internal/authctx"
"github.com/krow/krow-backend/go-api/internal/domain"
)
// The two callers validation distinguishes. Only the role is read.
var (
asOperator = authctx.Identity{Role: string(domain.RoleAdmin)}
asTalent = authctx.Identity{Role: string(domain.RoleTalent)}
)
// These exercise query parsing and validation without a database, so the
// contract's defaults are pinned even when PostgreSQL is not available.
@@ -139,24 +147,24 @@ func TestReservedParametersAreNotFilters(t *testing.T) {
func TestValidateRequiredAndUnknownAndEnum(t *testing.T) {
svc := New(resource(t, "job-postings"), nil)
if _, err := svc.validate(domain.Record{}, true); err == nil {
if _, err := svc.validate(asOperator, domain.Record{}, true); err == nil {
t.Error("a create with no title was accepted")
}
if _, err := svc.validate(domain.Record{"title": " "}, true); err == nil {
if _, err := svc.validate(asOperator, domain.Record{"title": " "}, true); err == nil {
t.Error("a blank title was accepted")
}
if _, err := svc.validate(domain.Record{"title": "X", "bogus": 1}, true); err == nil {
if _, err := svc.validate(asOperator, domain.Record{"title": "X", "bogus": 1}, true); err == nil {
t.Error("an unknown field was accepted")
}
if _, err := svc.validate(domain.Record{"title": "X", "status": "archived"}, true); err == nil {
if _, err := svc.validate(asOperator, domain.Record{"title": "X", "status": "archived"}, true); err == nil {
t.Error("an invalid enum value was accepted")
}
if _, err := svc.validate(domain.Record{"title": "X", "status": "active"}, true); err != nil {
if _, err := svc.validate(asOperator, domain.Record{"title": "X", "status": "active"}, true); err != nil {
t.Errorf("a valid payload was rejected: %v", err)
}
// Server-owned fields are stripped, not rejected.
out, err := svc.validate(domain.Record{"title": "X", "id": "abc", "org_id": "def"}, true)
out, err := svc.validate(asOperator, domain.Record{"title": "X", "id": "abc", "org_id": "def"}, true)
if err != nil {
t.Fatalf("server-owned fields caused a rejection: %v", err)
}
@@ -168,11 +176,62 @@ func TestValidateRequiredAndUnknownAndEnum(t *testing.T) {
}
// An update needs no required fields — it is a partial by definition.
if _, err := svc.validate(domain.Record{"location": "Here"}, false); err != nil {
if _, err := svc.validate(asOperator, domain.Record{"location": "Here"}, false); err != nil {
t.Errorf("a partial update was rejected: %v", err)
}
}
// A talent-only derivation is only server-supplied for a talent caller.
//
// The column records who the row is ABOUT, and the repository fills it from the
// session for talent and for nobody else (repo.derivedValues). Validation has
// to agree: an operator filing an application for somebody else must be told
// `email` is required, rather than being let through to a not-null violation
// from SQL — and a talent caller must not be asked for the value the server is
// about to override anyway.
func TestValidateHonoursTalentOnlyDerivation(t *testing.T) {
apps := New(resource(t, "job-applications"), nil)
body := domain.Record{
"job_posting_id": "00000000-0000-0000-0000-000000000000",
"applicant_name": "Someone",
}
if _, err := apps.validate(asTalent, body, true); err != nil {
t.Errorf("a talent create without email was rejected: %v", err)
}
_, err := apps.validate(asOperator, body, true)
if err == nil {
t.Fatal("an operator create without email was accepted")
}
var apiErr *domain.Error
if !errors.As(err, &apiErr) {
t.Fatalf("error is not an API error: %v", err)
}
if apiErr.Details["email"] != "required" {
t.Errorf("details = %v, want email: required", apiErr.Details)
}
// evidence.worker_email is the same shape, and the case the original
// comment in serverSupplies was written for.
ev := New(resource(t, "evidence"), nil)
if _, err := ev.validate(asTalent, domain.Record{"type": "photo_identify"}, true); err != nil {
t.Errorf("a talent evidence create without worker_email was rejected: %v", err)
}
if _, err := ev.validate(asOperator, domain.Record{"type": "photo_identify"}, true); err == nil {
t.Error("an operator evidence create without worker_email was accepted")
}
// A derivation that is NOT talent-only stays server-supplied for everyone:
// user_activity records who acted, whoever that is.
act := New(resource(t, "user-activity"), nil)
for name, ident := range map[string]authctx.Identity{"operator": asOperator, "talent": asTalent} {
if _, err := act.validate(ident, domain.Record{"event_type": "x"}, true); err != nil {
t.Errorf("%s: an activity create was rejected: %v", name, err)
}
}
}
func TestIsUUID(t *testing.T) {
valid := []string{
"00000000-0000-0000-0000-000000000000",