diff --git a/cmd/policy/main.go b/cmd/policy/main.go index b8257f6c50cc1f31254ef182e5b11826ee9fa8cb..cd489f786f0bdd81dd3ecdfbaf5fb3cbdb36fae3 100644 --- a/cmd/policy/main.go +++ b/cmd/policy/main.go @@ -86,9 +86,6 @@ func main() { // create rego policy cache regocache := regocache.New() - // create policy changes notifier - notifier := notify.New(events) - // connect to mongo db db, err := mongo.Connect( context.Background(), @@ -109,6 +106,9 @@ func main() { logger.Fatal("error connecting to database", zap.Error(err)) } + // create policy changes notifier + notifier := notify.New(events, httpClient, storage, logger) + // subscribe the cache for policy data changes storage.AddPolicyChangeSubscribers(regocache, notifier) diff --git a/design/design.go b/design/design.go index a1af34032ad4f377d54b00ff642a5addf19c13ab..971fdbf748bdffdcef01d051eb75384ead902fd5 100644 --- a/design/design.go +++ b/design/design.go @@ -1,7 +1,9 @@ // nolint:revive package design -import . "goa.design/goa/v3/dsl" +import ( + . "goa.design/goa/v3/dsl" +) var _ = API("policy", func() { Title("Policy Service") @@ -75,6 +77,16 @@ var _ = Service("policy", func() { Response(StatusOK) }) }) + + Method("Webhooks", func() { + Description("Gives ability to user to subscribe for policy change via webhooks") + Payload(WebhooksRequest) + Result(Any) + HTTP(func() { + POST("/policy/{group}/{policyname}/{version}/notifychange") + Response(StatusOK) + }) + }) }) var _ = Service("health", func() { diff --git a/design/types.go b/design/types.go index 2b2ed7d68e94798420624ca64685d279340f4eb6..8d47f542be96ae79d1d56eb091387e65bdd3ae77 100644 --- a/design/types.go +++ b/design/types.go @@ -1,7 +1,9 @@ // nolint:revive package design -import . "goa.design/goa/v3/dsl" +import ( + . "goa.design/goa/v3/dsl" +) var EvaluateRequest = Type("EvaluateRequest", func() { Field(1, "group", String, "Policy group.", func() { @@ -62,3 +64,12 @@ var PoliciesResult = Type("PoliciesResult", func() { Field(1, "policies", ArrayOf(Policy), "JSON array of policies.") Required("policies") }) + +var WebhooksRequest = Type("WebHooksRequest", func() { + Field(1, "webhook_url", String, "Subscriber webhook url.") + Field(2, "subscriber", String, "Name of the subscriber for policy.") + Field(3, "policyname", String, "Policy name.") + Field(4, "group", String, "Policy group.") + Field(5, "version", String, "Policy version.") + Required("webhook_url", "subscriber", "group", "policyname", "version") +}) diff --git a/gen/http/cli/policy/cli.go b/gen/http/cli/policy/cli.go index 65eb4e07570da777903af00b7b5a80ad12600f26..0ef0f3fe48e6c1275204613abd12a128c2eeed76 100644 --- a/gen/http/cli/policy/cli.go +++ b/gen/http/cli/policy/cli.go @@ -24,14 +24,14 @@ import ( // command (subcommand1|subcommand2|...) func UsageCommands() string { return `health (liveness|readiness) -policy (evaluate|lock|unlock|list-policies) +policy (evaluate|lock|unlock|list-policies|webhooks) ` } // UsageExamples produces an example of a valid invocation of the CLI tool. func UsageExamples() string { return os.Args[0] + ` health liveness` + "\n" + - os.Args[0] + ` policy evaluate --body "Quibusdam ab repellendus in illum." --group "example" --policy-name "example" --version "1.0" --evaluation-id "Nihil repudiandae dolore quod sunt aut." --ttl 4633716418015214972` + "\n" + + os.Args[0] + ` policy evaluate --body "Earum velit illum quia aliquam atque voluptatum." --group "example" --policy-name "example" --version "1.0" --evaluation-id "Omnis quasi aut consequuntur." --ttl 2830259876533307070` + "\n" + "" } @@ -76,6 +76,12 @@ func ParseEndpoint( policyListPoliciesRegoFlag = policyListPoliciesFlags.String("rego", "", "") policyListPoliciesDataFlag = policyListPoliciesFlags.String("data", "", "") policyListPoliciesDataConfigFlag = policyListPoliciesFlags.String("data-config", "", "") + + policyWebhooksFlags = flag.NewFlagSet("webhooks", flag.ExitOnError) + policyWebhooksBodyFlag = policyWebhooksFlags.String("body", "REQUIRED", "") + policyWebhooksGroupFlag = policyWebhooksFlags.String("group", "REQUIRED", "Policy group.") + policyWebhooksPolicynameFlag = policyWebhooksFlags.String("policyname", "REQUIRED", "Policy name.") + policyWebhooksVersionFlag = policyWebhooksFlags.String("version", "REQUIRED", "Policy version.") ) healthFlags.Usage = healthUsage healthLivenessFlags.Usage = healthLivenessUsage @@ -86,6 +92,7 @@ func ParseEndpoint( policyLockFlags.Usage = policyLockUsage policyUnlockFlags.Usage = policyUnlockUsage policyListPoliciesFlags.Usage = policyListPoliciesUsage + policyWebhooksFlags.Usage = policyWebhooksUsage if err := flag.CommandLine.Parse(os.Args[1:]); err != nil { return nil, nil, err @@ -145,6 +152,9 @@ func ParseEndpoint( case "list-policies": epf = policyListPoliciesFlags + case "webhooks": + epf = policyWebhooksFlags + } } @@ -192,6 +202,9 @@ func ParseEndpoint( case "list-policies": endpoint = c.ListPolicies() data, err = policyc.BuildListPoliciesPayload(*policyListPoliciesLockedFlag, *policyListPoliciesRegoFlag, *policyListPoliciesDataFlag, *policyListPoliciesDataConfigFlag) + case "webhooks": + endpoint = c.Webhooks() + data, err = policyc.BuildWebhooksPayload(*policyWebhooksBodyFlag, *policyWebhooksGroupFlag, *policyWebhooksPolicynameFlag, *policyWebhooksVersionFlag) } } } @@ -247,6 +260,7 @@ COMMAND: lock: Lock a policy so that it cannot be evaluated. unlock: Unlock a policy so it can be evaluated again. list-policies: List policies from storage with optional filters. + webhooks: Gives ability to user to subscribe for policy change via webhooks Additional help: %[1]s policy COMMAND --help @@ -264,7 +278,7 @@ Evaluate executes a policy with the given 'data' as input. -ttl INT: Example: - %[1]s policy evaluate --body "Quibusdam ab repellendus in illum." --group "example" --policy-name "example" --version "1.0" --evaluation-id "Nihil repudiandae dolore quod sunt aut." --ttl 4633716418015214972 + %[1]s policy evaluate --body "Earum velit illum quia aliquam atque voluptatum." --group "example" --policy-name "example" --version "1.0" --evaluation-id "Omnis quasi aut consequuntur." --ttl 2830259876533307070 `, os.Args[0]) } @@ -277,7 +291,7 @@ Lock a policy so that it cannot be evaluated. -version STRING: Policy version. Example: - %[1]s policy lock --group "Aliquam atque voluptatum ut dolorem." --policy-name "Aut facere veniam repudiandae id." --version "Aut minus alias." + %[1]s policy lock --group "Aut voluptas." --policy-name "Sint nam voluptatem ea consequatur similique et." --version "Non mollitia nesciunt impedit facere." `, os.Args[0]) } @@ -290,7 +304,7 @@ Unlock a policy so it can be evaluated again. -version STRING: Policy version. Example: - %[1]s policy unlock --group "Aut voluptas." --policy-name "Sint nam voluptatem ea consequatur similique et." --version "Non mollitia nesciunt impedit facere." + %[1]s policy unlock --group "In quis nesciunt autem et." --policy-name "Sunt in et quia cum." --version "Commodi nemo fugiat id praesentium accusantium expedita." `, os.Args[0]) } @@ -304,6 +318,23 @@ List policies from storage with optional filters. -data-config BOOL: Example: - %[1]s policy list-policies --locked false --rego true --data false --data-config false + %[1]s policy list-policies --locked false --rego true --data false --data-config true +`, os.Args[0]) +} + +func policyWebhooksUsage() { + fmt.Fprintf(os.Stderr, `%[1]s [flags] policy webhooks -body JSON -group STRING -policyname STRING -version STRING + +Gives ability to user to subscribe for policy change via webhooks + -body JSON: + -group STRING: Policy group. + -policyname STRING: Policy name. + -version STRING: Policy version. + +Example: + %[1]s policy webhooks --body '{ + "subscriber": "Est totam officia necessitatibus tempore.", + "webhook_url": "Ad ab perspiciatis voluptatem pariatur corporis est." + }' --group "Animi consequuntur consequatur vel rerum." --policyname "Ipsam nam." --version "Vitae dolores quas et aperiam dolores reiciendis." `, os.Args[0]) } diff --git a/gen/http/openapi.json b/gen/http/openapi.json index 9305711eca0a6d7ccd6bb112a789ee5292605307..f8384375ce127787df963daa5ec7895db7726367 100644 --- a/gen/http/openapi.json +++ b/gen/http/openapi.json @@ -1 +1 @@ -{"swagger":"2.0","info":{"title":"Policy Service","description":"The policy service exposes HTTP API for executing policies.","version":""},"host":"localhost:8081","consumes":["application/json","application/xml","application/gob"],"produces":["application/json","application/xml","application/gob"],"paths":{"/liveness":{"get":{"tags":["health"],"summary":"Liveness health","operationId":"health#Liveness","responses":{"200":{"description":"OK response."}},"schemes":["http"]}},"/policy/{group}/{policyName}/{version}/evaluation":{"get":{"tags":["policy"],"summary":"Evaluate policy","description":"Evaluate executes a policy with the given 'data' as input.","operationId":"policy#Evaluate#1","parameters":[{"name":"group","in":"path","description":"Policy group.","required":true,"type":"string"},{"name":"policyName","in":"path","description":"Policy name.","required":true,"type":"string"},{"name":"version","in":"path","description":"Policy version.","required":true,"type":"string"},{"name":"x-evaluation-id","in":"header","description":"EvaluationID allows overwriting the randomly generated evaluationID","required":false,"type":"string"},{"name":"x-cache-ttl","in":"header","description":"Policy result cache TTL in seconds","required":false,"type":"integer"},{"name":"any","in":"body","description":"Input data passed to the policy execution runtime.","required":true,"schema":{"type":"string","format":"binary"}}],"responses":{"200":{"description":"OK response.","schema":{"type":"string","format":"binary"},"headers":{"ETag":{"description":"ETag contains unique identifier of the policy evaluation and can be used to later retrieve the results from Cache.","type":"string"}}}},"schemes":["http"]},"post":{"tags":["policy"],"summary":"Evaluate policy","description":"Evaluate executes a policy with the given 'data' as input.","operationId":"policy#Evaluate#2","parameters":[{"name":"group","in":"path","description":"Policy group.","required":true,"type":"string"},{"name":"policyName","in":"path","description":"Policy name.","required":true,"type":"string"},{"name":"version","in":"path","description":"Policy version.","required":true,"type":"string"},{"name":"x-evaluation-id","in":"header","description":"EvaluationID allows overwriting the randomly generated evaluationID","required":false,"type":"string"},{"name":"x-cache-ttl","in":"header","description":"Policy result cache TTL in seconds","required":false,"type":"integer"},{"name":"any","in":"body","description":"Input data passed to the policy execution runtime.","required":true,"schema":{"type":"string","format":"binary"}}],"responses":{"200":{"description":"OK response.","schema":{"type":"string","format":"binary"},"headers":{"ETag":{"description":"ETag contains unique identifier of the policy evaluation and can be used to later retrieve the results from Cache.","type":"string"}}}},"schemes":["http"]}},"/policy/{group}/{policyName}/{version}/evaluation/did.json":{"get":{"tags":["policy"],"summary":"Evaluate policy","description":"Evaluate executes a policy with the given 'data' as input.","operationId":"policy#Evaluate","parameters":[{"name":"group","in":"path","description":"Policy group.","required":true,"type":"string"},{"name":"policyName","in":"path","description":"Policy name.","required":true,"type":"string"},{"name":"version","in":"path","description":"Policy version.","required":true,"type":"string"},{"name":"x-evaluation-id","in":"header","description":"EvaluationID allows overwriting the randomly generated evaluationID","required":false,"type":"string"},{"name":"x-cache-ttl","in":"header","description":"Policy result cache TTL in seconds","required":false,"type":"integer"},{"name":"any","in":"body","description":"Input data passed to the policy execution runtime.","required":true,"schema":{"type":"string","format":"binary"}}],"responses":{"200":{"description":"OK response.","schema":{"type":"string","format":"binary"},"headers":{"ETag":{"description":"ETag contains unique identifier of the policy evaluation and can be used to later retrieve the results from Cache.","type":"string"}}}},"schemes":["http"]}},"/policy/{group}/{policyName}/{version}/lock":{"post":{"tags":["policy"],"summary":"Lock policy","description":"Lock a policy so that it cannot be evaluated.","operationId":"policy#Lock","parameters":[{"name":"group","in":"path","description":"Policy group.","required":true,"type":"string"},{"name":"policyName","in":"path","description":"Policy name.","required":true,"type":"string"},{"name":"version","in":"path","description":"Policy version.","required":true,"type":"string"}],"responses":{"200":{"description":"OK response."}},"schemes":["http"]},"delete":{"tags":["policy"],"summary":"Unlock policy","description":"Unlock a policy so it can be evaluated again.","operationId":"policy#Unlock","parameters":[{"name":"group","in":"path","description":"Policy group.","required":true,"type":"string"},{"name":"policyName","in":"path","description":"Policy name.","required":true,"type":"string"},{"name":"version","in":"path","description":"Policy version.","required":true,"type":"string"}],"responses":{"200":{"description":"OK response."}},"schemes":["http"]}},"/readiness":{"get":{"tags":["health"],"summary":"Readiness health","operationId":"health#Readiness","responses":{"200":{"description":"OK response."}},"schemes":["http"]}},"/v1/policies":{"get":{"tags":["policy"],"summary":"ListPolicies policy","description":"List policies from storage with optional filters.","operationId":"policy#ListPolicies","parameters":[{"name":"locked","in":"query","description":"Filter to return locked/unlocked policies (optional).","required":false,"type":"boolean"},{"name":"rego","in":"query","description":"Include policy source code in results (optional).","required":false,"type":"boolean"},{"name":"data","in":"query","description":"Include policy static data in results (optional). ","required":false,"type":"boolean"},{"name":"dataConfig","in":"query","description":"Include static data config (optional).","required":false,"type":"boolean"}],"responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/PolicyListPoliciesResponseBody","required":["policies"]}}},"schemes":["http"]}}},"definitions":{"PolicyListPoliciesResponseBody":{"title":"PolicyListPoliciesResponseBody","type":"object","properties":{"policies":{"type":"array","items":{"$ref":"#/definitions/PolicyResponseBody"},"description":"JSON array of policies.","example":[{"data":"Commodi nemo fugiat id praesentium accusantium expedita.","dataConfig":"Qui non quia.","group":"Sequi adipisci et nulla.","lastUpdate":8181859392515170659,"locked":false,"policyName":"Consequatur accusamus.","rego":"Sunt in et quia cum.","version":"In quis nesciunt autem et."},{"data":"Commodi nemo fugiat id praesentium accusantium expedita.","dataConfig":"Qui non quia.","group":"Sequi adipisci et nulla.","lastUpdate":8181859392515170659,"locked":false,"policyName":"Consequatur accusamus.","rego":"Sunt in et quia cum.","version":"In quis nesciunt autem et."},{"data":"Commodi nemo fugiat id praesentium accusantium expedita.","dataConfig":"Qui non quia.","group":"Sequi adipisci et nulla.","lastUpdate":8181859392515170659,"locked":false,"policyName":"Consequatur accusamus.","rego":"Sunt in et quia cum.","version":"In quis nesciunt autem et."}]}},"example":{"policies":[{"data":"Commodi nemo fugiat id praesentium accusantium expedita.","dataConfig":"Qui non quia.","group":"Sequi adipisci et nulla.","lastUpdate":8181859392515170659,"locked":false,"policyName":"Consequatur accusamus.","rego":"Sunt in et quia cum.","version":"In quis nesciunt autem et."},{"data":"Commodi nemo fugiat id praesentium accusantium expedita.","dataConfig":"Qui non quia.","group":"Sequi adipisci et nulla.","lastUpdate":8181859392515170659,"locked":false,"policyName":"Consequatur accusamus.","rego":"Sunt in et quia cum.","version":"In quis nesciunt autem et."},{"data":"Commodi nemo fugiat id praesentium accusantium expedita.","dataConfig":"Qui non quia.","group":"Sequi adipisci et nulla.","lastUpdate":8181859392515170659,"locked":false,"policyName":"Consequatur accusamus.","rego":"Sunt in et quia cum.","version":"In quis nesciunt autem et."},{"data":"Commodi nemo fugiat id praesentium accusantium expedita.","dataConfig":"Qui non quia.","group":"Sequi adipisci et nulla.","lastUpdate":8181859392515170659,"locked":false,"policyName":"Consequatur accusamus.","rego":"Sunt in et quia cum.","version":"In quis nesciunt autem et."}]},"required":["policies"]},"PolicyResponseBody":{"title":"PolicyResponseBody","type":"object","properties":{"data":{"type":"string","description":"Policy static data.","example":"Accusamus enim."},"dataConfig":{"type":"string","description":"Policy static data optional configuration.","example":"Recusandae est rerum corrupti quia."},"group":{"type":"string","description":"Policy group.","example":"Optio quia et laborum."},"lastUpdate":{"type":"integer","description":"Last update (Unix timestamp).","example":1029654258457164464,"format":"int64"},"locked":{"type":"boolean","description":"Locked specifies if the policy is locked or allowed to execute.","example":true},"policyName":{"type":"string","description":"Policy name.","example":"Quia non voluptatibus error."},"rego":{"type":"string","description":"Policy rego source code.","example":"Ut amet."},"version":{"type":"string","description":"Policy version.","example":"In libero perspiciatis voluptatum ut soluta."}},"example":{"data":"Totam officia necessitatibus tempore nulla animi.","dataConfig":"Consequatur vel rerum rem ipsam nam.","group":"Adipisci inventore ipsum voluptatibus recusandae.","lastUpdate":1724369781608544610,"locked":true,"policyName":"Architecto itaque voluptatum voluptas ad.","rego":"Ab perspiciatis voluptatem pariatur corporis est rem.","version":"Nisi distinctio vitae."},"required":["group","policyName","version","locked","lastUpdate"]}}} \ No newline at end of file +{"swagger":"2.0","info":{"title":"Policy Service","description":"The policy service exposes HTTP API for executing policies.","version":""},"host":"localhost:8081","consumes":["application/json","application/xml","application/gob"],"produces":["application/json","application/xml","application/gob"],"paths":{"/liveness":{"get":{"tags":["health"],"summary":"Liveness health","operationId":"health#Liveness","responses":{"200":{"description":"OK response."}},"schemes":["http"]}},"/policy/{group}/{policyName}/{version}/evaluation":{"get":{"tags":["policy"],"summary":"Evaluate policy","description":"Evaluate executes a policy with the given 'data' as input.","operationId":"policy#Evaluate#1","parameters":[{"name":"group","in":"path","description":"Policy group.","required":true,"type":"string"},{"name":"policyName","in":"path","description":"Policy name.","required":true,"type":"string"},{"name":"version","in":"path","description":"Policy version.","required":true,"type":"string"},{"name":"x-evaluation-id","in":"header","description":"EvaluationID allows overwriting the randomly generated evaluationID","required":false,"type":"string"},{"name":"x-cache-ttl","in":"header","description":"Policy result cache TTL in seconds","required":false,"type":"integer"},{"name":"any","in":"body","description":"Input data passed to the policy execution runtime.","required":true,"schema":{"type":"string","format":"binary"}}],"responses":{"200":{"description":"OK response.","schema":{"type":"string","format":"binary"},"headers":{"ETag":{"description":"ETag contains unique identifier of the policy evaluation and can be used to later retrieve the results from Cache.","type":"string"}}}},"schemes":["http"]},"post":{"tags":["policy"],"summary":"Evaluate policy","description":"Evaluate executes a policy with the given 'data' as input.","operationId":"policy#Evaluate#2","parameters":[{"name":"group","in":"path","description":"Policy group.","required":true,"type":"string"},{"name":"policyName","in":"path","description":"Policy name.","required":true,"type":"string"},{"name":"version","in":"path","description":"Policy version.","required":true,"type":"string"},{"name":"x-evaluation-id","in":"header","description":"EvaluationID allows overwriting the randomly generated evaluationID","required":false,"type":"string"},{"name":"x-cache-ttl","in":"header","description":"Policy result cache TTL in seconds","required":false,"type":"integer"},{"name":"any","in":"body","description":"Input data passed to the policy execution runtime.","required":true,"schema":{"type":"string","format":"binary"}}],"responses":{"200":{"description":"OK response.","schema":{"type":"string","format":"binary"},"headers":{"ETag":{"description":"ETag contains unique identifier of the policy evaluation and can be used to later retrieve the results from Cache.","type":"string"}}}},"schemes":["http"]}},"/policy/{group}/{policyName}/{version}/evaluation/did.json":{"get":{"tags":["policy"],"summary":"Evaluate policy","description":"Evaluate executes a policy with the given 'data' as input.","operationId":"policy#Evaluate","parameters":[{"name":"group","in":"path","description":"Policy group.","required":true,"type":"string"},{"name":"policyName","in":"path","description":"Policy name.","required":true,"type":"string"},{"name":"version","in":"path","description":"Policy version.","required":true,"type":"string"},{"name":"x-evaluation-id","in":"header","description":"EvaluationID allows overwriting the randomly generated evaluationID","required":false,"type":"string"},{"name":"x-cache-ttl","in":"header","description":"Policy result cache TTL in seconds","required":false,"type":"integer"},{"name":"any","in":"body","description":"Input data passed to the policy execution runtime.","required":true,"schema":{"type":"string","format":"binary"}}],"responses":{"200":{"description":"OK response.","schema":{"type":"string","format":"binary"},"headers":{"ETag":{"description":"ETag contains unique identifier of the policy evaluation and can be used to later retrieve the results from Cache.","type":"string"}}}},"schemes":["http"]}},"/policy/{group}/{policyName}/{version}/lock":{"post":{"tags":["policy"],"summary":"Lock policy","description":"Lock a policy so that it cannot be evaluated.","operationId":"policy#Lock","parameters":[{"name":"group","in":"path","description":"Policy group.","required":true,"type":"string"},{"name":"policyName","in":"path","description":"Policy name.","required":true,"type":"string"},{"name":"version","in":"path","description":"Policy version.","required":true,"type":"string"}],"responses":{"200":{"description":"OK response."}},"schemes":["http"]},"delete":{"tags":["policy"],"summary":"Unlock policy","description":"Unlock a policy so it can be evaluated again.","operationId":"policy#Unlock","parameters":[{"name":"group","in":"path","description":"Policy group.","required":true,"type":"string"},{"name":"policyName","in":"path","description":"Policy name.","required":true,"type":"string"},{"name":"version","in":"path","description":"Policy version.","required":true,"type":"string"}],"responses":{"200":{"description":"OK response."}},"schemes":["http"]}},"/policy/{group}/{policyname}/{version}/notifychange":{"post":{"tags":["policy"],"summary":"Webhooks policy","description":"Gives ability to user to subscribe for policy change via webhooks","operationId":"policy#Webhooks","parameters":[{"name":"group","in":"path","description":"Policy group.","required":true,"type":"string"},{"name":"policyname","in":"path","description":"Policy name.","required":true,"type":"string"},{"name":"version","in":"path","description":"Policy version.","required":true,"type":"string"},{"name":"WebhooksRequestBody","in":"body","required":true,"schema":{"$ref":"#/definitions/PolicyWebhooksRequestBody","required":["webhook_url","subscriber"]}}],"responses":{"200":{"description":"OK response.","schema":{"type":"string","format":"binary"}}},"schemes":["http"]}},"/readiness":{"get":{"tags":["health"],"summary":"Readiness health","operationId":"health#Readiness","responses":{"200":{"description":"OK response."}},"schemes":["http"]}},"/v1/policies":{"get":{"tags":["policy"],"summary":"ListPolicies policy","description":"List policies from storage with optional filters.","operationId":"policy#ListPolicies","parameters":[{"name":"locked","in":"query","description":"Filter to return locked/unlocked policies (optional).","required":false,"type":"boolean"},{"name":"rego","in":"query","description":"Include policy source code in results (optional).","required":false,"type":"boolean"},{"name":"data","in":"query","description":"Include policy static data in results (optional). ","required":false,"type":"boolean"},{"name":"dataConfig","in":"query","description":"Include static data config (optional).","required":false,"type":"boolean"}],"responses":{"200":{"description":"OK response.","schema":{"$ref":"#/definitions/PolicyListPoliciesResponseBody","required":["policies"]}}},"schemes":["http"]}}},"definitions":{"PolicyListPoliciesResponseBody":{"title":"PolicyListPoliciesResponseBody","type":"object","properties":{"policies":{"type":"array","items":{"$ref":"#/definitions/PolicyResponseBody"},"description":"JSON array of policies.","example":[{"data":"Accusamus enim.","dataConfig":"Recusandae est rerum corrupti quia.","group":"Optio quia et laborum.","lastUpdate":1029654258457164464,"locked":true,"policyName":"Error maxime quasi quia non voluptatibus error.","rego":"Ut amet.","version":"In libero perspiciatis voluptatum ut soluta."},{"data":"Accusamus enim.","dataConfig":"Recusandae est rerum corrupti quia.","group":"Optio quia et laborum.","lastUpdate":1029654258457164464,"locked":true,"policyName":"Error maxime quasi quia non voluptatibus error.","rego":"Ut amet.","version":"In libero perspiciatis voluptatum ut soluta."},{"data":"Accusamus enim.","dataConfig":"Recusandae est rerum corrupti quia.","group":"Optio quia et laborum.","lastUpdate":1029654258457164464,"locked":true,"policyName":"Error maxime quasi quia non voluptatibus error.","rego":"Ut amet.","version":"In libero perspiciatis voluptatum ut soluta."}]}},"example":{"policies":[{"data":"Accusamus enim.","dataConfig":"Recusandae est rerum corrupti quia.","group":"Optio quia et laborum.","lastUpdate":1029654258457164464,"locked":true,"policyName":"Error maxime quasi quia non voluptatibus error.","rego":"Ut amet.","version":"In libero perspiciatis voluptatum ut soluta."},{"data":"Accusamus enim.","dataConfig":"Recusandae est rerum corrupti quia.","group":"Optio quia et laborum.","lastUpdate":1029654258457164464,"locked":true,"policyName":"Error maxime quasi quia non voluptatibus error.","rego":"Ut amet.","version":"In libero perspiciatis voluptatum ut soluta."},{"data":"Accusamus enim.","dataConfig":"Recusandae est rerum corrupti quia.","group":"Optio quia et laborum.","lastUpdate":1029654258457164464,"locked":true,"policyName":"Error maxime quasi quia non voluptatibus error.","rego":"Ut amet.","version":"In libero perspiciatis voluptatum ut soluta."},{"data":"Accusamus enim.","dataConfig":"Recusandae est rerum corrupti quia.","group":"Optio quia et laborum.","lastUpdate":1029654258457164464,"locked":true,"policyName":"Error maxime quasi quia non voluptatibus error.","rego":"Ut amet.","version":"In libero perspiciatis voluptatum ut soluta."}]},"required":["policies"]},"PolicyResponseBody":{"title":"PolicyResponseBody","type":"object","properties":{"data":{"type":"string","description":"Policy static data.","example":"Ipsa ad voluptatum maxime ut."},"dataConfig":{"type":"string","description":"Policy static data optional configuration.","example":"Aut asperiores."},"group":{"type":"string","description":"Policy group.","example":"Veritatis quam qui nostrum eaque."},"lastUpdate":{"type":"integer","description":"Last update (Unix timestamp).","example":1131015782715696616,"format":"int64"},"locked":{"type":"boolean","description":"Locked specifies if the policy is locked or allowed to execute.","example":false},"policyName":{"type":"string","description":"Policy name.","example":"Maiores et minus."},"rego":{"type":"string","description":"Policy rego source code.","example":"Delectus rerum molestiae possimus cum laboriosam."},"version":{"type":"string","description":"Policy version.","example":"Et dolores."}},"example":{"data":"Similique architecto.","dataConfig":"Sunt ut est ut molestias.","group":"Error minus vel voluptate quasi.","lastUpdate":2308837710267791288,"locked":true,"policyName":"Omnis molestiae tempora sed repellendus.","rego":"Vel sunt dolorem ea architecto iure.","version":"Debitis consectetur."},"required":["group","policyName","version","locked","lastUpdate"]},"PolicyWebhooksRequestBody":{"title":"PolicyWebhooksRequestBody","type":"object","properties":{"subscriber":{"type":"string","description":"Name of the subscriber for policy.","example":"Dolorum suscipit quae."},"webhook_url":{"type":"string","description":"Subscriber webhook url.","example":"Dolore laborum aperiam aut."}},"example":{"subscriber":"Accusamus et voluptatibus cupiditate ea.","webhook_url":"Et unde rerum dolore."},"required":["webhook_url","subscriber"]}}} \ No newline at end of file diff --git a/gen/http/openapi.yaml b/gen/http/openapi.yaml index 6e529672c8c09484fbb8eb1b22fdb475f84e7b54..3f9c608a1b6d489fe057feca0e33bca839ae4c4f 100644 --- a/gen/http/openapi.yaml +++ b/gen/http/openapi.yaml @@ -234,6 +234,45 @@ paths: description: OK response. schemes: - http + /policy/{group}/{policyname}/{version}/notifychange: + post: + tags: + - policy + summary: Webhooks policy + description: Gives ability to user to subscribe for policy change via webhooks + operationId: policy#Webhooks + parameters: + - name: group + in: path + description: Policy group. + required: true + type: string + - name: policyname + in: path + description: Policy name. + required: true + type: string + - name: version + in: path + description: Policy version. + required: true + type: string + - name: WebhooksRequestBody + in: body + required: true + schema: + $ref: '#/definitions/PolicyWebhooksRequestBody' + required: + - webhook_url + - subscriber + responses: + "200": + description: OK response. + schema: + type: string + format: binary + schemes: + - http /readiness: get: tags: @@ -293,64 +332,64 @@ definitions: $ref: '#/definitions/PolicyResponseBody' description: JSON array of policies. example: - - data: Commodi nemo fugiat id praesentium accusantium expedita. - dataConfig: Qui non quia. - group: Sequi adipisci et nulla. - lastUpdate: 8181859392515170659 - locked: false - policyName: Consequatur accusamus. - rego: Sunt in et quia cum. - version: In quis nesciunt autem et. - - data: Commodi nemo fugiat id praesentium accusantium expedita. - dataConfig: Qui non quia. - group: Sequi adipisci et nulla. - lastUpdate: 8181859392515170659 - locked: false - policyName: Consequatur accusamus. - rego: Sunt in et quia cum. - version: In quis nesciunt autem et. - - data: Commodi nemo fugiat id praesentium accusantium expedita. - dataConfig: Qui non quia. - group: Sequi adipisci et nulla. - lastUpdate: 8181859392515170659 - locked: false - policyName: Consequatur accusamus. - rego: Sunt in et quia cum. - version: In quis nesciunt autem et. + - data: Accusamus enim. + dataConfig: Recusandae est rerum corrupti quia. + group: Optio quia et laborum. + lastUpdate: 1029654258457164464 + locked: true + policyName: Error maxime quasi quia non voluptatibus error. + rego: Ut amet. + version: In libero perspiciatis voluptatum ut soluta. + - data: Accusamus enim. + dataConfig: Recusandae est rerum corrupti quia. + group: Optio quia et laborum. + lastUpdate: 1029654258457164464 + locked: true + policyName: Error maxime quasi quia non voluptatibus error. + rego: Ut amet. + version: In libero perspiciatis voluptatum ut soluta. + - data: Accusamus enim. + dataConfig: Recusandae est rerum corrupti quia. + group: Optio quia et laborum. + lastUpdate: 1029654258457164464 + locked: true + policyName: Error maxime quasi quia non voluptatibus error. + rego: Ut amet. + version: In libero perspiciatis voluptatum ut soluta. example: policies: - - data: Commodi nemo fugiat id praesentium accusantium expedita. - dataConfig: Qui non quia. - group: Sequi adipisci et nulla. - lastUpdate: 8181859392515170659 - locked: false - policyName: Consequatur accusamus. - rego: Sunt in et quia cum. - version: In quis nesciunt autem et. - - data: Commodi nemo fugiat id praesentium accusantium expedita. - dataConfig: Qui non quia. - group: Sequi adipisci et nulla. - lastUpdate: 8181859392515170659 - locked: false - policyName: Consequatur accusamus. - rego: Sunt in et quia cum. - version: In quis nesciunt autem et. - - data: Commodi nemo fugiat id praesentium accusantium expedita. - dataConfig: Qui non quia. - group: Sequi adipisci et nulla. - lastUpdate: 8181859392515170659 - locked: false - policyName: Consequatur accusamus. - rego: Sunt in et quia cum. - version: In quis nesciunt autem et. - - data: Commodi nemo fugiat id praesentium accusantium expedita. - dataConfig: Qui non quia. - group: Sequi adipisci et nulla. - lastUpdate: 8181859392515170659 - locked: false - policyName: Consequatur accusamus. - rego: Sunt in et quia cum. - version: In quis nesciunt autem et. + - data: Accusamus enim. + dataConfig: Recusandae est rerum corrupti quia. + group: Optio quia et laborum. + lastUpdate: 1029654258457164464 + locked: true + policyName: Error maxime quasi quia non voluptatibus error. + rego: Ut amet. + version: In libero perspiciatis voluptatum ut soluta. + - data: Accusamus enim. + dataConfig: Recusandae est rerum corrupti quia. + group: Optio quia et laborum. + lastUpdate: 1029654258457164464 + locked: true + policyName: Error maxime quasi quia non voluptatibus error. + rego: Ut amet. + version: In libero perspiciatis voluptatum ut soluta. + - data: Accusamus enim. + dataConfig: Recusandae est rerum corrupti quia. + group: Optio quia et laborum. + lastUpdate: 1029654258457164464 + locked: true + policyName: Error maxime quasi quia non voluptatibus error. + rego: Ut amet. + version: In libero perspiciatis voluptatum ut soluta. + - data: Accusamus enim. + dataConfig: Recusandae est rerum corrupti quia. + group: Optio quia et laborum. + lastUpdate: 1029654258457164464 + locked: true + policyName: Error maxime quasi quia non voluptatibus error. + rego: Ut amet. + version: In libero perspiciatis voluptatum ut soluta. required: - policies PolicyResponseBody: @@ -360,48 +399,66 @@ definitions: data: type: string description: Policy static data. - example: Accusamus enim. + example: Ipsa ad voluptatum maxime ut. dataConfig: type: string description: Policy static data optional configuration. - example: Recusandae est rerum corrupti quia. + example: Aut asperiores. group: type: string description: Policy group. - example: Optio quia et laborum. + example: Veritatis quam qui nostrum eaque. lastUpdate: type: integer description: Last update (Unix timestamp). - example: 1029654258457164464 + example: 1131015782715696616 format: int64 locked: type: boolean description: Locked specifies if the policy is locked or allowed to execute. - example: true + example: false policyName: type: string description: Policy name. - example: Quia non voluptatibus error. + example: Maiores et minus. rego: type: string description: Policy rego source code. - example: Ut amet. + example: Delectus rerum molestiae possimus cum laboriosam. version: type: string description: Policy version. - example: In libero perspiciatis voluptatum ut soluta. + example: Et dolores. example: - data: Totam officia necessitatibus tempore nulla animi. - dataConfig: Consequatur vel rerum rem ipsam nam. - group: Adipisci inventore ipsum voluptatibus recusandae. - lastUpdate: 1724369781608544610 + data: Similique architecto. + dataConfig: Sunt ut est ut molestias. + group: Error minus vel voluptate quasi. + lastUpdate: 2308837710267791288 locked: true - policyName: Architecto itaque voluptatum voluptas ad. - rego: Ab perspiciatis voluptatem pariatur corporis est rem. - version: Nisi distinctio vitae. + policyName: Omnis molestiae tempora sed repellendus. + rego: Vel sunt dolorem ea architecto iure. + version: Debitis consectetur. required: - group - policyName - version - locked - lastUpdate + PolicyWebhooksRequestBody: + title: PolicyWebhooksRequestBody + type: object + properties: + subscriber: + type: string + description: Name of the subscriber for policy. + example: Dolorum suscipit quae. + webhook_url: + type: string + description: Subscriber webhook url. + example: Dolore laborum aperiam aut. + example: + subscriber: Accusamus et voluptatibus cupiditate ea. + webhook_url: Et unde rerum dolore. + required: + - webhook_url + - subscriber diff --git a/gen/http/openapi3.json b/gen/http/openapi3.json index dc818a939caf50b3aac951cb4a916c3a9a07581f..dce151929456b7701c7b8f384d1f2591995077c2 100644 --- a/gen/http/openapi3.json +++ b/gen/http/openapi3.json @@ -1 +1 @@ -{"openapi":"3.0.3","info":{"title":"Policy Service","description":"The policy service exposes HTTP API for executing policies.","version":"1.0"},"servers":[{"url":"http://localhost:8081","description":"Policy Server"}],"paths":{"/liveness":{"get":{"tags":["health"],"summary":"Liveness health","operationId":"health#Liveness","responses":{"200":{"description":"OK response."}}}},"/policy/{group}/{policyName}/{version}/evaluation":{"get":{"tags":["policy"],"summary":"Evaluate policy","description":"Evaluate executes a policy with the given 'data' as input.","operationId":"policy#Evaluate#1","parameters":[{"name":"group","in":"path","description":"Policy group.","required":true,"schema":{"type":"string","description":"Policy group.","example":"example"},"example":"example"},{"name":"policyName","in":"path","description":"Policy name.","required":true,"schema":{"type":"string","description":"Policy name.","example":"example"},"example":"example"},{"name":"version","in":"path","description":"Policy version.","required":true,"schema":{"type":"string","description":"Policy version.","example":"1.0"},"example":"1.0"},{"name":"x-evaluation-id","in":"header","description":"EvaluationID allows overwriting the randomly generated evaluationID","allowEmptyValue":true,"schema":{"type":"string","description":"EvaluationID allows overwriting the randomly generated evaluationID","example":"did:web:example.com"},"example":"did:web:example.com"},{"name":"x-cache-ttl","in":"header","description":"Policy result cache TTL in seconds","allowEmptyValue":true,"schema":{"type":"integer","description":"Policy result cache TTL in seconds","example":60,"format":"int64"},"example":60}],"requestBody":{"description":"Input data passed to the policy execution runtime.","required":true,"content":{"application/json":{"schema":{"type":"string","description":"Input data passed to the policy execution runtime.","example":"Aperiam dolores reiciendis ut voluptate amet.","format":"binary"},"example":"Et quis nisi vitae iure."}}},"responses":{"200":{"description":"OK response.","headers":{"ETag":{"description":"ETag contains unique identifier of the policy evaluation and can be used to later retrieve the results from Cache.","required":true,"schema":{"type":"string","description":"ETag contains unique identifier of the policy evaluation and can be used to later retrieve the results from Cache.","example":"Sed sit."},"example":"Et eaque."}},"content":{"application/json":{"schema":{"type":"string","description":"Arbitrary JSON response.","example":"Aut et.","format":"binary"},"example":"Et mollitia."}}}}},"post":{"tags":["policy"],"summary":"Evaluate policy","description":"Evaluate executes a policy with the given 'data' as input.","operationId":"policy#Evaluate#2","parameters":[{"name":"group","in":"path","description":"Policy group.","required":true,"schema":{"type":"string","description":"Policy group.","example":"example"},"example":"example"},{"name":"policyName","in":"path","description":"Policy name.","required":true,"schema":{"type":"string","description":"Policy name.","example":"example"},"example":"example"},{"name":"version","in":"path","description":"Policy version.","required":true,"schema":{"type":"string","description":"Policy version.","example":"1.0"},"example":"1.0"},{"name":"x-evaluation-id","in":"header","description":"EvaluationID allows overwriting the randomly generated evaluationID","allowEmptyValue":true,"schema":{"type":"string","description":"EvaluationID allows overwriting the randomly generated evaluationID","example":"did:web:example.com"},"example":"did:web:example.com"},{"name":"x-cache-ttl","in":"header","description":"Policy result cache TTL in seconds","allowEmptyValue":true,"schema":{"type":"integer","description":"Policy result cache TTL in seconds","example":60,"format":"int64"},"example":60}],"requestBody":{"description":"Input data passed to the policy execution runtime.","required":true,"content":{"application/json":{"schema":{"type":"string","description":"Input data passed to the policy execution runtime.","example":"Aperiam dolores reiciendis ut voluptate amet.","format":"binary"},"example":"Non quo ut molestias rerum sunt."}}},"responses":{"200":{"description":"OK response.","headers":{"ETag":{"description":"ETag contains unique identifier of the policy evaluation and can be used to later retrieve the results from Cache.","required":true,"schema":{"type":"string","description":"ETag contains unique identifier of the policy evaluation and can be used to later retrieve the results from Cache.","example":"Omnis dolores totam voluptatem rerum."},"example":"Est impedit."}},"content":{"application/json":{"schema":{"type":"string","description":"Arbitrary JSON response.","example":"Aut et.","format":"binary"},"example":"Consequatur ut suscipit."}}}}}},"/policy/{group}/{policyName}/{version}/evaluation/did.json":{"get":{"tags":["policy"],"summary":"Evaluate policy","description":"Evaluate executes a policy with the given 'data' as input.","operationId":"policy#Evaluate","parameters":[{"name":"group","in":"path","description":"Policy group.","required":true,"schema":{"type":"string","description":"Policy group.","example":"example"},"example":"example"},{"name":"policyName","in":"path","description":"Policy name.","required":true,"schema":{"type":"string","description":"Policy name.","example":"example"},"example":"example"},{"name":"version","in":"path","description":"Policy version.","required":true,"schema":{"type":"string","description":"Policy version.","example":"1.0"},"example":"1.0"},{"name":"x-evaluation-id","in":"header","description":"EvaluationID allows overwriting the randomly generated evaluationID","allowEmptyValue":true,"schema":{"type":"string","description":"EvaluationID allows overwriting the randomly generated evaluationID","example":"did:web:example.com"},"example":"did:web:example.com"},{"name":"x-cache-ttl","in":"header","description":"Policy result cache TTL in seconds","allowEmptyValue":true,"schema":{"type":"integer","description":"Policy result cache TTL in seconds","example":60,"format":"int64"},"example":60}],"requestBody":{"description":"Input data passed to the policy execution runtime.","required":true,"content":{"application/json":{"schema":{"type":"string","description":"Input data passed to the policy execution runtime.","example":"Aperiam dolores reiciendis ut voluptate amet.","format":"binary"},"example":"Dolore laborum aperiam aut."}}},"responses":{"200":{"description":"OK response.","headers":{"ETag":{"description":"ETag contains unique identifier of the policy evaluation and can be used to later retrieve the results from Cache.","required":true,"schema":{"type":"string","description":"ETag contains unique identifier of the policy evaluation and can be used to later retrieve the results from Cache.","example":"Dolorum suscipit quae."},"example":"Accusamus et voluptatibus cupiditate ea."}},"content":{"application/json":{"schema":{"type":"string","description":"Arbitrary JSON response.","example":"Aut et.","format":"binary"},"example":"Inventore ut doloremque recusandae."}}}}}},"/policy/{group}/{policyName}/{version}/lock":{"delete":{"tags":["policy"],"summary":"Unlock policy","description":"Unlock a policy so it can be evaluated again.","operationId":"policy#Unlock","parameters":[{"name":"group","in":"path","description":"Policy group.","required":true,"schema":{"type":"string","description":"Policy group.","example":"Explicabo expedita ipsum minus ipsam at vel."},"example":"Nisi et praesentium ut reiciendis."},{"name":"policyName","in":"path","description":"Policy name.","required":true,"schema":{"type":"string","description":"Policy name.","example":"Dolorum cupiditate provident."},"example":"Dolor dolorem modi aut officiis veritatis impedit."},{"name":"version","in":"path","description":"Policy version.","required":true,"schema":{"type":"string","description":"Policy version.","example":"Recusandae eligendi."},"example":"Id quibusdam quia deserunt officiis."}],"responses":{"200":{"description":"OK response."}}},"post":{"tags":["policy"],"summary":"Lock policy","description":"Lock a policy so that it cannot be evaluated.","operationId":"policy#Lock","parameters":[{"name":"group","in":"path","description":"Policy group.","required":true,"schema":{"type":"string","description":"Policy group.","example":"Neque et sed modi accusantium."},"example":"Rerum asperiores nulla."},{"name":"policyName","in":"path","description":"Policy name.","required":true,"schema":{"type":"string","description":"Policy name.","example":"Tenetur rerum necessitatibus fugit."},"example":"Ut velit aut nobis repellendus."},{"name":"version","in":"path","description":"Policy version.","required":true,"schema":{"type":"string","description":"Policy version.","example":"Rem et occaecati quam."},"example":"Laborum harum voluptate et ut similique doloremque."}],"responses":{"200":{"description":"OK response."}}}},"/readiness":{"get":{"tags":["health"],"summary":"Readiness health","operationId":"health#Readiness","responses":{"200":{"description":"OK response."}}}},"/v1/policies":{"get":{"tags":["policy"],"summary":"ListPolicies policy","description":"List policies from storage with optional filters.","operationId":"policy#ListPolicies","parameters":[{"name":"locked","in":"query","description":"Filter to return locked/unlocked policies (optional).","allowEmptyValue":true,"schema":{"type":"boolean","description":"Filter to return locked/unlocked policies (optional).","example":false},"example":true},{"name":"rego","in":"query","description":"Include policy source code in results (optional).","allowEmptyValue":true,"schema":{"type":"boolean","description":"Include policy source code in results (optional).","example":false},"example":true},{"name":"data","in":"query","description":"Include policy static data in results (optional). ","allowEmptyValue":true,"schema":{"type":"boolean","description":"Include policy static data in results (optional). ","example":false},"example":false},{"name":"dataConfig","in":"query","description":"Include static data config (optional).","allowEmptyValue":true,"schema":{"type":"boolean","description":"Include static data config (optional).","example":false},"example":true}],"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PoliciesResult"},"example":{"policies":[{"data":"Commodi nemo fugiat id praesentium accusantium expedita.","dataConfig":"Qui non quia.","group":"Sequi adipisci et nulla.","lastUpdate":8181859392515170659,"locked":false,"policyName":"Consequatur accusamus.","rego":"Sunt in et quia cum.","version":"In quis nesciunt autem et."},{"data":"Commodi nemo fugiat id praesentium accusantium expedita.","dataConfig":"Qui non quia.","group":"Sequi adipisci et nulla.","lastUpdate":8181859392515170659,"locked":false,"policyName":"Consequatur accusamus.","rego":"Sunt in et quia cum.","version":"In quis nesciunt autem et."},{"data":"Commodi nemo fugiat id praesentium accusantium expedita.","dataConfig":"Qui non quia.","group":"Sequi adipisci et nulla.","lastUpdate":8181859392515170659,"locked":false,"policyName":"Consequatur accusamus.","rego":"Sunt in et quia cum.","version":"In quis nesciunt autem et."},{"data":"Commodi nemo fugiat id praesentium accusantium expedita.","dataConfig":"Qui non quia.","group":"Sequi adipisci et nulla.","lastUpdate":8181859392515170659,"locked":false,"policyName":"Consequatur accusamus.","rego":"Sunt in et quia cum.","version":"In quis nesciunt autem et."}]}}}}}}}},"components":{"schemas":{"PoliciesResult":{"type":"object","properties":{"policies":{"type":"array","items":{"$ref":"#/components/schemas/Policy"},"description":"JSON array of policies.","example":[{"data":"Commodi nemo fugiat id praesentium accusantium expedita.","dataConfig":"Qui non quia.","group":"Sequi adipisci et nulla.","lastUpdate":8181859392515170659,"locked":false,"policyName":"Consequatur accusamus.","rego":"Sunt in et quia cum.","version":"In quis nesciunt autem et."},{"data":"Commodi nemo fugiat id praesentium accusantium expedita.","dataConfig":"Qui non quia.","group":"Sequi adipisci et nulla.","lastUpdate":8181859392515170659,"locked":false,"policyName":"Consequatur accusamus.","rego":"Sunt in et quia cum.","version":"In quis nesciunt autem et."},{"data":"Commodi nemo fugiat id praesentium accusantium expedita.","dataConfig":"Qui non quia.","group":"Sequi adipisci et nulla.","lastUpdate":8181859392515170659,"locked":false,"policyName":"Consequatur accusamus.","rego":"Sunt in et quia cum.","version":"In quis nesciunt autem et."}]}},"example":{"policies":[{"data":"Commodi nemo fugiat id praesentium accusantium expedita.","dataConfig":"Qui non quia.","group":"Sequi adipisci et nulla.","lastUpdate":8181859392515170659,"locked":false,"policyName":"Consequatur accusamus.","rego":"Sunt in et quia cum.","version":"In quis nesciunt autem et."},{"data":"Commodi nemo fugiat id praesentium accusantium expedita.","dataConfig":"Qui non quia.","group":"Sequi adipisci et nulla.","lastUpdate":8181859392515170659,"locked":false,"policyName":"Consequatur accusamus.","rego":"Sunt in et quia cum.","version":"In quis nesciunt autem et."},{"data":"Commodi nemo fugiat id praesentium accusantium expedita.","dataConfig":"Qui non quia.","group":"Sequi adipisci et nulla.","lastUpdate":8181859392515170659,"locked":false,"policyName":"Consequatur accusamus.","rego":"Sunt in et quia cum.","version":"In quis nesciunt autem et."},{"data":"Commodi nemo fugiat id praesentium accusantium expedita.","dataConfig":"Qui non quia.","group":"Sequi adipisci et nulla.","lastUpdate":8181859392515170659,"locked":false,"policyName":"Consequatur accusamus.","rego":"Sunt in et quia cum.","version":"In quis nesciunt autem et."}]},"required":["policies"]},"Policy":{"type":"object","properties":{"data":{"type":"string","description":"Policy static data.","example":"Ipsa ad voluptatum maxime ut."},"dataConfig":{"type":"string","description":"Policy static data optional configuration.","example":"Aut asperiores."},"group":{"type":"string","description":"Policy group.","example":"Veritatis quam qui nostrum eaque."},"lastUpdate":{"type":"integer","description":"Last update (Unix timestamp).","example":1131015782715696616,"format":"int64"},"locked":{"type":"boolean","description":"Locked specifies if the policy is locked or allowed to execute.","example":false},"policyName":{"type":"string","description":"Policy name.","example":"Maiores et minus."},"rego":{"type":"string","description":"Policy rego source code.","example":"Delectus rerum molestiae possimus cum laboriosam."},"version":{"type":"string","description":"Policy version.","example":"Et dolores."}},"example":{"data":"Similique architecto.","dataConfig":"Sunt ut est ut molestias.","group":"Error minus vel voluptate quasi.","lastUpdate":2308837710267791288,"locked":true,"policyName":"Omnis molestiae tempora sed repellendus.","rego":"Vel sunt dolorem ea architecto iure.","version":"Debitis consectetur."},"required":["group","policyName","version","locked","lastUpdate"]}}},"tags":[{"name":"health","description":"Health service provides health check endpoints."},{"name":"policy","description":"Policy Service provides evaluation of policies through Open Policy Agent."}]} \ No newline at end of file +{"openapi":"3.0.3","info":{"title":"Policy Service","description":"The policy service exposes HTTP API for executing policies.","version":"1.0"},"servers":[{"url":"http://localhost:8081","description":"Policy Server"}],"paths":{"/liveness":{"get":{"tags":["health"],"summary":"Liveness health","operationId":"health#Liveness","responses":{"200":{"description":"OK response."}}}},"/policy/{group}/{policyName}/{version}/evaluation":{"get":{"tags":["policy"],"summary":"Evaluate policy","description":"Evaluate executes a policy with the given 'data' as input.","operationId":"policy#Evaluate#1","parameters":[{"name":"group","in":"path","description":"Policy group.","required":true,"schema":{"type":"string","description":"Policy group.","example":"example"},"example":"example"},{"name":"policyName","in":"path","description":"Policy name.","required":true,"schema":{"type":"string","description":"Policy name.","example":"example"},"example":"example"},{"name":"version","in":"path","description":"Policy version.","required":true,"schema":{"type":"string","description":"Policy version.","example":"1.0"},"example":"1.0"},{"name":"x-evaluation-id","in":"header","description":"EvaluationID allows overwriting the randomly generated evaluationID","allowEmptyValue":true,"schema":{"type":"string","description":"EvaluationID allows overwriting the randomly generated evaluationID","example":"did:web:example.com"},"example":"did:web:example.com"},{"name":"x-cache-ttl","in":"header","description":"Policy result cache TTL in seconds","allowEmptyValue":true,"schema":{"type":"integer","description":"Policy result cache TTL in seconds","example":60,"format":"int64"},"example":60}],"requestBody":{"description":"Input data passed to the policy execution runtime.","required":true,"content":{"application/json":{"schema":{"type":"string","description":"Input data passed to the policy execution runtime.","example":"Inventore ut doloremque recusandae.","format":"binary"},"example":"Aut accusantium in."}}},"responses":{"200":{"description":"OK response.","headers":{"ETag":{"description":"ETag contains unique identifier of the policy evaluation and can be used to later retrieve the results from Cache.","required":true,"schema":{"type":"string","description":"ETag contains unique identifier of the policy evaluation and can be used to later retrieve the results from Cache.","example":"Culpa deserunt voluptatem culpa."},"example":"Cupiditate qui quo."}},"content":{"application/json":{"schema":{"type":"string","description":"Arbitrary JSON response.","example":"Et quis nisi vitae iure.","format":"binary"},"example":"Dignissimos enim."}}}}},"post":{"tags":["policy"],"summary":"Evaluate policy","description":"Evaluate executes a policy with the given 'data' as input.","operationId":"policy#Evaluate#2","parameters":[{"name":"group","in":"path","description":"Policy group.","required":true,"schema":{"type":"string","description":"Policy group.","example":"example"},"example":"example"},{"name":"policyName","in":"path","description":"Policy name.","required":true,"schema":{"type":"string","description":"Policy name.","example":"example"},"example":"example"},{"name":"version","in":"path","description":"Policy version.","required":true,"schema":{"type":"string","description":"Policy version.","example":"1.0"},"example":"1.0"},{"name":"x-evaluation-id","in":"header","description":"EvaluationID allows overwriting the randomly generated evaluationID","allowEmptyValue":true,"schema":{"type":"string","description":"EvaluationID allows overwriting the randomly generated evaluationID","example":"did:web:example.com"},"example":"did:web:example.com"},{"name":"x-cache-ttl","in":"header","description":"Policy result cache TTL in seconds","allowEmptyValue":true,"schema":{"type":"integer","description":"Policy result cache TTL in seconds","example":60,"format":"int64"},"example":60}],"requestBody":{"description":"Input data passed to the policy execution runtime.","required":true,"content":{"application/json":{"schema":{"type":"string","description":"Input data passed to the policy execution runtime.","example":"Inventore ut doloremque recusandae.","format":"binary"},"example":"Error et sunt maxime aperiam."}}},"responses":{"200":{"description":"OK response.","headers":{"ETag":{"description":"ETag contains unique identifier of the policy evaluation and can be used to later retrieve the results from Cache.","required":true,"schema":{"type":"string","description":"ETag contains unique identifier of the policy evaluation and can be used to later retrieve the results from Cache.","example":"Et sit qui fugit enim labore."},"example":"Molestiae fugiat harum quia corporis ullam natus."}},"content":{"application/json":{"schema":{"type":"string","description":"Arbitrary JSON response.","example":"Et quis nisi vitae iure.","format":"binary"},"example":"Animi omnis minima fuga numquam."}}}}}},"/policy/{group}/{policyName}/{version}/evaluation/did.json":{"get":{"tags":["policy"],"summary":"Evaluate policy","description":"Evaluate executes a policy with the given 'data' as input.","operationId":"policy#Evaluate","parameters":[{"name":"group","in":"path","description":"Policy group.","required":true,"schema":{"type":"string","description":"Policy group.","example":"example"},"example":"example"},{"name":"policyName","in":"path","description":"Policy name.","required":true,"schema":{"type":"string","description":"Policy name.","example":"example"},"example":"example"},{"name":"version","in":"path","description":"Policy version.","required":true,"schema":{"type":"string","description":"Policy version.","example":"1.0"},"example":"1.0"},{"name":"x-evaluation-id","in":"header","description":"EvaluationID allows overwriting the randomly generated evaluationID","allowEmptyValue":true,"schema":{"type":"string","description":"EvaluationID allows overwriting the randomly generated evaluationID","example":"did:web:example.com"},"example":"did:web:example.com"},{"name":"x-cache-ttl","in":"header","description":"Policy result cache TTL in seconds","allowEmptyValue":true,"schema":{"type":"integer","description":"Policy result cache TTL in seconds","example":60,"format":"int64"},"example":60}],"requestBody":{"description":"Input data passed to the policy execution runtime.","required":true,"content":{"application/json":{"schema":{"type":"string","description":"Input data passed to the policy execution runtime.","example":"Inventore ut doloremque recusandae.","format":"binary"},"example":"Laborum dolor dolorem modi aut."}}},"responses":{"200":{"description":"OK response.","headers":{"ETag":{"description":"ETag contains unique identifier of the policy evaluation and can be used to later retrieve the results from Cache.","required":true,"schema":{"type":"string","description":"ETag contains unique identifier of the policy evaluation and can be used to later retrieve the results from Cache.","example":"Veritatis impedit rerum recusandae eligendi in."},"example":"Sapiente unde doloremque quae ullam qui optio."}},"content":{"application/json":{"schema":{"type":"string","description":"Arbitrary JSON response.","example":"Et quis nisi vitae iure.","format":"binary"},"example":"Iure rerum non cumque sapiente laborum voluptas."}}}}}},"/policy/{group}/{policyName}/{version}/lock":{"delete":{"tags":["policy"],"summary":"Unlock policy","description":"Unlock a policy so it can be evaluated again.","operationId":"policy#Unlock","parameters":[{"name":"group","in":"path","description":"Policy group.","required":true,"schema":{"type":"string","description":"Policy group.","example":"Consequatur aut ipsam."},"example":"Aut provident ducimus vero adipisci nemo."},{"name":"policyName","in":"path","description":"Policy name.","required":true,"schema":{"type":"string","description":"Policy name.","example":"Itaque laborum."},"example":"Quos saepe dolorum qui tenetur aut."},{"name":"version","in":"path","description":"Policy version.","required":true,"schema":{"type":"string","description":"Policy version.","example":"Iusto mollitia rerum quis ut et."},"example":"Ipsam est alias officiis."}],"responses":{"200":{"description":"OK response."}}},"post":{"tags":["policy"],"summary":"Lock policy","description":"Lock a policy so that it cannot be evaluated.","operationId":"policy#Lock","parameters":[{"name":"group","in":"path","description":"Policy group.","required":true,"schema":{"type":"string","description":"Policy group.","example":"Ipsum explicabo assumenda delectus."},"example":"Eius sed."},{"name":"policyName","in":"path","description":"Policy name.","required":true,"schema":{"type":"string","description":"Policy name.","example":"Rerum saepe dolores laborum odio."},"example":"Eos nemo repudiandae."},{"name":"version","in":"path","description":"Policy version.","required":true,"schema":{"type":"string","description":"Policy version.","example":"Eveniet voluptas rerum."},"example":"Facilis tempora dolor consectetur."}],"responses":{"200":{"description":"OK response."}}}},"/policy/{group}/{policyname}/{version}/notifychange":{"post":{"tags":["policy"],"summary":"Webhooks policy","description":"Gives ability to user to subscribe for policy change via webhooks","operationId":"policy#Webhooks","parameters":[{"name":"group","in":"path","description":"Policy group.","required":true,"schema":{"type":"string","description":"Policy group.","example":"Aut quas eos qui minima."},"example":"Est non."},{"name":"policyname","in":"path","description":"Policy name.","required":true,"schema":{"type":"string","description":"Policy name.","example":"Minima aut in quis et qui."},"example":"Deleniti natus eos cumque asperiores."},{"name":"version","in":"path","description":"Policy version.","required":true,"schema":{"type":"string","description":"Policy version.","example":"Commodi illo quidem omnis eveniet et."},"example":"Adipisci harum."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhooksRequestBody"},"example":{"subscriber":"Est totam officia necessitatibus tempore.","webhook_url":"Ad ab perspiciatis voluptatem pariatur corporis est."}}}},"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"type":"string","example":"Ut reiciendis fugit dolorum cupiditate.","format":"binary"},"example":"Ratione sit numquam non cupiditate sed omnis."}}}}}},"/readiness":{"get":{"tags":["health"],"summary":"Readiness health","operationId":"health#Readiness","responses":{"200":{"description":"OK response."}}}},"/v1/policies":{"get":{"tags":["policy"],"summary":"ListPolicies policy","description":"List policies from storage with optional filters.","operationId":"policy#ListPolicies","parameters":[{"name":"locked","in":"query","description":"Filter to return locked/unlocked policies (optional).","allowEmptyValue":true,"schema":{"type":"boolean","description":"Filter to return locked/unlocked policies (optional).","example":false},"example":false},{"name":"rego","in":"query","description":"Include policy source code in results (optional).","allowEmptyValue":true,"schema":{"type":"boolean","description":"Include policy source code in results (optional).","example":false},"example":false},{"name":"data","in":"query","description":"Include policy static data in results (optional). ","allowEmptyValue":true,"schema":{"type":"boolean","description":"Include policy static data in results (optional). ","example":true},"example":true},{"name":"dataConfig","in":"query","description":"Include static data config (optional).","allowEmptyValue":true,"schema":{"type":"boolean","description":"Include static data config (optional).","example":true},"example":true}],"responses":{"200":{"description":"OK response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PoliciesResult"},"example":{"policies":[{"data":"Accusamus enim.","dataConfig":"Recusandae est rerum corrupti quia.","group":"Optio quia et laborum.","lastUpdate":1029654258457164464,"locked":true,"policyName":"Error maxime quasi quia non voluptatibus error.","rego":"Ut amet.","version":"In libero perspiciatis voluptatum ut soluta."},{"data":"Accusamus enim.","dataConfig":"Recusandae est rerum corrupti quia.","group":"Optio quia et laborum.","lastUpdate":1029654258457164464,"locked":true,"policyName":"Error maxime quasi quia non voluptatibus error.","rego":"Ut amet.","version":"In libero perspiciatis voluptatum ut soluta."},{"data":"Accusamus enim.","dataConfig":"Recusandae est rerum corrupti quia.","group":"Optio quia et laborum.","lastUpdate":1029654258457164464,"locked":true,"policyName":"Error maxime quasi quia non voluptatibus error.","rego":"Ut amet.","version":"In libero perspiciatis voluptatum ut soluta."},{"data":"Accusamus enim.","dataConfig":"Recusandae est rerum corrupti quia.","group":"Optio quia et laborum.","lastUpdate":1029654258457164464,"locked":true,"policyName":"Error maxime quasi quia non voluptatibus error.","rego":"Ut amet.","version":"In libero perspiciatis voluptatum ut soluta."}]}}}}}}}},"components":{"schemas":{"PoliciesResult":{"type":"object","properties":{"policies":{"type":"array","items":{"$ref":"#/components/schemas/Policy"},"description":"JSON array of policies.","example":[{"data":"Accusamus enim.","dataConfig":"Recusandae est rerum corrupti quia.","group":"Optio quia et laborum.","lastUpdate":1029654258457164464,"locked":true,"policyName":"Error maxime quasi quia non voluptatibus error.","rego":"Ut amet.","version":"In libero perspiciatis voluptatum ut soluta."},{"data":"Accusamus enim.","dataConfig":"Recusandae est rerum corrupti quia.","group":"Optio quia et laborum.","lastUpdate":1029654258457164464,"locked":true,"policyName":"Error maxime quasi quia non voluptatibus error.","rego":"Ut amet.","version":"In libero perspiciatis voluptatum ut soluta."}]}},"example":{"policies":[{"data":"Accusamus enim.","dataConfig":"Recusandae est rerum corrupti quia.","group":"Optio quia et laborum.","lastUpdate":1029654258457164464,"locked":true,"policyName":"Error maxime quasi quia non voluptatibus error.","rego":"Ut amet.","version":"In libero perspiciatis voluptatum ut soluta."},{"data":"Accusamus enim.","dataConfig":"Recusandae est rerum corrupti quia.","group":"Optio quia et laborum.","lastUpdate":1029654258457164464,"locked":true,"policyName":"Error maxime quasi quia non voluptatibus error.","rego":"Ut amet.","version":"In libero perspiciatis voluptatum ut soluta."}]},"required":["policies"]},"Policy":{"type":"object","properties":{"data":{"type":"string","description":"Policy static data.","example":"Non quo ut molestias rerum sunt."},"dataConfig":{"type":"string","description":"Policy static data optional configuration.","example":"Omnis dolores totam voluptatem rerum."},"group":{"type":"string","description":"Policy group.","example":"Iusto ut."},"lastUpdate":{"type":"integer","description":"Last update (Unix timestamp).","example":3092150594834775360,"format":"int64"},"locked":{"type":"boolean","description":"Locked specifies if the policy is locked or allowed to execute.","example":false},"policyName":{"type":"string","description":"Policy name.","example":"Sed sit."},"rego":{"type":"string","description":"Policy rego source code.","example":"Et mollitia."},"version":{"type":"string","description":"Policy version.","example":"Et eaque."}},"example":{"data":"Rerum asperiores nulla.","dataConfig":"Tenetur rerum necessitatibus fugit.","group":"Est impedit.","lastUpdate":2958895584654309878,"locked":false,"policyName":"Enim omnis.","rego":"Neque et sed modi accusantium.","version":"Consequatur ut suscipit."},"required":["group","policyName","version","locked","lastUpdate"]},"WebhooksRequestBody":{"type":"object","properties":{"subscriber":{"type":"string","description":"Name of the subscriber for policy.","example":"Harum voluptate et ut similique doloremque quis."},"webhook_url":{"type":"string","description":"Subscriber webhook url.","example":"Repellendus quis rem et occaecati quam tempora."}},"example":{"subscriber":"Vel saepe nisi et.","webhook_url":"Expedita ipsum minus ipsam."},"required":["webhook_url","subscriber"]}}},"tags":[{"name":"health","description":"Health service provides health check endpoints."},{"name":"policy","description":"Policy Service provides evaluation of policies through Open Policy Agent."}]} \ No newline at end of file diff --git a/gen/http/openapi3.yaml b/gen/http/openapi3.yaml index e49a8b9a48f6b8f8eeec706997f46bcb09ae812b..2e47c1a30d9321501ff5d251f769147b509c0878 100644 --- a/gen/http/openapi3.yaml +++ b/gen/http/openapi3.yaml @@ -78,9 +78,9 @@ paths: schema: type: string description: Input data passed to the policy execution runtime. - example: Aperiam dolores reiciendis ut voluptate amet. + example: Inventore ut doloremque recusandae. format: binary - example: Et quis nisi vitae iure. + example: Aut accusantium in. responses: "200": description: OK response. @@ -91,16 +91,16 @@ paths: schema: type: string description: ETag contains unique identifier of the policy evaluation and can be used to later retrieve the results from Cache. - example: Sed sit. - example: Et eaque. + example: Culpa deserunt voluptatem culpa. + example: Cupiditate qui quo. content: application/json: schema: type: string description: Arbitrary JSON response. - example: Aut et. + example: Et quis nisi vitae iure. format: binary - example: Et mollitia. + example: Dignissimos enim. post: tags: - policy @@ -162,9 +162,9 @@ paths: schema: type: string description: Input data passed to the policy execution runtime. - example: Aperiam dolores reiciendis ut voluptate amet. + example: Inventore ut doloremque recusandae. format: binary - example: Non quo ut molestias rerum sunt. + example: Error et sunt maxime aperiam. responses: "200": description: OK response. @@ -175,16 +175,16 @@ paths: schema: type: string description: ETag contains unique identifier of the policy evaluation and can be used to later retrieve the results from Cache. - example: Omnis dolores totam voluptatem rerum. - example: Est impedit. + example: Et sit qui fugit enim labore. + example: Molestiae fugiat harum quia corporis ullam natus. content: application/json: schema: type: string description: Arbitrary JSON response. - example: Aut et. + example: Et quis nisi vitae iure. format: binary - example: Consequatur ut suscipit. + example: Animi omnis minima fuga numquam. /policy/{group}/{policyName}/{version}/evaluation/did.json: get: tags: @@ -247,9 +247,9 @@ paths: schema: type: string description: Input data passed to the policy execution runtime. - example: Aperiam dolores reiciendis ut voluptate amet. + example: Inventore ut doloremque recusandae. format: binary - example: Dolore laborum aperiam aut. + example: Laborum dolor dolorem modi aut. responses: "200": description: OK response. @@ -260,16 +260,16 @@ paths: schema: type: string description: ETag contains unique identifier of the policy evaluation and can be used to later retrieve the results from Cache. - example: Dolorum suscipit quae. - example: Accusamus et voluptatibus cupiditate ea. + example: Veritatis impedit rerum recusandae eligendi in. + example: Sapiente unde doloremque quae ullam qui optio. content: application/json: schema: type: string description: Arbitrary JSON response. - example: Aut et. + example: Et quis nisi vitae iure. format: binary - example: Inventore ut doloremque recusandae. + example: Iure rerum non cumque sapiente laborum voluptas. /policy/{group}/{policyName}/{version}/lock: delete: tags: @@ -285,8 +285,8 @@ paths: schema: type: string description: Policy group. - example: Explicabo expedita ipsum minus ipsam at vel. - example: Nisi et praesentium ut reiciendis. + example: Consequatur aut ipsam. + example: Aut provident ducimus vero adipisci nemo. - name: policyName in: path description: Policy name. @@ -294,8 +294,8 @@ paths: schema: type: string description: Policy name. - example: Dolorum cupiditate provident. - example: Dolor dolorem modi aut officiis veritatis impedit. + example: Itaque laborum. + example: Quos saepe dolorum qui tenetur aut. - name: version in: path description: Policy version. @@ -303,8 +303,8 @@ paths: schema: type: string description: Policy version. - example: Recusandae eligendi. - example: Id quibusdam quia deserunt officiis. + example: Iusto mollitia rerum quis ut et. + example: Ipsam est alias officiis. responses: "200": description: OK response. @@ -322,8 +322,8 @@ paths: schema: type: string description: Policy group. - example: Neque et sed modi accusantium. - example: Rerum asperiores nulla. + example: Ipsum explicabo assumenda delectus. + example: Eius sed. - name: policyName in: path description: Policy name. @@ -331,8 +331,8 @@ paths: schema: type: string description: Policy name. - example: Tenetur rerum necessitatibus fugit. - example: Ut velit aut nobis repellendus. + example: Rerum saepe dolores laborum odio. + example: Eos nemo repudiandae. - name: version in: path description: Policy version. @@ -340,11 +340,65 @@ paths: schema: type: string description: Policy version. - example: Rem et occaecati quam. - example: Laborum harum voluptate et ut similique doloremque. + example: Eveniet voluptas rerum. + example: Facilis tempora dolor consectetur. responses: "200": description: OK response. + /policy/{group}/{policyname}/{version}/notifychange: + post: + tags: + - policy + summary: Webhooks policy + description: Gives ability to user to subscribe for policy change via webhooks + operationId: policy#Webhooks + parameters: + - name: group + in: path + description: Policy group. + required: true + schema: + type: string + description: Policy group. + example: Aut quas eos qui minima. + example: Est non. + - name: policyname + in: path + description: Policy name. + required: true + schema: + type: string + description: Policy name. + example: Minima aut in quis et qui. + example: Deleniti natus eos cumque asperiores. + - name: version + in: path + description: Policy version. + required: true + schema: + type: string + description: Policy version. + example: Commodi illo quidem omnis eveniet et. + example: Adipisci harum. + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/WebhooksRequestBody' + example: + subscriber: Est totam officia necessitatibus tempore. + webhook_url: Ad ab perspiciatis voluptatem pariatur corporis est. + responses: + "200": + description: OK response. + content: + application/json: + schema: + type: string + example: Ut reiciendis fugit dolorum cupiditate. + format: binary + example: Ratione sit numquam non cupiditate sed omnis. /readiness: get: tags: @@ -370,7 +424,7 @@ paths: type: boolean description: Filter to return locked/unlocked policies (optional). example: false - example: true + example: false - name: rego in: query description: Include policy source code in results (optional). @@ -379,7 +433,7 @@ paths: type: boolean description: Include policy source code in results (optional). example: false - example: true + example: false - name: data in: query description: 'Include policy static data in results (optional). ' @@ -387,8 +441,8 @@ paths: schema: type: boolean description: 'Include policy static data in results (optional). ' - example: false - example: false + example: true + example: true - name: dataConfig in: query description: Include static data config (optional). @@ -396,7 +450,7 @@ paths: schema: type: boolean description: Include static data config (optional). - example: false + example: true example: true responses: "200": @@ -407,38 +461,38 @@ paths: $ref: '#/components/schemas/PoliciesResult' example: policies: - - data: Commodi nemo fugiat id praesentium accusantium expedita. - dataConfig: Qui non quia. - group: Sequi adipisci et nulla. - lastUpdate: 8181859392515170659 - locked: false - policyName: Consequatur accusamus. - rego: Sunt in et quia cum. - version: In quis nesciunt autem et. - - data: Commodi nemo fugiat id praesentium accusantium expedita. - dataConfig: Qui non quia. - group: Sequi adipisci et nulla. - lastUpdate: 8181859392515170659 - locked: false - policyName: Consequatur accusamus. - rego: Sunt in et quia cum. - version: In quis nesciunt autem et. - - data: Commodi nemo fugiat id praesentium accusantium expedita. - dataConfig: Qui non quia. - group: Sequi adipisci et nulla. - lastUpdate: 8181859392515170659 - locked: false - policyName: Consequatur accusamus. - rego: Sunt in et quia cum. - version: In quis nesciunt autem et. - - data: Commodi nemo fugiat id praesentium accusantium expedita. - dataConfig: Qui non quia. - group: Sequi adipisci et nulla. - lastUpdate: 8181859392515170659 - locked: false - policyName: Consequatur accusamus. - rego: Sunt in et quia cum. - version: In quis nesciunt autem et. + - data: Accusamus enim. + dataConfig: Recusandae est rerum corrupti quia. + group: Optio quia et laborum. + lastUpdate: 1029654258457164464 + locked: true + policyName: Error maxime quasi quia non voluptatibus error. + rego: Ut amet. + version: In libero perspiciatis voluptatum ut soluta. + - data: Accusamus enim. + dataConfig: Recusandae est rerum corrupti quia. + group: Optio quia et laborum. + lastUpdate: 1029654258457164464 + locked: true + policyName: Error maxime quasi quia non voluptatibus error. + rego: Ut amet. + version: In libero perspiciatis voluptatum ut soluta. + - data: Accusamus enim. + dataConfig: Recusandae est rerum corrupti quia. + group: Optio quia et laborum. + lastUpdate: 1029654258457164464 + locked: true + policyName: Error maxime quasi quia non voluptatibus error. + rego: Ut amet. + version: In libero perspiciatis voluptatum ut soluta. + - data: Accusamus enim. + dataConfig: Recusandae est rerum corrupti quia. + group: Optio quia et laborum. + lastUpdate: 1029654258457164464 + locked: true + policyName: Error maxime quasi quia non voluptatibus error. + rego: Ut amet. + version: In libero perspiciatis voluptatum ut soluta. components: schemas: PoliciesResult: @@ -450,64 +504,40 @@ components: $ref: '#/components/schemas/Policy' description: JSON array of policies. example: - - data: Commodi nemo fugiat id praesentium accusantium expedita. - dataConfig: Qui non quia. - group: Sequi adipisci et nulla. - lastUpdate: 8181859392515170659 - locked: false - policyName: Consequatur accusamus. - rego: Sunt in et quia cum. - version: In quis nesciunt autem et. - - data: Commodi nemo fugiat id praesentium accusantium expedita. - dataConfig: Qui non quia. - group: Sequi adipisci et nulla. - lastUpdate: 8181859392515170659 - locked: false - policyName: Consequatur accusamus. - rego: Sunt in et quia cum. - version: In quis nesciunt autem et. - - data: Commodi nemo fugiat id praesentium accusantium expedita. - dataConfig: Qui non quia. - group: Sequi adipisci et nulla. - lastUpdate: 8181859392515170659 - locked: false - policyName: Consequatur accusamus. - rego: Sunt in et quia cum. - version: In quis nesciunt autem et. + - data: Accusamus enim. + dataConfig: Recusandae est rerum corrupti quia. + group: Optio quia et laborum. + lastUpdate: 1029654258457164464 + locked: true + policyName: Error maxime quasi quia non voluptatibus error. + rego: Ut amet. + version: In libero perspiciatis voluptatum ut soluta. + - data: Accusamus enim. + dataConfig: Recusandae est rerum corrupti quia. + group: Optio quia et laborum. + lastUpdate: 1029654258457164464 + locked: true + policyName: Error maxime quasi quia non voluptatibus error. + rego: Ut amet. + version: In libero perspiciatis voluptatum ut soluta. example: policies: - - data: Commodi nemo fugiat id praesentium accusantium expedita. - dataConfig: Qui non quia. - group: Sequi adipisci et nulla. - lastUpdate: 8181859392515170659 - locked: false - policyName: Consequatur accusamus. - rego: Sunt in et quia cum. - version: In quis nesciunt autem et. - - data: Commodi nemo fugiat id praesentium accusantium expedita. - dataConfig: Qui non quia. - group: Sequi adipisci et nulla. - lastUpdate: 8181859392515170659 - locked: false - policyName: Consequatur accusamus. - rego: Sunt in et quia cum. - version: In quis nesciunt autem et. - - data: Commodi nemo fugiat id praesentium accusantium expedita. - dataConfig: Qui non quia. - group: Sequi adipisci et nulla. - lastUpdate: 8181859392515170659 - locked: false - policyName: Consequatur accusamus. - rego: Sunt in et quia cum. - version: In quis nesciunt autem et. - - data: Commodi nemo fugiat id praesentium accusantium expedita. - dataConfig: Qui non quia. - group: Sequi adipisci et nulla. - lastUpdate: 8181859392515170659 - locked: false - policyName: Consequatur accusamus. - rego: Sunt in et quia cum. - version: In quis nesciunt autem et. + - data: Accusamus enim. + dataConfig: Recusandae est rerum corrupti quia. + group: Optio quia et laborum. + lastUpdate: 1029654258457164464 + locked: true + policyName: Error maxime quasi quia non voluptatibus error. + rego: Ut amet. + version: In libero perspiciatis voluptatum ut soluta. + - data: Accusamus enim. + dataConfig: Recusandae est rerum corrupti quia. + group: Optio quia et laborum. + lastUpdate: 1029654258457164464 + locked: true + policyName: Error maxime quasi quia non voluptatibus error. + rego: Ut amet. + version: In libero perspiciatis voluptatum ut soluta. required: - policies Policy: @@ -516,19 +546,19 @@ components: data: type: string description: Policy static data. - example: Ipsa ad voluptatum maxime ut. + example: Non quo ut molestias rerum sunt. dataConfig: type: string description: Policy static data optional configuration. - example: Aut asperiores. + example: Omnis dolores totam voluptatem rerum. group: type: string description: Policy group. - example: Veritatis quam qui nostrum eaque. + example: Iusto ut. lastUpdate: type: integer description: Last update (Unix timestamp). - example: 1131015782715696616 + example: 3092150594834775360 format: int64 locked: type: boolean @@ -537,30 +567,47 @@ components: policyName: type: string description: Policy name. - example: Maiores et minus. + example: Sed sit. rego: type: string description: Policy rego source code. - example: Delectus rerum molestiae possimus cum laboriosam. + example: Et mollitia. version: type: string description: Policy version. - example: Et dolores. + example: Et eaque. example: - data: Similique architecto. - dataConfig: Sunt ut est ut molestias. - group: Error minus vel voluptate quasi. - lastUpdate: 2308837710267791288 - locked: true - policyName: Omnis molestiae tempora sed repellendus. - rego: Vel sunt dolorem ea architecto iure. - version: Debitis consectetur. + data: Rerum asperiores nulla. + dataConfig: Tenetur rerum necessitatibus fugit. + group: Est impedit. + lastUpdate: 2958895584654309878 + locked: false + policyName: Enim omnis. + rego: Neque et sed modi accusantium. + version: Consequatur ut suscipit. required: - group - policyName - version - locked - lastUpdate + WebhooksRequestBody: + type: object + properties: + subscriber: + type: string + description: Name of the subscriber for policy. + example: Harum voluptate et ut similique doloremque quis. + webhook_url: + type: string + description: Subscriber webhook url. + example: Repellendus quis rem et occaecati quam tempora. + example: + subscriber: Vel saepe nisi et. + webhook_url: Expedita ipsum minus ipsam. + required: + - webhook_url + - subscriber tags: - name: health description: Health service provides health check endpoints. diff --git a/gen/http/policy/client/cli.go b/gen/http/policy/client/cli.go index c032452f7ed3cb2596000498d6a11acabb8f2773..fbd0d51da31d090091af5598c4d0c55ab21109e9 100644 --- a/gen/http/policy/client/cli.go +++ b/gen/http/policy/client/cli.go @@ -23,7 +23,7 @@ func BuildEvaluatePayload(policyEvaluateBody string, policyEvaluateGroup string, { err = json.Unmarshal([]byte(policyEvaluateBody), &body) if err != nil { - return nil, fmt.Errorf("invalid JSON for body, \nerror: %s, \nexample of valid JSON:\n%s", err, "\"Quibusdam ab repellendus in illum.\"") + return nil, fmt.Errorf("invalid JSON for body, \nerror: %s, \nexample of valid JSON:\n%s", err, "\"Earum velit illum quia aliquam atque voluptatum.\"") } } var group string @@ -171,3 +171,37 @@ func BuildListPoliciesPayload(policyListPoliciesLocked string, policyListPolicie return v, nil } + +// BuildWebhooksPayload builds the payload for the policy Webhooks endpoint +// from CLI flags. +func BuildWebhooksPayload(policyWebhooksBody string, policyWebhooksGroup string, policyWebhooksPolicyname string, policyWebhooksVersion string) (*policy.WebHooksRequest, error) { + var err error + var body WebhooksRequestBody + { + err = json.Unmarshal([]byte(policyWebhooksBody), &body) + if err != nil { + return nil, fmt.Errorf("invalid JSON for body, \nerror: %s, \nexample of valid JSON:\n%s", err, "'{\n \"subscriber\": \"Est totam officia necessitatibus tempore.\",\n \"webhook_url\": \"Ad ab perspiciatis voluptatem pariatur corporis est.\"\n }'") + } + } + var group string + { + group = policyWebhooksGroup + } + var policyname string + { + policyname = policyWebhooksPolicyname + } + var version string + { + version = policyWebhooksVersion + } + v := &policy.WebHooksRequest{ + WebhookURL: body.WebhookURL, + Subscriber: body.Subscriber, + } + v.Group = group + v.Policyname = policyname + v.Version = version + + return v, nil +} diff --git a/gen/http/policy/client/client.go b/gen/http/policy/client/client.go index afcf58c9ff68a7f4a4f708f7b555a90114059207..435cb3eb4fc22beb5429130272e604b6fd84876f 100644 --- a/gen/http/policy/client/client.go +++ b/gen/http/policy/client/client.go @@ -31,6 +31,10 @@ type Client struct { // ListPolicies endpoint. ListPoliciesDoer goahttp.Doer + // Webhooks Doer is the HTTP client used to make requests to the Webhooks + // endpoint. + WebhooksDoer goahttp.Doer + // RestoreResponseBody controls whether the response bodies are reset after // decoding so they can be read again. RestoreResponseBody bool @@ -55,6 +59,7 @@ func NewClient( LockDoer: doer, UnlockDoer: doer, ListPoliciesDoer: doer, + WebhooksDoer: doer, RestoreResponseBody: restoreBody, scheme: scheme, host: host, @@ -148,3 +153,27 @@ func (c *Client) ListPolicies() goa.Endpoint { return decodeResponse(resp) } } + +// Webhooks returns an endpoint that makes HTTP requests to the policy service +// Webhooks server. +func (c *Client) Webhooks() goa.Endpoint { + var ( + encodeRequest = EncodeWebhooksRequest(c.encoder) + decodeResponse = DecodeWebhooksResponse(c.decoder, c.RestoreResponseBody) + ) + return func(ctx context.Context, v any) (any, error) { + req, err := c.BuildWebhooksRequest(ctx, v) + if err != nil { + return nil, err + } + err = encodeRequest(req, v) + if err != nil { + return nil, err + } + resp, err := c.WebhooksDoer.Do(req) + if err != nil { + return nil, goahttp.ErrRequestError("policy", "Webhooks", err) + } + return decodeResponse(resp) + } +} diff --git a/gen/http/policy/client/encode_decode.go b/gen/http/policy/client/encode_decode.go index 417538d82bfd8fffd8819c87b9aab48745cd6445..8f864fb47dcd31ef495a11c203d9a1036dbfbebf 100644 --- a/gen/http/policy/client/encode_decode.go +++ b/gen/http/policy/client/encode_decode.go @@ -315,6 +315,86 @@ func DecodeListPoliciesResponse(decoder func(*http.Response) goahttp.Decoder, re } } +// BuildWebhooksRequest instantiates a HTTP request object with method and path +// set to call the "policy" service "Webhooks" endpoint +func (c *Client) BuildWebhooksRequest(ctx context.Context, v any) (*http.Request, error) { + var ( + group string + policyname string + version string + ) + { + p, ok := v.(*policy.WebHooksRequest) + if !ok { + return nil, goahttp.ErrInvalidType("policy", "Webhooks", "*policy.WebHooksRequest", v) + } + group = p.Group + policyname = p.Policyname + version = p.Version + } + u := &url.URL{Scheme: c.scheme, Host: c.host, Path: WebhooksPolicyPath(group, policyname, version)} + req, err := http.NewRequest("POST", u.String(), nil) + if err != nil { + return nil, goahttp.ErrInvalidURL("policy", "Webhooks", u.String(), err) + } + if ctx != nil { + req = req.WithContext(ctx) + } + + return req, nil +} + +// EncodeWebhooksRequest returns an encoder for requests sent to the policy +// Webhooks server. +func EncodeWebhooksRequest(encoder func(*http.Request) goahttp.Encoder) func(*http.Request, any) error { + return func(req *http.Request, v any) error { + p, ok := v.(*policy.WebHooksRequest) + if !ok { + return goahttp.ErrInvalidType("policy", "Webhooks", "*policy.WebHooksRequest", v) + } + body := NewWebhooksRequestBody(p) + if err := encoder(req).Encode(&body); err != nil { + return goahttp.ErrEncodingError("policy", "Webhooks", err) + } + return nil + } +} + +// DecodeWebhooksResponse returns a decoder for responses returned by the +// policy Webhooks endpoint. restoreBody controls whether the response body +// should be restored after having been read. +func DecodeWebhooksResponse(decoder func(*http.Response) goahttp.Decoder, restoreBody bool) func(*http.Response) (any, error) { + return func(resp *http.Response) (any, error) { + if restoreBody { + b, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + resp.Body = io.NopCloser(bytes.NewBuffer(b)) + defer func() { + resp.Body = io.NopCloser(bytes.NewBuffer(b)) + }() + } else { + defer resp.Body.Close() + } + switch resp.StatusCode { + case http.StatusOK: + var ( + body any + err error + ) + err = decoder(resp).Decode(&body) + if err != nil { + return nil, goahttp.ErrDecodingError("policy", "Webhooks", err) + } + return body, nil + default: + body, _ := io.ReadAll(resp.Body) + return nil, goahttp.ErrInvalidResponse("policy", "Webhooks", resp.StatusCode, string(body)) + } + } +} + // unmarshalPolicyResponseBodyToPolicyPolicy builds a value of type // *policy.Policy from a value of type *PolicyResponseBody. func unmarshalPolicyResponseBodyToPolicyPolicy(v *PolicyResponseBody) *policy.Policy { diff --git a/gen/http/policy/client/paths.go b/gen/http/policy/client/paths.go index a5da8845a897c497d06e6dc0ed55e98437560100..06a7d6be4315a562a788f5d8418b78268ffeceb7 100644 --- a/gen/http/policy/client/paths.go +++ b/gen/http/policy/client/paths.go @@ -40,3 +40,8 @@ func UnlockPolicyPath(group string, policyName string, version string) string { func ListPoliciesPolicyPath() string { return "/v1/policies" } + +// WebhooksPolicyPath returns the URL path to the policy service Webhooks HTTP endpoint. +func WebhooksPolicyPath(group string, policyname string, version string) string { + return fmt.Sprintf("/policy/%v/%v/%v/notifychange", group, policyname, version) +} diff --git a/gen/http/policy/client/types.go b/gen/http/policy/client/types.go index 4f9370b3baf08b33de636c9855b34fbb7e16873d..f17e6ed9c0ad0a3a5cf312f4cd2848d7d76765be 100644 --- a/gen/http/policy/client/types.go +++ b/gen/http/policy/client/types.go @@ -12,6 +12,15 @@ import ( goa "goa.design/goa/v3/pkg" ) +// WebhooksRequestBody is the type of the "policy" service "Webhooks" endpoint +// HTTP request body. +type WebhooksRequestBody struct { + // Subscriber webhook url. + WebhookURL string `form:"webhook_url" json:"webhook_url" xml:"webhook_url"` + // Name of the subscriber for policy. + Subscriber string `form:"subscriber" json:"subscriber" xml:"subscriber"` +} + // ListPoliciesResponseBody is the type of the "policy" service "ListPolicies" // endpoint HTTP response body. type ListPoliciesResponseBody struct { @@ -39,6 +48,16 @@ type PolicyResponseBody struct { LastUpdate *int64 `form:"lastUpdate,omitempty" json:"lastUpdate,omitempty" xml:"lastUpdate,omitempty"` } +// NewWebhooksRequestBody builds the HTTP request body from the payload of the +// "Webhooks" endpoint of the "policy" service. +func NewWebhooksRequestBody(p *policy.WebHooksRequest) *WebhooksRequestBody { + body := &WebhooksRequestBody{ + WebhookURL: p.WebhookURL, + Subscriber: p.Subscriber, + } + return body +} + // NewEvaluateResultOK builds a "policy" service "Evaluate" endpoint result // from a HTTP "OK" response. func NewEvaluateResultOK(body any, eTag string) *policy.EvaluateResult { diff --git a/gen/http/policy/server/encode_decode.go b/gen/http/policy/server/encode_decode.go index 8556a4be5eb12a836422f45341b5a3b9d0cf2cc5..d37f26d769134a4a9973a04c934dfe5f43360033 100644 --- a/gen/http/policy/server/encode_decode.go +++ b/gen/http/policy/server/encode_decode.go @@ -214,6 +214,54 @@ func DecodeListPoliciesRequest(mux goahttp.Muxer, decoder func(*http.Request) go } } +// EncodeWebhooksResponse returns an encoder for responses returned by the +// policy Webhooks endpoint. +func EncodeWebhooksResponse(encoder func(context.Context, http.ResponseWriter) goahttp.Encoder) func(context.Context, http.ResponseWriter, any) error { + return func(ctx context.Context, w http.ResponseWriter, v any) error { + res, _ := v.(any) + enc := encoder(ctx, w) + body := res + w.WriteHeader(http.StatusOK) + return enc.Encode(body) + } +} + +// DecodeWebhooksRequest returns a decoder for requests sent to the policy +// Webhooks endpoint. +func DecodeWebhooksRequest(mux goahttp.Muxer, decoder func(*http.Request) goahttp.Decoder) func(*http.Request) (any, error) { + return func(r *http.Request) (any, error) { + var ( + body WebhooksRequestBody + err error + ) + err = decoder(r).Decode(&body) + if err != nil { + if err == io.EOF { + return nil, goa.MissingPayloadError() + } + return nil, goa.DecodePayloadError(err.Error()) + } + err = ValidateWebhooksRequestBody(&body) + if err != nil { + return nil, err + } + + var ( + group string + policyname string + version string + + params = mux.Vars(r) + ) + group = params["group"] + policyname = params["policyname"] + version = params["version"] + payload := NewWebhooksWebHooksRequest(&body, group, policyname, version) + + return payload, nil + } +} + // marshalPolicyPolicyToPolicyResponseBody builds a value of type // *PolicyResponseBody from a value of type *policy.Policy. func marshalPolicyPolicyToPolicyResponseBody(v *policy.Policy) *PolicyResponseBody { diff --git a/gen/http/policy/server/paths.go b/gen/http/policy/server/paths.go index f224fbe4c1bc4f5ef5c1d86d22d95f746c08feec..8e398de2d13d4091bdcc65cc9f0f2c1fc02b9330 100644 --- a/gen/http/policy/server/paths.go +++ b/gen/http/policy/server/paths.go @@ -40,3 +40,8 @@ func UnlockPolicyPath(group string, policyName string, version string) string { func ListPoliciesPolicyPath() string { return "/v1/policies" } + +// WebhooksPolicyPath returns the URL path to the policy service Webhooks HTTP endpoint. +func WebhooksPolicyPath(group string, policyname string, version string) string { + return fmt.Sprintf("/policy/%v/%v/%v/notifychange", group, policyname, version) +} diff --git a/gen/http/policy/server/server.go b/gen/http/policy/server/server.go index 2043d7396d4c8ca1b50983eda1b7664ee9e11a2b..e93b79a7e18d3edeb0bf627a4756cb7bc8a49e48 100644 --- a/gen/http/policy/server/server.go +++ b/gen/http/policy/server/server.go @@ -23,6 +23,7 @@ type Server struct { Lock http.Handler Unlock http.Handler ListPolicies http.Handler + Webhooks http.Handler } // MountPoint holds information about the mounted endpoints. @@ -58,11 +59,13 @@ func New( {"Lock", "POST", "/policy/{group}/{policyName}/{version}/lock"}, {"Unlock", "DELETE", "/policy/{group}/{policyName}/{version}/lock"}, {"ListPolicies", "GET", "/v1/policies"}, + {"Webhooks", "POST", "/policy/{group}/{policyname}/{version}/notifychange"}, }, Evaluate: NewEvaluateHandler(e.Evaluate, mux, decoder, encoder, errhandler, formatter), Lock: NewLockHandler(e.Lock, mux, decoder, encoder, errhandler, formatter), Unlock: NewUnlockHandler(e.Unlock, mux, decoder, encoder, errhandler, formatter), ListPolicies: NewListPoliciesHandler(e.ListPolicies, mux, decoder, encoder, errhandler, formatter), + Webhooks: NewWebhooksHandler(e.Webhooks, mux, decoder, encoder, errhandler, formatter), } } @@ -75,6 +78,7 @@ func (s *Server) Use(m func(http.Handler) http.Handler) { s.Lock = m(s.Lock) s.Unlock = m(s.Unlock) s.ListPolicies = m(s.ListPolicies) + s.Webhooks = m(s.Webhooks) } // MethodNames returns the methods served. @@ -86,6 +90,7 @@ func Mount(mux goahttp.Muxer, h *Server) { MountLockHandler(mux, h.Lock) MountUnlockHandler(mux, h.Unlock) MountListPoliciesHandler(mux, h.ListPolicies) + MountWebhooksHandler(mux, h.Webhooks) } // Mount configures the mux to serve the policy endpoints. @@ -298,3 +303,54 @@ func NewListPoliciesHandler( } }) } + +// MountWebhooksHandler configures the mux to serve the "policy" service +// "Webhooks" endpoint. +func MountWebhooksHandler(mux goahttp.Muxer, h http.Handler) { + f, ok := h.(http.HandlerFunc) + if !ok { + f = func(w http.ResponseWriter, r *http.Request) { + h.ServeHTTP(w, r) + } + } + mux.Handle("POST", "/policy/{group}/{policyname}/{version}/notifychange", f) +} + +// NewWebhooksHandler creates a HTTP handler which loads the HTTP request and +// calls the "policy" service "Webhooks" endpoint. +func NewWebhooksHandler( + endpoint goa.Endpoint, + mux goahttp.Muxer, + decoder func(*http.Request) goahttp.Decoder, + encoder func(context.Context, http.ResponseWriter) goahttp.Encoder, + errhandler func(context.Context, http.ResponseWriter, error), + formatter func(ctx context.Context, err error) goahttp.Statuser, +) http.Handler { + var ( + decodeRequest = DecodeWebhooksRequest(mux, decoder) + encodeResponse = EncodeWebhooksResponse(encoder) + encodeError = goahttp.ErrorEncoder(encoder, formatter) + ) + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + ctx := context.WithValue(r.Context(), goahttp.AcceptTypeKey, r.Header.Get("Accept")) + ctx = context.WithValue(ctx, goa.MethodKey, "Webhooks") + ctx = context.WithValue(ctx, goa.ServiceKey, "policy") + payload, err := decodeRequest(r) + if err != nil { + if err := encodeError(ctx, w, err); err != nil { + errhandler(ctx, w, err) + } + return + } + res, err := endpoint(ctx, payload) + if err != nil { + if err := encodeError(ctx, w, err); err != nil { + errhandler(ctx, w, err) + } + return + } + if err := encodeResponse(ctx, w, res); err != nil { + errhandler(ctx, w, err) + } + }) +} diff --git a/gen/http/policy/server/types.go b/gen/http/policy/server/types.go index 31b816ef74eb879775e220f44c2da4d73d4df8b4..5b878ce0066eddccb820c2bad7800f69e1b85d88 100644 --- a/gen/http/policy/server/types.go +++ b/gen/http/policy/server/types.go @@ -9,8 +9,18 @@ package server import ( policy "gitlab.eclipse.org/eclipse/xfsc/tsa/policy/gen/policy" + goa "goa.design/goa/v3/pkg" ) +// WebhooksRequestBody is the type of the "policy" service "Webhooks" endpoint +// HTTP request body. +type WebhooksRequestBody struct { + // Subscriber webhook url. + WebhookURL *string `form:"webhook_url,omitempty" json:"webhook_url,omitempty" xml:"webhook_url,omitempty"` + // Name of the subscriber for policy. + Subscriber *string `form:"subscriber,omitempty" json:"subscriber,omitempty" xml:"subscriber,omitempty"` +} + // ListPoliciesResponseBody is the type of the "policy" service "ListPolicies" // endpoint HTTP response body. type ListPoliciesResponseBody struct { @@ -99,3 +109,28 @@ func NewListPoliciesPoliciesRequest(locked *bool, rego *bool, data *bool, dataCo return v } + +// NewWebhooksWebHooksRequest builds a policy service Webhooks endpoint payload. +func NewWebhooksWebHooksRequest(body *WebhooksRequestBody, group string, policyname string, version string) *policy.WebHooksRequest { + v := &policy.WebHooksRequest{ + WebhookURL: *body.WebhookURL, + Subscriber: *body.Subscriber, + } + v.Group = group + v.Policyname = policyname + v.Version = version + + return v +} + +// ValidateWebhooksRequestBody runs the validations defined on +// WebhooksRequestBody +func ValidateWebhooksRequestBody(body *WebhooksRequestBody) (err error) { + if body.WebhookURL == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("webhook_url", "body")) + } + if body.Subscriber == nil { + err = goa.MergeErrors(err, goa.MissingFieldError("subscriber", "body")) + } + return +} diff --git a/gen/policy/client.go b/gen/policy/client.go index 49cb8cd5cac1433254711a75ee6c0a94f0e91687..26088b1527348298ff3636a986370e9e762cb135 100644 --- a/gen/policy/client.go +++ b/gen/policy/client.go @@ -19,15 +19,17 @@ type Client struct { LockEndpoint goa.Endpoint UnlockEndpoint goa.Endpoint ListPoliciesEndpoint goa.Endpoint + WebhooksEndpoint goa.Endpoint } // NewClient initializes a "policy" service client given the endpoints. -func NewClient(evaluate, lock, unlock, listPolicies goa.Endpoint) *Client { +func NewClient(evaluate, lock, unlock, listPolicies, webhooks goa.Endpoint) *Client { return &Client{ EvaluateEndpoint: evaluate, LockEndpoint: lock, UnlockEndpoint: unlock, ListPoliciesEndpoint: listPolicies, + WebhooksEndpoint: webhooks, } } @@ -62,3 +64,13 @@ func (c *Client) ListPolicies(ctx context.Context, p *PoliciesRequest) (res *Pol } return ires.(*PoliciesResult), nil } + +// Webhooks calls the "Webhooks" endpoint of the "policy" service. +func (c *Client) Webhooks(ctx context.Context, p *WebHooksRequest) (res any, err error) { + var ires any + ires, err = c.WebhooksEndpoint(ctx, p) + if err != nil { + return + } + return ires.(any), nil +} diff --git a/gen/policy/endpoints.go b/gen/policy/endpoints.go index e1c82db041f06b640cfcc82dfcf81e65272001c2..7b2afbe9474495eaceee08f254d1812b14f1e600 100644 --- a/gen/policy/endpoints.go +++ b/gen/policy/endpoints.go @@ -19,6 +19,7 @@ type Endpoints struct { Lock goa.Endpoint Unlock goa.Endpoint ListPolicies goa.Endpoint + Webhooks goa.Endpoint } // NewEndpoints wraps the methods of the "policy" service with endpoints. @@ -28,6 +29,7 @@ func NewEndpoints(s Service) *Endpoints { Lock: NewLockEndpoint(s), Unlock: NewUnlockEndpoint(s), ListPolicies: NewListPoliciesEndpoint(s), + Webhooks: NewWebhooksEndpoint(s), } } @@ -37,6 +39,7 @@ func (e *Endpoints) Use(m func(goa.Endpoint) goa.Endpoint) { e.Lock = m(e.Lock) e.Unlock = m(e.Unlock) e.ListPolicies = m(e.ListPolicies) + e.Webhooks = m(e.Webhooks) } // NewEvaluateEndpoint returns an endpoint function that calls the method @@ -74,3 +77,12 @@ func NewListPoliciesEndpoint(s Service) goa.Endpoint { return s.ListPolicies(ctx, p) } } + +// NewWebhooksEndpoint returns an endpoint function that calls the method +// "Webhooks" of service "policy". +func NewWebhooksEndpoint(s Service) goa.Endpoint { + return func(ctx context.Context, req any) (any, error) { + p := req.(*WebHooksRequest) + return s.Webhooks(ctx, p) + } +} diff --git a/gen/policy/service.go b/gen/policy/service.go index 2ca613b9186fc1be5c01ab16a0671819c7c90dc7..7f05e1b38eba0796490fa157fabd2a94963449f9 100644 --- a/gen/policy/service.go +++ b/gen/policy/service.go @@ -21,6 +21,8 @@ type Service interface { Unlock(context.Context, *UnlockRequest) (err error) // List policies from storage with optional filters. ListPolicies(context.Context, *PoliciesRequest) (res *PoliciesResult, err error) + // Gives ability to user to subscribe for policy change via webhooks + Webhooks(context.Context, *WebHooksRequest) (res any, err error) } // ServiceName is the name of the service as defined in the design. This is the @@ -31,7 +33,7 @@ const ServiceName = "policy" // MethodNames lists the service method names as defined in the design. These // are the same values that are set in the endpoint request contexts under the // MethodKey key. -var MethodNames = [4]string{"Evaluate", "Lock", "Unlock", "ListPolicies"} +var MethodNames = [5]string{"Evaluate", "Lock", "Unlock", "ListPolicies", "Webhooks"} // EvaluateRequest is the payload type of the policy service Evaluate method. type EvaluateRequest struct { @@ -112,3 +114,17 @@ type UnlockRequest struct { // Policy version. Version string } + +// WebHooksRequest is the payload type of the policy service Webhooks method. +type WebHooksRequest struct { + // Subscriber webhook url. + WebhookURL string + // Name of the subscriber for policy. + Subscriber string + // Policy name. + Policyname string + // Policy group. + Group string + // Policy version. + Version string +} diff --git a/internal/notify/notify.go b/internal/notify/notify.go index 4f52c85eb87523dec1dd28241a8991937999b519..6417cfed9f4f7f64226e854de40b7fb92d116871 100644 --- a/internal/notify/notify.go +++ b/internal/notify/notify.go @@ -1,17 +1,32 @@ package notify import ( + "bytes" "context" + "encoding/json" + "fmt" + "net/http" + + "gitlab.eclipse.org/eclipse/xfsc/tsa/policy/internal/storage" + "go.uber.org/zap" ) //go:generate counterfeiter . Events +//go:generate counterfeiter . Storage type Events interface { Send(ctx context.Context, data any) error } +type Storage interface { + FindAllSubscribed(ctx context.Context, policyName, policyGroup, policyVersion string) ([]*storage.Subscriber, error) +} + type Notifier struct { - events Events + events Events + storage Storage + client *http.Client + logger *zap.Logger } type EventPolicyChange struct { @@ -22,12 +37,59 @@ type EventPolicyChange struct { // New creates a policy change notifier for interested subscribers. // It can notify for policy changes both via MessageQueue or Web hooks. -func New(events Events) *Notifier { - return &Notifier{events: events} +func New(events Events, client *http.Client, storage Storage, logger *zap.Logger) *Notifier { + return &Notifier{events: events, client: client, storage: storage, logger: logger} } // PolicyDataChange is called when the policies source code or data are updated // in storage. The function will notify subscribers of the given changes. -func (n *Notifier) PolicyDataChange(ctx context.Context, event *EventPolicyChange) error { - return n.events.Send(ctx, event) +func (n *Notifier) PolicyDataChange(ctx context.Context, policyName, policyGroup, policyVersion string) error { + data := &EventPolicyChange{Name: policyName, Version: policyVersion, Group: policyGroup} + + n.notifySubscribers(ctx, data) + + return n.events.Send(ctx, data) +} + +func (n *Notifier) notifySubscribers(ctx context.Context, data *EventPolicyChange) { + logger := n.logger.With( + zap.String("operation", "notifySubscribers"), + zap.String("group", data.Group), + zap.String("policy", data.Name), + zap.String("version", data.Version), + ) + + byteData, err := json.Marshal(data) + if err != nil { + logger.Error("error while marshal the data", zap.Error(err)) + } + + subscribers, err := n.storage.FindAllSubscribed(ctx, data.Name, data.Group, data.Version) + if err != nil { + logger.Error("error while getting subscribers", zap.Error(err)) + } + + for _, subscriber := range subscribers { + req, err := http.NewRequestWithContext(ctx, http.MethodPost, subscriber.WebhookURL, bytes.NewBuffer(byteData)) + if err != nil { + err = fmt.Errorf("error while creating request for sending data to subscriber: %s with URL: %s: %w", subscriber.Name, subscriber.WebhookURL, err) + logger.Error("error creating request", zap.Error(err)) + } + req.Header.Set("Content-Type", "application/json") + + res, err := n.client.Do(req) + if err != nil { + err = fmt.Errorf("error while trying to send data to subscriber: %s with URL: %s: %w", subscriber.Name, subscriber.WebhookURL, err) + logger.Error("error sending data", zap.Error(err)) + } + + if res != nil { + defer res.Body.Close() + + if res.StatusCode >= http.StatusBadRequest { + err = fmt.Errorf("error: subscriber %s with URL %s didn't respond with status code %d: %w", subscriber.Name, subscriber.WebhookURL, res.StatusCode, err) + logger.Error("client did not respond", zap.Error(err)) + } + } + } } diff --git a/internal/notify/notify_test.go b/internal/notify/notify_test.go index ed6aadbce9512cf526dac0cd1b7c533e3209bb35..2b81e0f73fb3089ab28e203854c44166c35fe08a 100644 --- a/internal/notify/notify_test.go +++ b/internal/notify/notify_test.go @@ -3,17 +3,21 @@ package notify_test import ( "context" "fmt" + "net/http" "testing" "github.com/stretchr/testify/assert" "gitlab.eclipse.org/eclipse/xfsc/tsa/policy/internal/notify" "gitlab.eclipse.org/eclipse/xfsc/tsa/policy/internal/notify/notifyfakes" + "gitlab.eclipse.org/eclipse/xfsc/tsa/policy/internal/storage" + "go.uber.org/zap" ) func TestNotify_PolicyDataChange(t *testing.T) { tests := []struct { name string events notify.Events + storage notify.Storage eventPolicyChange *notify.EventPolicyChange errText string @@ -21,6 +25,9 @@ func TestNotify_PolicyDataChange(t *testing.T) { { name: "error when sending event", eventPolicyChange: ¬ify.EventPolicyChange{Name: "exampleName", Version: "exampleVersion", Group: "exampleGroup"}, + storage: ¬ifyfakes.FakeStorage{FindAllSubscribedStub: func(ctx context.Context, s1, s2, s3 string) ([]*storage.Subscriber, error) { + return []*storage.Subscriber{}, nil + }}, events: ¬ifyfakes.FakeEvents{SendStub: func(ctx context.Context, a any) error { return fmt.Errorf("some error") }}, @@ -31,6 +38,9 @@ func TestNotify_PolicyDataChange(t *testing.T) { { name: "sending event is successful", eventPolicyChange: ¬ify.EventPolicyChange{Name: "exampleName", Version: "exampleVersion", Group: "exampleGroup"}, + storage: ¬ifyfakes.FakeStorage{FindAllSubscribedStub: func(ctx context.Context, s1, s2, s3 string) ([]*storage.Subscriber, error) { + return []*storage.Subscriber{}, nil + }}, events: ¬ifyfakes.FakeEvents{SendStub: func(ctx context.Context, a any) error { return nil }}, @@ -39,8 +49,8 @@ func TestNotify_PolicyDataChange(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - notifier := notify.New(test.events) - err := notifier.PolicyDataChange(context.Background(), test.eventPolicyChange) + notifier := notify.New(test.events, http.DefaultClient, test.storage, zap.NewNop()) + err := notifier.PolicyDataChange(context.Background(), test.eventPolicyChange.Name, test.eventPolicyChange.Group, test.eventPolicyChange.Version) if test.errText != "" { assert.ErrorContains(t, err, test.errText) } else { diff --git a/internal/notify/notifyfakes/fake_storage.go b/internal/notify/notifyfakes/fake_storage.go new file mode 100644 index 0000000000000000000000000000000000000000..c42f298c057048ad2173177993b48f7bfd63c448 --- /dev/null +++ b/internal/notify/notifyfakes/fake_storage.go @@ -0,0 +1,124 @@ +// Code generated by counterfeiter. DO NOT EDIT. +package notifyfakes + +import ( + "context" + "sync" + + "gitlab.eclipse.org/eclipse/xfsc/tsa/policy/internal/notify" + "gitlab.eclipse.org/eclipse/xfsc/tsa/policy/internal/storage" +) + +type FakeStorage struct { + FindAllSubscribedStub func(context.Context, string, string, string) ([]*storage.Subscriber, error) + findAllSubscribedMutex sync.RWMutex + findAllSubscribedArgsForCall []struct { + arg1 context.Context + arg2 string + arg3 string + arg4 string + } + findAllSubscribedReturns struct { + result1 []*storage.Subscriber + result2 error + } + findAllSubscribedReturnsOnCall map[int]struct { + result1 []*storage.Subscriber + result2 error + } + invocations map[string][][]interface{} + invocationsMutex sync.RWMutex +} + +func (fake *FakeStorage) FindAllSubscribed(arg1 context.Context, arg2 string, arg3 string, arg4 string) ([]*storage.Subscriber, error) { + fake.findAllSubscribedMutex.Lock() + ret, specificReturn := fake.findAllSubscribedReturnsOnCall[len(fake.findAllSubscribedArgsForCall)] + fake.findAllSubscribedArgsForCall = append(fake.findAllSubscribedArgsForCall, struct { + arg1 context.Context + arg2 string + arg3 string + arg4 string + }{arg1, arg2, arg3, arg4}) + stub := fake.FindAllSubscribedStub + fakeReturns := fake.findAllSubscribedReturns + fake.recordInvocation("FindAllSubscribed", []interface{}{arg1, arg2, arg3, arg4}) + fake.findAllSubscribedMutex.Unlock() + if stub != nil { + return stub(arg1, arg2, arg3, arg4) + } + if specificReturn { + return ret.result1, ret.result2 + } + return fakeReturns.result1, fakeReturns.result2 +} + +func (fake *FakeStorage) FindAllSubscribedCallCount() int { + fake.findAllSubscribedMutex.RLock() + defer fake.findAllSubscribedMutex.RUnlock() + return len(fake.findAllSubscribedArgsForCall) +} + +func (fake *FakeStorage) FindAllSubscribedCalls(stub func(context.Context, string, string, string) ([]*storage.Subscriber, error)) { + fake.findAllSubscribedMutex.Lock() + defer fake.findAllSubscribedMutex.Unlock() + fake.FindAllSubscribedStub = stub +} + +func (fake *FakeStorage) FindAllSubscribedArgsForCall(i int) (context.Context, string, string, string) { + fake.findAllSubscribedMutex.RLock() + defer fake.findAllSubscribedMutex.RUnlock() + argsForCall := fake.findAllSubscribedArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4 +} + +func (fake *FakeStorage) FindAllSubscribedReturns(result1 []*storage.Subscriber, result2 error) { + fake.findAllSubscribedMutex.Lock() + defer fake.findAllSubscribedMutex.Unlock() + fake.FindAllSubscribedStub = nil + fake.findAllSubscribedReturns = struct { + result1 []*storage.Subscriber + result2 error + }{result1, result2} +} + +func (fake *FakeStorage) FindAllSubscribedReturnsOnCall(i int, result1 []*storage.Subscriber, result2 error) { + fake.findAllSubscribedMutex.Lock() + defer fake.findAllSubscribedMutex.Unlock() + fake.FindAllSubscribedStub = nil + if fake.findAllSubscribedReturnsOnCall == nil { + fake.findAllSubscribedReturnsOnCall = make(map[int]struct { + result1 []*storage.Subscriber + result2 error + }) + } + fake.findAllSubscribedReturnsOnCall[i] = struct { + result1 []*storage.Subscriber + result2 error + }{result1, result2} +} + +func (fake *FakeStorage) Invocations() map[string][][]interface{} { + fake.invocationsMutex.RLock() + defer fake.invocationsMutex.RUnlock() + fake.findAllSubscribedMutex.RLock() + defer fake.findAllSubscribedMutex.RUnlock() + copiedInvocations := map[string][][]interface{}{} + for key, value := range fake.invocations { + copiedInvocations[key] = value + } + return copiedInvocations +} + +func (fake *FakeStorage) recordInvocation(key string, args []interface{}) { + fake.invocationsMutex.Lock() + defer fake.invocationsMutex.Unlock() + if fake.invocations == nil { + fake.invocations = map[string][][]interface{}{} + } + if fake.invocations[key] == nil { + fake.invocations[key] = [][]interface{}{} + } + fake.invocations[key] = append(fake.invocations[key], args) +} + +var _ notify.Storage = new(FakeStorage) diff --git a/internal/regocache/regocache.go b/internal/regocache/regocache.go index e100e032e6d41beb48963225e4d3723775a93cf9..bbe8c7687459bd1d41e8835d831a2c1307e80162 100644 --- a/internal/regocache/regocache.go +++ b/internal/regocache/regocache.go @@ -7,7 +7,6 @@ import ( "context" "sync" - "gitlab.eclipse.org/eclipse/xfsc/tsa/policy/internal/notify" "gitlab.eclipse.org/eclipse/xfsc/tsa/policy/internal/storage" ) @@ -43,7 +42,7 @@ func (c *Cache) Purge() { } // PolicyDataChange triggers purge on the cache. -func (c *Cache) PolicyDataChange(_ context.Context, _ *notify.EventPolicyChange) error { +func (c *Cache) PolicyDataChange(_ context.Context, _, _, _ string) error { c.Purge() return nil } diff --git a/internal/regocache/regocache_test.go b/internal/regocache/regocache_test.go index 0205858b6fac472675dd976f2a339e2ebc50ea6b..281e92c72b5ff8230acc79c9885d425c07b99907 100644 --- a/internal/regocache/regocache_test.go +++ b/internal/regocache/regocache_test.go @@ -73,7 +73,7 @@ func TestCache_PolicyDataChange(t *testing.T) { cache := regocache.New() cache.Set("key1", &p1) - err := cache.PolicyDataChange(context.Background(), nil) + err := cache.PolicyDataChange(context.Background(), "", "", "") assert.Nil(t, err) q2, ok := cache.Get("key1") assert.False(t, ok) diff --git a/internal/service/policy/policyfakes/fake_storage.go b/internal/service/policy/policyfakes/fake_storage.go index acf20f5ae889e77e6fbc799dccdfa87270d15293..da008faa9c5cb5fcfd18e65df24bcedf3073f6d0 100644 --- a/internal/service/policy/policyfakes/fake_storage.go +++ b/internal/service/policy/policyfakes/fake_storage.go @@ -10,6 +10,34 @@ import ( ) type FakeStorage struct { + CreateSubscriberStub func(context.Context, *storage.Subscriber) error + createSubscriberMutex sync.RWMutex + createSubscriberArgsForCall []struct { + arg1 context.Context + arg2 *storage.Subscriber + } + createSubscriberReturns struct { + result1 error + } + createSubscriberReturnsOnCall map[int]struct { + result1 error + } + FindAllSubscribedStub func(context.Context, string, string, string) ([]*storage.Subscriber, error) + findAllSubscribedMutex sync.RWMutex + findAllSubscribedArgsForCall []struct { + arg1 context.Context + arg2 string + arg3 string + arg4 string + } + findAllSubscribedReturns struct { + result1 []*storage.Subscriber + result2 error + } + findAllSubscribedReturnsOnCall map[int]struct { + result1 []*storage.Subscriber + result2 error + } GetPoliciesStub func(context.Context, *bool) ([]*storage.Policy, error) getPoliciesMutex sync.RWMutex getPoliciesArgsForCall []struct { @@ -59,6 +87,135 @@ type FakeStorage struct { invocationsMutex sync.RWMutex } +func (fake *FakeStorage) CreateSubscriber(arg1 context.Context, arg2 *storage.Subscriber) error { + fake.createSubscriberMutex.Lock() + ret, specificReturn := fake.createSubscriberReturnsOnCall[len(fake.createSubscriberArgsForCall)] + fake.createSubscriberArgsForCall = append(fake.createSubscriberArgsForCall, struct { + arg1 context.Context + arg2 *storage.Subscriber + }{arg1, arg2}) + stub := fake.CreateSubscriberStub + fakeReturns := fake.createSubscriberReturns + fake.recordInvocation("CreateSubscriber", []interface{}{arg1, arg2}) + fake.createSubscriberMutex.Unlock() + if stub != nil { + return stub(arg1, arg2) + } + if specificReturn { + return ret.result1 + } + return fakeReturns.result1 +} + +func (fake *FakeStorage) CreateSubscriberCallCount() int { + fake.createSubscriberMutex.RLock() + defer fake.createSubscriberMutex.RUnlock() + return len(fake.createSubscriberArgsForCall) +} + +func (fake *FakeStorage) CreateSubscriberCalls(stub func(context.Context, *storage.Subscriber) error) { + fake.createSubscriberMutex.Lock() + defer fake.createSubscriberMutex.Unlock() + fake.CreateSubscriberStub = stub +} + +func (fake *FakeStorage) CreateSubscriberArgsForCall(i int) (context.Context, *storage.Subscriber) { + fake.createSubscriberMutex.RLock() + defer fake.createSubscriberMutex.RUnlock() + argsForCall := fake.createSubscriberArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2 +} + +func (fake *FakeStorage) CreateSubscriberReturns(result1 error) { + fake.createSubscriberMutex.Lock() + defer fake.createSubscriberMutex.Unlock() + fake.CreateSubscriberStub = nil + fake.createSubscriberReturns = struct { + result1 error + }{result1} +} + +func (fake *FakeStorage) CreateSubscriberReturnsOnCall(i int, result1 error) { + fake.createSubscriberMutex.Lock() + defer fake.createSubscriberMutex.Unlock() + fake.CreateSubscriberStub = nil + if fake.createSubscriberReturnsOnCall == nil { + fake.createSubscriberReturnsOnCall = make(map[int]struct { + result1 error + }) + } + fake.createSubscriberReturnsOnCall[i] = struct { + result1 error + }{result1} +} + +func (fake *FakeStorage) FindAllSubscribed(arg1 context.Context, arg2 string, arg3 string, arg4 string) ([]*storage.Subscriber, error) { + fake.findAllSubscribedMutex.Lock() + ret, specificReturn := fake.findAllSubscribedReturnsOnCall[len(fake.findAllSubscribedArgsForCall)] + fake.findAllSubscribedArgsForCall = append(fake.findAllSubscribedArgsForCall, struct { + arg1 context.Context + arg2 string + arg3 string + arg4 string + }{arg1, arg2, arg3, arg4}) + stub := fake.FindAllSubscribedStub + fakeReturns := fake.findAllSubscribedReturns + fake.recordInvocation("FindAllSubscribed", []interface{}{arg1, arg2, arg3, arg4}) + fake.findAllSubscribedMutex.Unlock() + if stub != nil { + return stub(arg1, arg2, arg3, arg4) + } + if specificReturn { + return ret.result1, ret.result2 + } + return fakeReturns.result1, fakeReturns.result2 +} + +func (fake *FakeStorage) FindAllSubscribedCallCount() int { + fake.findAllSubscribedMutex.RLock() + defer fake.findAllSubscribedMutex.RUnlock() + return len(fake.findAllSubscribedArgsForCall) +} + +func (fake *FakeStorage) FindAllSubscribedCalls(stub func(context.Context, string, string, string) ([]*storage.Subscriber, error)) { + fake.findAllSubscribedMutex.Lock() + defer fake.findAllSubscribedMutex.Unlock() + fake.FindAllSubscribedStub = stub +} + +func (fake *FakeStorage) FindAllSubscribedArgsForCall(i int) (context.Context, string, string, string) { + fake.findAllSubscribedMutex.RLock() + defer fake.findAllSubscribedMutex.RUnlock() + argsForCall := fake.findAllSubscribedArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4 +} + +func (fake *FakeStorage) FindAllSubscribedReturns(result1 []*storage.Subscriber, result2 error) { + fake.findAllSubscribedMutex.Lock() + defer fake.findAllSubscribedMutex.Unlock() + fake.FindAllSubscribedStub = nil + fake.findAllSubscribedReturns = struct { + result1 []*storage.Subscriber + result2 error + }{result1, result2} +} + +func (fake *FakeStorage) FindAllSubscribedReturnsOnCall(i int, result1 []*storage.Subscriber, result2 error) { + fake.findAllSubscribedMutex.Lock() + defer fake.findAllSubscribedMutex.Unlock() + fake.FindAllSubscribedStub = nil + if fake.findAllSubscribedReturnsOnCall == nil { + fake.findAllSubscribedReturnsOnCall = make(map[int]struct { + result1 []*storage.Subscriber + result2 error + }) + } + fake.findAllSubscribedReturnsOnCall[i] = struct { + result1 []*storage.Subscriber + result2 error + }{result1, result2} +} + func (fake *FakeStorage) GetPolicies(arg1 context.Context, arg2 *bool) ([]*storage.Policy, error) { fake.getPoliciesMutex.Lock() ret, specificReturn := fake.getPoliciesReturnsOnCall[len(fake.getPoliciesArgsForCall)] @@ -259,6 +416,10 @@ func (fake *FakeStorage) SetPolicyLockReturnsOnCall(i int, result1 error) { func (fake *FakeStorage) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() + fake.createSubscriberMutex.RLock() + defer fake.createSubscriberMutex.RUnlock() + fake.findAllSubscribedMutex.RLock() + defer fake.findAllSubscribedMutex.RUnlock() fake.getPoliciesMutex.RLock() defer fake.getPoliciesMutex.RUnlock() fake.policyMutex.RLock() diff --git a/internal/service/policy/service.go b/internal/service/policy/service.go index 819c997cb8391c8dc54716ce302e945f8c56fff0..ed8355d2e9f2e55204ee72282c85fde29d71c5c4 100644 --- a/internal/service/policy/service.go +++ b/internal/service/policy/service.go @@ -30,6 +30,7 @@ type Storage interface { Policy(ctx context.Context, group, name, version string) (*storage.Policy, error) SetPolicyLock(ctx context.Context, group, name, version string, lock bool) error GetPolicies(ctx context.Context, locked *bool) ([]*storage.Policy, error) + CreateSubscriber(ctx context.Context, subscriber *storage.Subscriber) error } type RegoCache interface { @@ -241,6 +242,21 @@ func (s *Service) ListPolicies(ctx context.Context, req *policy.PoliciesRequest) return &policy.PoliciesResult{Policies: policiesResult}, nil } +func (s *Service) Webhooks(ctx context.Context, req *policy.WebHooksRequest) (any, error) { + err := s.storage.CreateSubscriber(ctx, &storage.Subscriber{ + Name: req.Subscriber, + WebhookURL: req.WebhookURL, + PolicyName: req.Policyname, + PolicyGroup: req.Group, + PolicyVersion: req.Version, + }) + if err != nil { + return nil, err + } + + return nil, nil +} + // prepareQuery tries to get a prepared query from the regocache. // If the policyCache entry is not found, it will try to prepare a new // query and will set it into the policyCache for future use. diff --git a/internal/storage/storage.go b/internal/storage/storage.go index 81c1dd83116bfae8bde0250213aff9d868d2beb4..5781696f83f9284f72469cad29475a255d886771 100644 --- a/internal/storage/storage.go +++ b/internal/storage/storage.go @@ -12,10 +12,10 @@ import ( zap "go.uber.org/zap" "gitlab.eclipse.org/eclipse/xfsc/tsa/golib/errors" - "gitlab.eclipse.org/eclipse/xfsc/tsa/policy/internal/notify" ) const ( + subscriberCollectionName = "subscribers" lockedField = "locked" dataField = "data" nextDataRefreshTimeField = "nextDataRefreshTime" @@ -23,7 +23,7 @@ const ( ) type PolicyChangeSubscriber interface { - PolicyDataChange(ctx context.Context, event *notify.EventPolicyChange) error + PolicyDataChange(ctx context.Context, policyName, policyGroup, policyVersion string) error } type Policy struct { @@ -43,6 +43,7 @@ type Policy struct { type Storage struct { db *mongo.Client policy *mongo.Collection + subscriber *mongo.Collection subscribers []PolicyChangeSubscriber logger *zap.Logger } @@ -52,10 +53,13 @@ func New(db *mongo.Client, dbname, collection string, logger *zap.Logger) (*Stor return nil, err } + database := db.Database(dbname) + return &Storage{ - db: db, - policy: db.Database(dbname).Collection(collection), - logger: logger, + db: db, + policy: database.Collection(collection), + subscriber: database.Collection(subscriberCollectionName), + logger: logger, }, nil } @@ -128,10 +132,7 @@ func (s *Storage) ListenPolicyDataChanges(ctx context.Context) error { policy := policyEvent.Policy for _, subscriber := range s.subscribers { - err := subscriber.PolicyDataChange( - ctx, - ¬ify.EventPolicyChange{Name: policy.Name, Version: policy.Version, Group: policy.Group}, - ) + err := subscriber.PolicyDataChange(ctx, policy.Name, policy.Group, policy.Version) if err != nil { return err } diff --git a/internal/storage/subscribers.go b/internal/storage/subscribers.go new file mode 100644 index 0000000000000000000000000000000000000000..5ddf9b9402aeea5a88cb208fe7ec0544e1b7cdf6 --- /dev/null +++ b/internal/storage/subscribers.go @@ -0,0 +1,54 @@ +package storage + +import ( + "context" + "time" + + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/bson/primitive" +) + +type Subscriber struct { + ID primitive.ObjectID `bson:"_id"` + Name string + WebhookURL string + PolicyName string + PolicyGroup string + PolicyVersion string + CreatedAt time.Time + UpdatedAt time.Time + DeletedAt *time.Time +} + +func (s *Storage) CreateSubscriber(ctx context.Context, subscriber *Subscriber) error { + subscriber.CreatedAt = time.Now() + subscriber.UpdatedAt = time.Now() + subscriber.ID = primitive.NewObjectID() + + _, err := s.subscriber.InsertOne(ctx, subscriber) + if err != nil { + return err + } + + return nil +} + +func (s *Storage) FindAllSubscribed(ctx context.Context, policyName, policyGroup, policyVersion string) ([]*Subscriber, error) { + cursor, err := s.subscriber.Find(ctx, bson.M{ + "policyname": policyName, + "policygroup": policyGroup, + "policyversion": policyVersion, + }) + + if err != nil { + return nil, err + } + + subscribers := []*Subscriber{} + + if err := cursor.All(ctx, &subscribers); err != nil { + return nil, err + } + + return subscribers, nil +}