Skip to content

Commit

Permalink
Add basic struture to support subscription auto-verification
Browse files Browse the repository at this point in the history
  • Loading branch information
ayeshLK committed Feb 17, 2025
1 parent c6188a0 commit 3ac34d9
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 44 deletions.
2 changes: 2 additions & 0 deletions ballerina/commons.bal
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ const int LISTENER_DETACH_ERROR = -4;
const int LISTENER_STOP_ERROR = -5;
const int CLIENT_INIT_ERROR = -10;

const DEFAULT_HUB_LEASE_SECONDS = 86400;

# Options to compress using Gzip or deflate.
#
# `AUTO`: When service behaves as a HTTP gateway inbound request/response accept-encoding option is set as the
Expand Down
9 changes: 5 additions & 4 deletions ballerina/http_service.bal
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@ isolated service class HttpService {
private final int defaultLeaseSeconds;
private final SubscriptionHandler subscriptionHandler;

isolated function init(HttpToWebsubhubAdaptor adaptor, string hubUrl, int leaseSeconds,
*ClientConfiguration clientConfig) {
isolated function init(HttpToWebsubhubAdaptor adaptor, string hubUrl, ServiceConfiguration? serviceConfig) {
self.adaptor = adaptor;
self.hub = hubUrl;
self.defaultLeaseSeconds = leaseSeconds;
self.subscriptionHandler = new (adaptor, clientConfig);
self.defaultLeaseSeconds = serviceConfig?.leaseSeconds ?: DEFAULT_HUB_LEASE_SECONDS;
ClientConfiguration clientConfig = serviceConfig?.webHookConfig ?: {};
boolean autoVerifySubscription = serviceConfig?.autoVerifySubscription ?: false;
self.subscriptionHandler = new (adaptor, autoVerifySubscription, clientConfig);
}

isolated resource function post .(http:Caller caller, http:Request request, http:Headers headers) returns Error? {
Expand Down
9 changes: 7 additions & 2 deletions ballerina/hub_controller.bal
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,17 @@
// todo: implement this properly

public isolated class Controller {
private final boolean autoVerifySubscription;

public function markAsVerified(Subscription|Unsubscription subscription) returns error? {
isolated function init(boolean autoVerifySubscription) {
self.autoVerifySubscription = autoVerifySubscription;
}

public isolated function markAsVerified(Subscription|Unsubscription subscription) returns error? {
return error("Not implemented yet");
}

function skipSubscriptionVerification(Subscription|Unsubscription subscription) returns boolean {
isolated function skipSubscriptionVerification(Subscription|Unsubscription subscription) returns boolean {
return false;
}
}
20 changes: 4 additions & 16 deletions ballerina/hub_listener.bal
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import ballerina/log;

# Represents a Service listener endpoint.
public class Listener {
private final int defaultHubLeaseSeconds = 864000;
private http:Listener httpListener;
private http:InferredListenerConfiguration listenerConfig;
private int port;
Expand Down Expand Up @@ -65,18 +64,9 @@ public class Listener {

string hubUrl = self.retrieveHubUrl(name);
ServiceConfiguration? configuration = retrieveServiceAnnotations('service);
HttpToWebsubhubAdaptor adaptor = new('service);
if configuration is ServiceConfiguration {
int leaseSeconds = configuration?.leaseSeconds is int ? <int>(configuration?.leaseSeconds) : self.defaultHubLeaseSeconds;
if configuration?.webHookConfig is ClientConfiguration {
self.httpService = new(adaptor, hubUrl, leaseSeconds, <ClientConfiguration>(configuration?.webHookConfig));
} else {
self.httpService = new(adaptor, hubUrl, leaseSeconds);
}
} else {
self.httpService = new(adaptor, hubUrl, self.defaultHubLeaseSeconds);
}
error? result = self.httpListener.attach(<HttpService> self.httpService, name);
HttpToWebsubhubAdaptor adaptor = new ('service);
self.httpService = new (adaptor, hubUrl, configuration);
error? result = self.httpListener.attach(<HttpService>self.httpService, name);
if (result is error) {
return error Error("Error occurred while attaching the service", result, statusCode = LISTENER_ATTACH_ERROR);
}
Expand All @@ -92,9 +82,7 @@ public class Listener {
isolated function retrieveHubUrl(string[]|string? servicePath) returns string {
string host = self.listenerConfig.host;
string protocol = self.listenerConfig.secureSocket is () ? "http" : "https";

string concatenatedServicePath = "";

string concatenatedServicePath = "";
if servicePath is string {
concatenatedServicePath += "/" + <string>servicePath;
} else if servicePath is string[] {
Expand Down
53 changes: 31 additions & 22 deletions ballerina/subscription.bal
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,18 @@ import ballerina/uuid;

isolated class SubscriptionHandler {
private final HttpToWebsubhubAdaptor adaptor;
private final Controller hubController;
private final readonly & ClientConfiguration clientConfig;

private final boolean isOnSubscriptionAvailable;
private final boolean isOnSubscriptionValidationAvailable;
private final boolean isOnUnsubscriptionAvailable;
private final boolean isOnUnsubscriptionValidationAvailable;

isolated function init(HttpToWebsubhubAdaptor adaptor, *ClientConfiguration clientConfig) {
isolated function init(HttpToWebsubhubAdaptor adaptor, boolean autoVerifySubscription,
ClientConfiguration clientConfig) {
self.adaptor = adaptor;
self.hubController = new (autoVerifySubscription);
self.clientConfig = clientConfig.cloneReadOnly();
string[] methodNames = adaptor.getServiceMethodNames();
self.isOnSubscriptionAvailable = methodNames.indexOf("onSubscription") is int;
Expand Down Expand Up @@ -63,17 +66,20 @@ isolated class SubscriptionHandler {
return;
}

string challenge = uuid:createType4AsString();
[string, string?][] params = [
[HUB_MODE, MODE_SUBSCRIBE],
[HUB_TOPIC, message.hubTopic],
[HUB_CHALLENGE, challenge],
[HUB_LEASE_SECONDS, message.hubLeaseSeconds]
];
http:Response subscriberResponse = check sendNotification(message.hubCallback, params, self.clientConfig);
string responsePayload = check subscriberResponse.getTextPayload();
if challenge != responsePayload {
return;
boolean skipIntentVerification = self.hubController.skipSubscriptionVerification(message);
if !skipIntentVerification {
string challenge = uuid:createType4AsString();
[string, string?][] params = [
[HUB_MODE, MODE_SUBSCRIBE],
[HUB_TOPIC, message.hubTopic],
[HUB_CHALLENGE, challenge],
[HUB_LEASE_SECONDS, message.hubLeaseSeconds]
];
http:Response subscriberResponse = check sendNotification(message.hubCallback, params, self.clientConfig);
string responsePayload = check subscriberResponse.getTextPayload();
if challenge != responsePayload {
return;
}
}

VerifiedSubscription verifiedSubscription = {
Expand Down Expand Up @@ -115,16 +121,19 @@ isolated class SubscriptionHandler {
_ = check sendNotification(message.hubCallback, params, self.clientConfig);
}

string challenge = uuid:createType4AsString();
[string, string?][] params = [
[HUB_MODE, MODE_UNSUBSCRIBE],
[HUB_TOPIC, message.hubTopic],
[HUB_CHALLENGE, challenge]
];
http:Response subscriberResponse = check sendNotification(message.hubCallback, params, self.clientConfig);
string responsePayload = check subscriberResponse.getTextPayload();
if challenge != responsePayload {
return;
boolean skipIntentVerification = self.hubController.skipSubscriptionVerification(message);
if !skipIntentVerification {
string challenge = uuid:createType4AsString();
[string, string?][] params = [
[HUB_MODE, MODE_UNSUBSCRIBE],
[HUB_TOPIC, message.hubTopic],
[HUB_CHALLENGE, challenge]
];
http:Response subscriberResponse = check sendNotification(message.hubCallback, params, self.clientConfig);
string responsePayload = check subscriberResponse.getTextPayload();
if challenge != responsePayload {
return;
}
}

VerifiedUnsubscription verifiedUnsubscription = {
Expand Down

0 comments on commit 3ac34d9

Please sign in to comment.