package api import ( "context" "errors" "fmt" "dev.azure.com/schwarzit/schwarzit.stackit-core-platform/common-audit.git/audit/messaging" auditV1 "dev.azure.com/schwarzit/schwarzit.stackit-core-platform/common-audit.git/gen/go/audit/v1" ) // routablePayload implements SerializedPayload. type routablePayload struct { payload []byte contentType string } // GetPayload implements SerializedPayload.GetPayload. func (p *routablePayload) GetPayload() []byte { return p.payload } // GetContentType implements SerializedPayload.GetContentType. func (p *routablePayload) GetContentType() string { return p.contentType } // routableTopicNameResolver implements TopicNameResolver. // Resolves topic names by concatenating topic type prefixes with routing identifiers. type routableTopicNameResolver struct { organizationTopicPrefix string ProjectTopicPrefix string // If no identifier is provided for routing, it will be routed to a system topic systemTopicName string } // Resolve implements TopicNameResolver.Resolve. func (r *routableTopicNameResolver) Resolve(routingIdentifier *RoutingIdentifier) (string, error) { if routingIdentifier == nil { return r.systemTopicName, nil } switch routingIdentifier.Type { case RoutingIdentifierTypeOrganization: return fmt.Sprintf("topic://%s/%s", r.organizationTopicPrefix, routingIdentifier.Identifier), nil case RoutingIdentifierTypeProject: return fmt.Sprintf("topic://%s/%s", r.ProjectTopicPrefix, routingIdentifier.Identifier), nil default: return "", ErrUnsupportedObjectIdentifierType } } // topicNameConfig provides topic name information required for the topic name resolution. type topicNameConfig struct { OrganizationTopicPrefix string ProjectTopicPrefix string SystemTopicName string } // routableAuditApi is an implementation of AuditApi. // Warning: It is only there for local (compatibility) testing. // DO NOT USE IT! type routableAuditApi struct { messagingApi *messaging.MessagingApi topicNameResolver *TopicNameResolver validator *ProtobufValidator } // NewRoutableAuditApi can be used to initialize the audit log api. func newRoutableAuditApi( messagingApi *messaging.MessagingApi, topicNameConfig topicNameConfig, validator ProtobufValidator, ) (*AuditApi, error) { if messagingApi == nil { return nil, errors.New("messaging api nil") } // Topic resolver var topicNameResolver TopicNameResolver = &routableTopicNameResolver{ organizationTopicPrefix: topicNameConfig.OrganizationTopicPrefix, ProjectTopicPrefix: topicNameConfig.ProjectTopicPrefix, systemTopicName: topicNameConfig.SystemTopicName, } // Audit api var auditApi AuditApi = &routableAuditApi{ messagingApi: messagingApi, topicNameResolver: &topicNameResolver, validator: &validator, } return &auditApi, nil } // Log implements AuditApi.Log func (a *routableAuditApi) Log( ctx context.Context, event *auditV1.AuditEvent, visibility auditV1.Visibility, routingIdentifier *RoutingIdentifier, objectIdentifier *auditV1.ObjectIdentifier, ) error { serializedPayload, err := a.ValidateAndSerialize(event, visibility, routingIdentifier, objectIdentifier) if err != nil { return err } return a.Send(ctx, routingIdentifier, &serializedPayload) } // ValidateAndSerialize implements AuditApi.ValidateAndSerialize func (a *routableAuditApi) ValidateAndSerialize( event *auditV1.AuditEvent, visibility auditV1.Visibility, routingIdentifier *RoutingIdentifier, objectIdentifier *auditV1.ObjectIdentifier, ) (SerializedPayload, error) { routableEvent, err := validateAndSerializePartially( a.validator, event, visibility, routingIdentifier, objectIdentifier) if err != nil { return nil, err } return serializeToProtobufMessage(routableEvent) } // Send implements AuditApi.Send func (a *routableAuditApi) Send( ctx context.Context, routingIdentifier *RoutingIdentifier, serializedPayload *SerializedPayload, ) error { return send(a.topicNameResolver, a.messagingApi, ctx, routingIdentifier, serializedPayload) }