github.com/xmidt-org/webpa-common@v1.11.9/secure/key/resolverFactory.go (about) 1 package key 2 3 import ( 4 "fmt" 5 "time" 6 7 "github.com/xmidt-org/webpa-common/concurrent" 8 "github.com/xmidt-org/webpa-common/resource" 9 ) 10 11 const ( 12 // KeyIdParameterName is the template parameter that must be present in URI templates 13 // if there are any parameters. URI templates accepted by this package have either no parameters 14 // or exactly one (1) parameter with this name. 15 KeyIdParameterName = "keyId" 16 ) 17 18 var ( 19 // ErrorInvalidTemplate is the error returned when a URI template is invalid for a key resource 20 ErrorInvalidTemplate = fmt.Errorf( 21 "Key resource template must support either no parameters are the %s parameter", 22 KeyIdParameterName, 23 ) 24 ) 25 26 // ResolverFactory provides a JSON representation of a collection of keys together 27 // with a factory interface for creating distinct Resolver instances. 28 // 29 // This factory uses resource.NewExpander() to create a resource template used in resolving keys. 30 // This template can have no parameters, in which case the same resource is used regardless 31 // of the key id. If the template has any parameters, it must have exactly (1) parameter 32 // and that parameter's name must be equal to KeyIdParameterName. 33 type ResolverFactory struct { 34 resource.Factory 35 36 // All keys resolved by this factory will have this purpose, which affects 37 // how keys are parsed. 38 Purpose Purpose `json:"purpose"` 39 40 // UpdateInterval specifies how often keys should be refreshed. 41 // If negative or zero, keys are never refreshed and are cached forever. 42 UpdateInterval time.Duration `json:"updateInterval"` 43 44 // Parser is a custom key parser. If omitted, DefaultParser is used. 45 Parser Parser `json:"-"` 46 } 47 48 func (factory *ResolverFactory) parser() Parser { 49 if factory.Parser != nil { 50 return factory.Parser 51 } 52 53 return DefaultParser 54 } 55 56 // NewResolver() creates a Resolver using this factory's configuration. The 57 // returned Resolver always caches keys forever once they have been loaded. 58 func (factory *ResolverFactory) NewResolver() (Resolver, error) { 59 expander, err := factory.NewExpander() 60 if err != nil { 61 return nil, err 62 } 63 64 names := expander.Names() 65 nameCount := len(names) 66 if nameCount == 0 { 67 // the template had no parameters, so we can create a simpler object 68 loader, err := factory.NewLoader() 69 if err != nil { 70 return nil, err 71 } 72 73 return &singleCache{ 74 basicCache{ 75 delegate: &singleResolver{ 76 basicResolver: basicResolver{ 77 parser: factory.parser(), 78 purpose: factory.Purpose, 79 }, 80 loader: loader, 81 }, 82 }, 83 }, nil 84 } else if nameCount == 1 && names[0] == KeyIdParameterName { 85 return &multiCache{ 86 basicCache{ 87 delegate: &multiResolver{ 88 basicResolver: basicResolver{ 89 parser: factory.parser(), 90 purpose: factory.Purpose, 91 }, 92 expander: expander, 93 }, 94 }, 95 }, nil 96 } 97 98 return nil, ErrorInvalidTemplate 99 } 100 101 // NewUpdater uses this factory's configuration to conditionally create a Runnable updater 102 // for the given resolver. This method delegates to the NewUpdater function, and may 103 // return a nil Runnable if no updates are necessary. 104 func (factory *ResolverFactory) NewUpdater(resolver Resolver) concurrent.Runnable { 105 return NewUpdater(time.Duration(factory.UpdateInterval), resolver) 106 }