package configkit import "gitea.maximumdirect.net/eric/ConfigKit/internal/document" type secretDependency struct { target Path dependency Path } func classifySecretPaths(schema *schemaDescriptor, predicate func(Path) bool, metadata Metadata, final *document.Node, applications []historyApplication) map[string]bool { paths := make(map[string]Path) finalPaths := make(map[string]*document.Node) indexDocument(final, Path{}, finalPaths) for pointer := range finalPaths { addSecretPath(paths, pointer) } for _, application := range applications { applicationPaths := make(map[string]*document.Node) indexDocument(application.value, application.path, applicationPaths) for pointer := range applicationPaths { addSecretPath(paths, pointer) } } var dependencies []secretDependency for pointer, history := range metadata.history { addSecretPath(paths, pointer) for _, change := range history { paths[change.Path.String()] = change.Path.clone() for _, dependency := range change.Dependencies { paths[dependency.String()] = dependency.clone() dependencies = append(dependencies, secretDependency{ target: change.Path.clone(), dependency: dependency.clone(), }) } } } secret := make(map[string]bool) for pointer, path := range paths { if root, ok := schemaSecretRoot(schema, path); ok { secret[root.String()] = true } if predicate != nil && predicate(path.clone()) { secret[pointer] = true } } for { changed := false for _, dependency := range dependencies { if secretIntersectsPath(paths, secret, dependency.dependency) && !secret[dependency.target.String()] { secret[dependency.target.String()] = true changed = true } } if !changed { return secret } } } func addSecretPath(paths map[string]Path, pointer string) { if path, err := ParsePath(pointer); err == nil { paths[pointer] = path } } func secretIntersectsPath(paths map[string]Path, secret map[string]bool, candidate Path) bool { for pointer := range secret { classified, ok := paths[pointer] if !ok { continue } if pathContains(classified, candidate) || pathContains(candidate, classified) { return true } } return false } func schemaSecretRoot(schema *schemaDescriptor, path Path) (Path, bool) { if schema == nil || schema.root == nil || !path.valid() { return Path{}, false } current := schema.root walked := Path{} for _, segment := range path.segments { walked.segments = append(walked.segments, segment) for current.kind == descriptorPointer { current = current.element } switch current.kind { case descriptorStruct: if segment.kind == pathSegmentIndex { return Path{}, false } position, ok := current.fieldByName[segment.key] var field *fieldDescriptor if ok { field = ¤t.fields[position] } else { field = current.inlineMap } if field == nil { return Path{}, false } if field.secret { return walked.clone(), true } if field.inlineMap { current = field.descriptor.element } else { current = field.descriptor } case descriptorMap: if segment.kind == pathSegmentIndex { return Path{}, false } current = current.element case descriptorSlice, descriptorArray: if _, ok := schemaIndex(segment); !ok { return Path{}, false } current = current.element case descriptorDynamic: return Path{}, false default: return Path{}, false } } return Path{}, false }