-
Notifications
You must be signed in to change notification settings - Fork 38
feat(namespaces CRUD): protos, generated SDK, db interactivity for namespaces table #54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 5 commits
Commits
Show all changes
35 commits
Select commit
Hold shift + click to select a range
e8b7669
Define protos for simple namespaces CRUD
jakedoublev a36c14a
add generated namespaces sdk files
jakedoublev 722a1ce
add grpcurl namespaces examples
jakedoublev a4b2db2
feat: implement attributes
jrschumacher 3665174
add db layer for namespaces and add the serviceclient to the SDK afte…
jakedoublev d44cb49
merging in latest work
jakedoublev f8fbb90
provide namespace back in response when creating/updating and add ser…
jakedoublev 3817b5a
make sure to register namespaces service on start
jakedoublev 44505c0
namespaces cleanup
jakedoublev 7f3d571
namespaces test suite boilerplate
jakedoublev 17130db
Merge branch 'policy-config-changes' into feat/namespaces
jakedoublev 493a999
Merge branch 'policy-config-changes' into feat/namespaces
jakedoublev 2ffca7a
Merge branch 'policy-config-changes' into feat/namespaces
jakedoublev 00bbaac
Merge branch 'policy-config-changes' into feat/namespaces
jakedoublev 8d3a621
move all row scanning to db layer
jakedoublev 2ac05e5
service work for namespaces
jakedoublev c0b7de3
use tableField func in attributes
jakedoublev 49e3a7e
use proper namespace table name
jakedoublev 3939449
require name and id, but id only once on update, and require only nam…
jakedoublev 81cbd0b
ensure working crud of namespaces
jakedoublev 9ee0cb2
lint fix
jakedoublev 6ef08cb
fix grpcurl update example
jakedoublev 4eacdee
add helper for checking constraint violations
jakedoublev 624b006
improve error handling
jakedoublev 6b541a3
consume error handling functions
jakedoublev c733264
Merge branch 'policy-config-changes' into feat/namespaces
jakedoublev ecea196
update to define and test more types of postgres 'bad request' type e…
jakedoublev 03f27f9
consume latest error helper updates
jakedoublev 0df765c
validate working error handling with logs and messages in namespaces
jakedoublev 35b1b44
fix deletion
jakedoublev f4925e2
improve error wrapping by moving it down into the query and exec leve…
jakedoublev 9b2efb4
consume latest db error changes
jakedoublev 8f9804f
avoid nil pointer dereference
jakedoublev 6a8d55d
Merge branch 'policy-config-changes' into feat/namespaces
jakedoublev 86f55ff
declutter diff with varied lint settings
jakedoublev File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| package db | ||
|
|
||
| import ( | ||
| "context" | ||
|
|
||
| sq "github.com/Masterminds/squirrel" | ||
| "github.com/jackc/pgx/v5" | ||
| "github.com/opentdf/opentdf-v2-poc/sdk/attributes" | ||
| ) | ||
|
|
||
| func getAttributeByDefinitionSql(definition_id string) (string, []interface{}, error) { | ||
| return newStatementBuilder(). | ||
| Select("*"). | ||
| Join("attribute_definitions ON attribute_definitions.id = attribute_values.id"). | ||
| Where(sq.Eq{"id": definition_id}). | ||
| From("attribute_values"). | ||
| ToSql() | ||
| } | ||
| func (c Client) GetAttribute(ctx context.Context, definition_id string) (pgx.Row, error) { | ||
| sql, args, err := getAttributeByDefinitionSql(definition_id) | ||
| return c.queryRow(ctx, sql, args, err) | ||
| } | ||
|
|
||
| func getAttributesByNamespaceSql(namespaceId string) (string, []interface{}, error) { | ||
| return newStatementBuilder(). | ||
| Select("*"). | ||
| Join("attribute_definitions ON attribute_definitions.id = attribute_values.id"). | ||
| Where(sq.Eq{"namespace_id": namespaceId}). | ||
| From("attribute_values"). | ||
| ToSql() | ||
| } | ||
| func (c Client) GetAttributesByNamespace(ctx context.Context, namespaceId string) (pgx.Rows, error) { | ||
| sql, args, err := getAttributesByNamespaceSql(namespaceId) | ||
| return c.query(ctx, sql, args, err) | ||
| } | ||
|
|
||
| func createAttributeSql(namespaceId string, name string, rule string) (string, []interface{}, error) { | ||
| return newStatementBuilder(). | ||
| Insert("attribute_values"). | ||
| Columns("namespace_id", "name", "rule"). | ||
| Values(namespaceId, name, rule). | ||
| ToSql() | ||
| } | ||
| func (c Client) CreateAttribute(ctx context.Context, def *attributes.Definition) error { | ||
| sql, args, err := createAttributeSql(def.NamespaceId, def.Name, removeProtobufEnumPrefix(def.Rule.String())) | ||
| return c.exec(ctx, sql, args, err) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| package db | ||
|
|
||
| import "strings" | ||
|
|
||
| func removeProtobufEnumPrefix(s string) string { | ||
| // find the first instance of TYPE_ | ||
| if strings.Contains(s, "TYPE_") { | ||
| // remove everything left of it | ||
| return s[strings.Index(s, "TYPE_")+5:] | ||
| } | ||
| return s | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| package db | ||
|
|
||
| import ( | ||
| "context" | ||
|
|
||
| sq "github.com/Masterminds/squirrel" | ||
| "github.com/jackc/pgx/v5" | ||
| "github.com/opentdf/opentdf-v2-poc/sdk/namespaces" | ||
| ) | ||
|
|
||
| func getNamespaceSql(id string) (string, []interface{}, error) { | ||
| return newStatementBuilder(). | ||
| Select("*"). | ||
| From("namespaces"). | ||
| Where(sq.Eq{"id": id}). | ||
| ToSql() | ||
| } | ||
|
|
||
| func (c Client) GetNamespace(ctx context.Context, id string) (pgx.Row, error) { | ||
| sql, args, err := getNamespaceSql(id) | ||
| return c.queryRow(ctx, sql, args, err) | ||
| } | ||
|
|
||
| func listNamespacesSql() (string, []interface{}, error) { | ||
| return newStatementBuilder(). | ||
| Select("*"). | ||
| From("namespaces"). | ||
| ToSql() | ||
| } | ||
|
|
||
| func (c Client) ListNamespaces(ctx context.Context) (pgx.Rows, error) { | ||
| sql, args, err := listNamespacesSql() | ||
| return c.query(ctx, sql, args, err) | ||
| } | ||
|
|
||
| func createNamespaceSql(namespace *namespaces.Namespace) (string, []interface{}, error) { | ||
| return newStatementBuilder(). | ||
| Insert("namespaces"). | ||
| Columns("name"). | ||
| Values(namespace.Name). | ||
| ToSql() | ||
| } | ||
|
|
||
| func (c Client) CreateNamespace(ctx context.Context, namespace *namespaces.Namespace) error { | ||
| sql, args, err := createNamespaceSql(namespace) | ||
| return c.exec(ctx, sql, args, err) | ||
| } | ||
|
|
||
| func updateNamespaceSql(namespace *namespaces.Namespace) (string, []interface{}, error) { | ||
| return newStatementBuilder(). | ||
| Update("namespaces"). | ||
| Set("name", namespace.Name). | ||
| Where(sq.Eq{"id": namespace.Id}). | ||
| ToSql() | ||
| } | ||
|
|
||
| func (c Client) UpdateNamespace(ctx context.Context, namespace *namespaces.Namespace) error { | ||
| sql, args, err := updateNamespaceSql(namespace) | ||
| return c.exec(ctx, sql, args, err) | ||
| } | ||
|
|
||
| func deleteNamespaceSql(id string) (string, []interface{}, error) { | ||
| return newStatementBuilder(). | ||
| Delete("namespaces"). | ||
| Where(sq.Eq{"id": id}). | ||
| ToSql() | ||
| } | ||
|
|
||
| func (c Client) DeleteNamespace(ctx context.Context, id string) error { | ||
| sql, args, err := deleteNamespaceSql(id) | ||
| return c.exec(ctx, sql, args, err) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,134 @@ | ||
| syntax = "proto3"; | ||
|
|
||
| package namespaces; | ||
|
|
||
| import "buf/validate/validate.proto"; | ||
| import "google/api/annotations.proto"; | ||
|
|
||
| message Namespace { | ||
| // generated uuid in database | ||
| string id = 1; | ||
| // used to partition Attribute Definitions, support by namespace AuthN and enable federation | ||
| string name = 5 [ | ||
| (buf.validate.field).required = true, | ||
| (buf.validate.field).string.max_len = 253, | ||
| (buf.validate.field).cel = { | ||
| id: "namespace_format", | ||
| message: "Namespace must be a valid hostname. It should include at least one dot, with each segment (label) starting and ending with an alphanumeric character. Each label must be 1 to 63 characters long, allowing hyphens but not as the first or last character. The top-level domain (the last segment after the final dot) must consist of at least two alphabetic characters.", | ||
| expression: "this.matches('^([a-zA-Z0-9]([a-zA-Z0-9\\\\-]{0,61}[a-zA-Z0-9])?\\\\.)+[a-zA-Z]{2,}$')" | ||
| } | ||
| ]; | ||
| } | ||
|
|
||
| /* | ||
|
|
||
| Namespace Service Definitions | ||
|
|
||
| */ | ||
|
|
||
| message GetNamespaceRequest { | ||
| string id = 1 [(buf.validate.field).required = true]; | ||
| } | ||
| message GetNamespaceResponse { | ||
| Namespace namespace = 1; | ||
| } | ||
|
|
||
| message ListNamespacesRequest {} | ||
| message ListNamespacesResponse { | ||
| repeated Namespace namespaces = 1; | ||
| } | ||
|
|
||
| message CreateNamespaceRequest { | ||
| Namespace namespace = 1 [(buf.validate.field).required = true]; | ||
| } | ||
| message CreateNamespaceResponse { | ||
| Namespace namespace = 1; | ||
| } | ||
|
|
||
| message UpdateNamespaceRequest { | ||
| string id = 1 [(buf.validate.field).required = true]; | ||
| Namespace namespace = 2 [(buf.validate.field).required = true]; | ||
| } | ||
| message UpdateNamespaceResponse { | ||
| Namespace namespace = 1; | ||
| } | ||
|
|
||
| message DeleteNamespaceRequest { | ||
| string id = 1 [(buf.validate.field).required = true]; | ||
| } | ||
| message DeleteNamespaceResponse {} | ||
|
|
||
| service NamespaceService { | ||
| rpc GetNamespace(GetNamespaceRequest) returns (GetNamespaceResponse) { | ||
| option (google.api.http) = { | ||
| get: "/attributes/namespaces/{id}" | ||
| }; | ||
| } | ||
| rpc ListNamespaces(ListNamespacesRequest) returns (ListNamespacesResponse) { | ||
| option (google.api.http) = { | ||
| get: "/attributes/namespaces" | ||
| }; | ||
| } | ||
| rpc CreateNamespace(CreateNamespaceRequest) returns (CreateNamespaceResponse) { | ||
| option (google.api.http) = { | ||
| post: "/attributes/namespaces" | ||
| }; | ||
| } | ||
| rpc UpdateNamespace(UpdateNamespaceRequest) returns (UpdateNamespaceResponse) { | ||
| option (google.api.http) = { | ||
| put: "/attributes/namespaces/{id}" | ||
| }; | ||
| } | ||
| rpc DeleteNamespace(DeleteNamespaceRequest) returns (DeleteNamespaceResponse) { | ||
| option (google.api.http) = { | ||
| delete: "/attributes/namespaces/{id}" | ||
| }; | ||
| } | ||
| } | ||
|
|
||
| /* | ||
|
|
||
| Namespace Service Examples | ||
|
|
||
| Create a Namespace: | ||
| Request: | ||
| grpcurl -plaintext -d @ localhost:9000 attributes.NamespaceService/CreateNamespace <<EOM | ||
| { | ||
| "namespace": { | ||
| "name": "example.com" | ||
| } | ||
| } | ||
| EOM | ||
| Response: | ||
| { | ||
| "namespace": { | ||
| "id": "b3d9e3e0-0b0a-4e1a-8b0a-0b0a0b0a0b0a", | ||
| "name": "example.com" | ||
| } | ||
| } | ||
|
|
||
| List Namespaces (assuming 3 have been created) | ||
| Request: | ||
| grpcurl -plaintext -d @ localhost:9000 attributes.NamespaceService/ListNamespaces <<EOM | ||
| {} | ||
| EOM | ||
| Response: | ||
| { | ||
| "namespaces": [ | ||
| { | ||
| "id": "b3d9e3e0-0b0a-4e1a-8b0a-0b0a0b0a0b0a", | ||
| "name": "example.com" | ||
| }, | ||
| { | ||
| "id": "b3d9e3e0-0b0a-4e1a-8b0a-0b0a0b0a0b0b", | ||
| "name": "loremipsum.com" | ||
| }, | ||
| { | ||
| "id": "b3d9e3e0-0b0a-4e1a-8b0a-0b0a0b0a0b0c", | ||
| "name": "helloworld.com" | ||
| } | ||
| ] | ||
| } | ||
|
|
||
|
|
||
| */ | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.