aravind changes
This commit is contained in:
@@ -150,7 +150,7 @@ func (s *Service) Get(ctx context.Context, ident authctx.Identity, id string) (d
|
||||
|
||||
// Create validates and inserts, returning the complete stored record.
|
||||
func (s *Service) Create(ctx context.Context, ident authctx.Identity, body domain.Record) (domain.Record, error) {
|
||||
clean, err := s.validate(body, true)
|
||||
clean, err := s.validate(ident, body, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -162,7 +162,7 @@ func (s *Service) Update(ctx context.Context, ident authctx.Identity, id string,
|
||||
if !isUUID(id) {
|
||||
return nil, domain.NotFound(s.res.Name, id)
|
||||
}
|
||||
clean, err := s.validate(patch, false)
|
||||
clean, err := s.validate(ident, patch, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -201,7 +201,11 @@ func (s *Service) Delete(ctx context.Context, ident authctx.Identity, id string)
|
||||
// exactly how `interview_id`, `training_outline` and `score_breakdown` would
|
||||
// have been lost: the frontend would have written them, the API would have
|
||||
// accepted the request, and the data would never have arrived.
|
||||
func (s *Service) validate(in domain.Record, isCreate bool) (domain.Record, error) {
|
||||
//
|
||||
// The identity is a parameter because "the server will supply this column"
|
||||
// is not a property of the column alone: a talent-only derivation supplies it
|
||||
// for a talent caller and for nobody else. See serverSupplies.
|
||||
func (s *Service) validate(ident authctx.Identity, in domain.Record, isCreate bool) (domain.Record, error) {
|
||||
details := map[string]string{}
|
||||
out := make(domain.Record, len(in))
|
||||
|
||||
@@ -237,7 +241,7 @@ func (s *Service) validate(in domain.Record, isCreate bool) (domain.Record, erro
|
||||
if !col.Required {
|
||||
continue
|
||||
}
|
||||
if s.serverSupplies(col.Name) {
|
||||
if s.serverSupplies(col.Name, ident) {
|
||||
// The repository fills this from the session, so demanding it
|
||||
// from the caller would reject a request the server is about to
|
||||
// complete correctly. evidence.worker_email is the live case.
|
||||
@@ -262,13 +266,24 @@ func (s *Service) validate(in domain.Record, isCreate bool) (domain.Record, erro
|
||||
}
|
||||
|
||||
// serverSupplies reports whether a column is filled in from the authenticated
|
||||
// session rather than from the request body.
|
||||
func (s *Service) serverSupplies(name string) bool {
|
||||
// session rather than from the request body, FOR THIS CALLER.
|
||||
//
|
||||
// The caller matters. A TalentOnly derivation records who the row is ABOUT, and
|
||||
// the repository fills it for a talent caller only — when an operator files an
|
||||
// application or logs evidence on somebody else's behalf, the subject is not
|
||||
// the operator, so nothing is derived and the value has to come from the body.
|
||||
// Treating those columns as server-supplied for every role was how an operator
|
||||
// creating a job application without an email got as far as SQL and came back
|
||||
// with a not-null violation instead of the required-field message the contract
|
||||
// promises. It must agree with repo.derivedValues, which decides the same thing
|
||||
// on the write path.
|
||||
func (s *Service) serverSupplies(name string, ident authctx.Identity) bool {
|
||||
if s.res.Policy == nil {
|
||||
return false
|
||||
}
|
||||
isTalent := ident.Role == string(domain.RoleTalent)
|
||||
for _, d := range s.res.Policy.Derived {
|
||||
if d.Column == name {
|
||||
if d.Column == name && (!d.TalentOnly || isTalent) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user