diff --git a/client/Pages/EventTypeCreate/Models.elm b/client/Pages/EventTypeCreate/Models.elm index 6e40cdc..db69024 100644 --- a/client/Pages/EventTypeCreate/Models.elm +++ b/client/Pages/EventTypeCreate/Models.elm @@ -13,6 +13,7 @@ import Stores.EventType , categories , cleanupPolicies , compatibilityModes + , emptyEventOwnerSelector , partitionStrategies ) import Stores.Partition @@ -38,6 +39,9 @@ type Field | FieldSchema | FieldEnvelope | FieldAudience + | FieldEventOwnerSelectorType + | FieldEventOwnerSelectorName + | FieldEventOwnerSelectorValue | FieldCleanupPolicy | FieldSql | FieldPartitionCompactionKeyField @@ -100,6 +104,9 @@ defaultValues = , ( FieldEnvelope, boolToString True ) , ( FieldCompatibilityMode, compatibilityModes.forward ) , ( FieldAudience, "" ) + , ( FieldEventOwnerSelectorType, "" ) + , ( FieldEventOwnerSelectorName, "" ) + , ( FieldEventOwnerSelectorValue, "" ) , ( FieldCleanupPolicy, cleanupPolicies.delete ) , ( FieldPartitionCompactionKeyField, emptyString ) ] @@ -120,6 +127,10 @@ loadValues eventType = |> Basics.ceiling |> Basics.clamp 2 4 |> String.fromInt + + ownerField = + eventType.event_owner_selector + |> Maybe.withDefault emptyEventOwnerSelector in defaultValues |> setValue FieldName eventType.name @@ -132,6 +143,9 @@ loadValues eventType = |> setValue FieldSchema eventType.schema.schema |> setValue FieldRetentionTime retentionTime |> maybeSetValue FieldAudience eventType.audience + |> setValue FieldEventOwnerSelectorType ownerField.type_ + |> setValue FieldEventOwnerSelectorName ownerField.name + |> setValue FieldEventOwnerSelectorValue ownerField.value |> setValue FieldCleanupPolicy eventType.cleanup_policy diff --git a/client/Pages/EventTypeCreate/Update.elm b/client/Pages/EventTypeCreate/Update.elm index 48156e7..5fab513 100644 --- a/client/Pages/EventTypeCreate/Update.elm +++ b/client/Pages/EventTypeCreate/Update.elm @@ -372,10 +372,34 @@ submitCreate model = |> String.trim |> Json.string + isEmptyString field = + model.values + |> getValue field + |> String.trim + |> String.isEmpty + auth = AccessEditor.unflatten model.accessEditor.authorization |> Stores.Authorization.encoder + event_owner_selector = + if + isEmptyString FieldEventOwnerSelectorName + && isEmptyString FieldEventOwnerSelectorValue + && isEmptyString FieldEventOwnerSelectorType + then + [] + + else + [ ( "event_owner_selector" + , Json.object + [ ( "type", asString FieldEventOwnerSelectorType ) + , ( "name", asString FieldEventOwnerSelectorName ) + , ( "value", asString FieldEventOwnerSelectorValue ) + ] + ) + ] + fields = [ ( "name", asString FieldName ) , ( "owning_application", asString FieldOwningApplication ) @@ -419,7 +443,7 @@ submitCreate model = ] body = - Json.object (List.concat [ fields, enrichment ]) + Json.object (List.concat [ fields, enrichment, event_owner_selector ]) in post body @@ -457,10 +481,34 @@ submitUpdate model = |> String.trim |> Json.string + isEmptyString field = + model.values + |> getValue field + |> String.trim + |> String.isEmpty + auth = AccessEditor.unflatten model.accessEditor.authorization |> Stores.Authorization.encoder + event_owner_selector = + if + isEmptyString FieldEventOwnerSelectorName + && isEmptyString FieldEventOwnerSelectorValue + && isEmptyString FieldEventOwnerSelectorType + then + [] + + else + [ ( "event_owner_selector" + , Json.object + [ ( "type", asString FieldEventOwnerSelectorType ) + , ( "name", asString FieldEventOwnerSelectorName ) + , ( "value", asString FieldEventOwnerSelectorValue ) + ] + ) + ] + fields = [ ( "name", asString FieldName ) , ( "owning_application", asString FieldOwningApplication ) @@ -496,7 +544,7 @@ submitUpdate model = ] body = - Json.object (List.concat [ fields, enrichment ]) + Json.object (List.concat [ fields, enrichment, event_owner_selector ]) in put body (getValue FieldName model.values) diff --git a/client/Pages/EventTypeCreate/View.elm b/client/Pages/EventTypeCreate/View.elm index 627565d..d656f50 100644 --- a/client/Pages/EventTypeCreate/View.elm +++ b/client/Pages/EventTypeCreate/View.elm @@ -22,6 +22,7 @@ import Stores.EventType , allCategories , allCleanupPolicies , allModes + , allOwnerSelectorTypes , categories , cleanupPolicies , compatibilityModes @@ -265,6 +266,41 @@ viewForm model setup = Required Enabled ("" :: allAudiences) + , div [ class "dc-row form-create__input-row" ] + [ selectInput formModel + FieldEventOwnerSelectorType + OnInput + "Event Owner Selector Type" + "" + Help.eventOwnerSelector + Optional + Enabled + ("" :: allOwnerSelectorTypes) + , div + [ class "dc-column" ] + [ textInput formModel + FieldEventOwnerSelectorName + OnInput + "Event Owner Selector Name" + "Example: retailer_id" + "" + Help.eventOwnerSelector + Optional + Enabled + ] + , div + [ class "dc-column" ] + [ textInput formModel + FieldEventOwnerSelectorValue + OnInput + "Event Owner Selector Value" + "Example: security.owners" + "" + Help.eventOwnerSelector + Optional + Enabled + ] + ] , selectInput formModel FieldCleanupPolicy OnInput diff --git a/client/Pages/EventTypeDetails/Help.elm b/client/Pages/EventTypeDetails/Help.elm index d8cbdab..62179a1 100644 --- a/client/Pages/EventTypeDetails/Help.elm +++ b/client/Pages/EventTypeDetails/Help.elm @@ -1,4 +1,4 @@ -module Pages.EventTypeDetails.Help exposing (audience, authorization, category, cleanupPolicy, cleanupPolicyCompact, compatibilityMode, consumers, consumingQueries, createdAt, defaultStatistic, enrichmentStrategies, envelope, eventType, options, orderingKeyFields, owningApplication, partitionCompactionKeyField, partitionKeyFields, partitionStrategy, partitions, publishers, schema, subscription, updatedAt) +module Pages.EventTypeDetails.Help exposing (audience, authorization, category, cleanupPolicy, cleanupPolicyCompact, compatibilityMode, consumers, consumingQueries, createdAt, defaultStatistic, enrichmentStrategies, envelope, eventOwnerSelector, eventType, options, orderingKeyFields, owningApplication, partitionCompactionKeyField, partitionKeyFields, partitionStrategy, partitions, publishers, schema, subscription, updatedAt) import Config exposing (appPreffix) import Helpers.UI exposing (..) @@ -414,6 +414,41 @@ audience = ] +eventOwnerSelector : List (Html msg) +eventOwnerSelector = + [ text "Event Owner Selector for per-event authorization. " + , text "Can be used to point to a string field in the event, which " + , text "is used by Nakadi do decide if an authorized consumer " + , text "can read a published event. It is optional and " + , text "if not specified or field is not present/null, all " + , text "authorized consumers can read the event." + , newline + , bold "The event_owner_selector must contain the following fields:" + , newline + , text "- " + , mono "type" + , text " Specifies the type of the selector (can be 'path' or 'static')" + , newline + , text "- " + , mono "name" + , text " Informational field specifying what type of data the field" + , text " represents (eg: team/retailers, etc)" + , newline + , text "- " + , mono "value" + , text " Static value or value in dot notation pointing to a string field" + , text " in an event which will be used to" + , text " classify if the consumer is allowed to read the event." + , newline + , newline + , bold "Key: " + , mono "event_owner_selector" + , bold "optional" + , newline + , man "#definition_EventOwnerSelector" + ] + + cleanupPolicy : List (Html msg) cleanupPolicy = [ text "Event type cleanup policy." diff --git a/client/Pages/EventTypeDetails/View.elm b/client/Pages/EventTypeDetails/View.elm index 2d24423..cec4187 100644 --- a/client/Pages/EventTypeDetails/View.elm +++ b/client/Pages/EventTypeDetails/View.elm @@ -28,7 +28,8 @@ import Stores.ConsumingQuery exposing (ConsumingQuery) import Stores.CursorDistance import Stores.EventType exposing - ( EventType + ( EventOwnerSelector + , EventType , EventTypeOptions , EventTypeStatistics , cleanupPolicies @@ -198,6 +199,8 @@ detailsLayout typeName eventType model = none , infoField "Audience " Help.audience TopRight <| infoStringToText eventType.audience + , infoField "Event Owner Selector " Help.eventOwnerSelector TopRight <| + infoEventOwnerSelectorToText eventType.event_owner_selector , infoField "Created " Help.createdAt TopRight <| infoDateToText eventType.created_at , infoField "Updated " Help.updatedAt TopRight <| @@ -380,6 +383,20 @@ infoStatisticsToText maybeStatistics = infoEmpty +infoEventOwnerSelectorToText : Maybe EventOwnerSelector -> Html Msg +infoEventOwnerSelectorToText maybeEventOwnerSelector = + case maybeEventOwnerSelector of + Just owner_selector -> + div [] + [ infoSubField "Type: " owner_selector.type_ + , infoSubField "Name: " owner_selector.name + , infoSubField "Value: " owner_selector.value + ] + + Nothing -> + infoEmpty + + schemaTab : JsonEditor.Model -> Stores.EventTypeSchema.Model diff --git a/client/Stores/EventType.elm b/client/Stores/EventType.elm index df44027..e5ddf67 100644 --- a/client/Stores/EventType.elm +++ b/client/Stores/EventType.elm @@ -1,4 +1,4 @@ -module Stores.EventType exposing (EventType, EventTypeOptions, EventTypeStatistics, Model, Msg, allAudiences, allCategories, allCleanupPolicies, allModes, audiences, categories, cleanupPolicies, collectionDecoder, compatibilityModes, config, defaultStatisticDecoder, initialModel, memberDecoder, optionsDecoder, partitionStrategies, update) +module Stores.EventType exposing (EventOwnerSelector, EventType, EventTypeOptions, EventTypeStatistics, Model, Msg, allAudiences, allCategories, allCleanupPolicies, allModes, allOwnerSelectorTypes, audiences, categories, cleanupPolicies, collectionDecoder, compatibilityModes, config, defaultStatisticDecoder, emptyEventOwnerSelector, initialModel, memberDecoder, optionsDecoder, partitionStrategies, update) import Config import Constants @@ -32,6 +32,7 @@ type alias EventType = , --enum component-internal, business-unit-internal, -- company-internal, external-partner, external-public audience : Maybe String + , event_owner_selector : Maybe EventOwnerSelector , created_at : Maybe String , updated_at : Maybe String } @@ -50,6 +51,37 @@ type alias EventTypeOptions = } +type alias EventOwnerSelector = + { type_ : String + , name : String + , value : String + } + + +emptyEventOwnerSelector = + { type_ = "" + , name = "" + , value = "" + } + + +ownerSelectorTypes : + { path : String + , static : String + } +ownerSelectorTypes = + { path = "path" + , static = "static" + } + + +allOwnerSelectorTypes : List String +allOwnerSelectorTypes = + [ ownerSelectorTypes.path + , ownerSelectorTypes.static + ] + + type alias Model = Helpers.Store.Model EventType @@ -198,6 +230,7 @@ memberDecoder = |> optional "authorization" (nullable Stores.Authorization.collectionDecoder) Nothing |> optional "cleanup_policy" string cleanupPolicies.delete |> optional "audience" (nullable string) Nothing + |> optional "event_owner_selector" (nullable eventOwnerSelectorDecoder) Nothing |> optional "created_at" (nullable string) Nothing |> optional "updated_at" (nullable string) Nothing @@ -215,3 +248,11 @@ optionsDecoder : Decoder EventTypeOptions optionsDecoder = succeed EventTypeOptions |> optional "retention_time" (nullable int) Nothing + + +eventOwnerSelectorDecoder : Decoder EventOwnerSelector +eventOwnerSelectorDecoder = + succeed EventOwnerSelector + |> required "type" string + |> required "name" string + |> required "value" string