diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml
index 8dd41a223..9c4cd986d 100644
--- a/.github/workflows/run-tests.yml
+++ b/.github/workflows/run-tests.yml
@@ -51,6 +51,9 @@ jobs:
PN_PAM_PUB_KEY: ${{ secrets.SDK_PAM_PUB_KEY }}
PN_PAM_SUB_KEY: ${{ secrets.SDK_PAM_SUB_KEY }}
PN_PAM_SEC_KEY: ${{ secrets.SDK_PAM_SEC_KEY }}
+ PN_CAT_PUB_KEY: ${{ secrets.SDK_CAT_PUB_KEY }}
+ PN_CAT_SUB_KEY: ${{ secrets.SDK_CAT_SUB_KEY }}
+ PN_CAT_SEC_KEY: ${{ secrets.SDK_CAT_SEC_KEY }}
run: dotnet test .\\src\\UnitTests\\PubnubApiPCL.Tests\\PubnubApiPCL.Tests.csproj --verbosity normal --logger "console;verbosity=detailed"
- name: Cancel workflow runs for commit on error
if: failure()
diff --git a/.pubnub.yml b/.pubnub.yml
index 1f63858c1..28688e124 100644
--- a/.pubnub.yml
+++ b/.pubnub.yml
@@ -1,8 +1,15 @@
name: c-sharp
-version: "9.0.0"
+version: "9.1.0"
schema: 1
scm: github.com/pubnub/c-sharp
changelog:
+ - date: 2026-10-13
+ version: v9.1.0
+ changes:
+ - type: feature
+ text: "Categories permission support for Grant and GrantToken apis."
+ - type: bug
+ text: "Ensure unsubscribeAll clears subscription state when event engine is enabled."
- date: 2026-09-08
version: v9.0.0
changes:
@@ -1058,14 +1065,14 @@ features:
- QUERY-PARAM
supported-platforms:
-
- version: Pubnub 'C#' 9.0.0
+ version: Pubnub 'C#' 9.1.0
platforms:
- Windows 10 and up
- Windows Server 2008 and up
frameworks:
- .Net Framework 4.5+
-
- version: PubnubPCL 'C#' 9.0.0
+ version: PubnubPCL 'C#' 9.1.0
platforms:
- Xamarin.Android
- Xamarin.iOS
@@ -1077,7 +1084,7 @@ supported-platforms:
frameworks:
- .Net 4.5+
-
- version: PubnubUWP 'C#' 9.0.0
+ version: PubnubUWP 'C#' 9.1.0
platforms:
- Windows Phone 10
- Universal Windows Apps
@@ -1101,7 +1108,7 @@ sdks:
distribution-type: source
distribution-repository: GitHub
package-name: Pubnub
- location: https://github.com/pubnub/c-sharp/releases/tag/v9.0.0
+ location: https://github.com/pubnub/c-sharp/releases/tag/v9.1.0
requires:
-
name: ".Net"
@@ -1342,7 +1349,7 @@ sdks:
distribution-type: source
distribution-repository: GitHub
package-name: PubNubPCL
- location: https://github.com/pubnub/c-sharp/releases/tag/v9.0.0
+ location: https://github.com/pubnub/c-sharp/releases/tag/v9.1.0
requires:
-
name: ".Net"
@@ -1693,7 +1700,7 @@ sdks:
distribution-type: source
distribution-repository: GitHub
package-name: PubnubUWP
- location: https://github.com/pubnub/c-sharp/releases/tag/v9.0.0
+ location: https://github.com/pubnub/c-sharp/releases/tag/v9.1.0
requires:
-
name: "Universal Windows Platform Development"
diff --git a/CHANGELOG b/CHANGELOG
index 8e6d3ec22..003b0e5a3 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,9 @@
+v9.1.0 - October 13 2026
+-----------------------------
+- Added: categories permission support for Grant and GrantToken apis.
+
+- Fixed: ensure unsubscribeAll clears subscription state when event engine is enabled.
+
v9.0.0 - September 08 2026
-----------------------------
- Added: added Data Sync feature support.
diff --git a/src/Api/PubnubApi/EndPoint/Access/GrantOperation.cs b/src/Api/PubnubApi/EndPoint/Access/GrantOperation.cs
index 535e99dfe..a2b61eca3 100644
--- a/src/Api/PubnubApi/EndPoint/Access/GrantOperation.cs
+++ b/src/Api/PubnubApi/EndPoint/Access/GrantOperation.cs
@@ -16,6 +16,7 @@ public class GrantOperation : PubnubCoreBase
private string[] pubnubChannelNames;
private string[] pubnubChannelGroupNames;
private string[] pubnubTargetUuids;
+ private PNGrantCategory[] pubnubCategories;
private string[] pamAuthenticationKeys;
private bool grantWrite;
private bool grantRead;
@@ -53,6 +54,16 @@ public GrantOperation Uuids(string[] targetUuids)
return this;
}
+ ///
+ /// App Context categories whose metadata the auth keys may list in full.
+ /// Requires AuthKeys and accepts only the Get permission: Get(true) grants, Get(false) revokes.
+ ///
+ public GrantOperation Categories(PNGrantCategory[] categories)
+ {
+ pubnubCategories = categories;
+ return this;
+ }
+
public GrantOperation AuthKeys(string[] authKeys)
{
pamAuthenticationKeys = authKeys;
@@ -129,6 +140,7 @@ public void Execute(PNCallback callback)
{
throw new InvalidOperationException("Only Get/Update/Delete permissions are allowed for UUID");
}
+ ValidateCategories();
savedCallback = callback;
GrantAccess(callback);
}
@@ -143,6 +155,7 @@ public async Task> ExecuteAsync()
{
throw new InvalidOperationException("Only Get/Update/Delete permissions are allowed for UUID");
}
+ ValidateCategories();
return await GrantAccess().ConfigureAwait(false);
}
@@ -151,6 +164,39 @@ internal void Retry()
GrantAccess(savedCallback);
}
+ private void ValidateCategories()
+ {
+ if (pubnubCategories == null || pubnubCategories.Length == 0)
+ {
+ return;
+ }
+ if (pubnubCategories.Any(category => !Enum.IsDefined(typeof(PNGrantCategory), category)))
+ {
+ throw new InvalidOperationException("Only Channels and Uuids categories are supported");
+ }
+ if (pamAuthenticationKeys == null || !pamAuthenticationKeys.Any(auth => !string.IsNullOrEmpty(auth) && auth.Trim().Length > 0))
+ {
+ throw new InvalidOperationException("Category grants require at least one auth key");
+ }
+ if (grantRead || grantWrite || grantManage || grantDelete || grantUpdate || grantJoin)
+ {
+ throw new InvalidOperationException("Only Get permission is allowed for categories");
+ }
+ }
+
+ private static string GetCategoryQueryValue(PNGrantCategory category)
+ {
+ switch (category)
+ {
+ case PNGrantCategory.Channels:
+ return "channels";
+ case PNGrantCategory.Uuids:
+ return "uuids";
+ default:
+ throw new InvalidOperationException("Only Channels and Uuids categories are supported");
+ }
+ }
+
internal void GrantAccess(PNCallback callback)
{
if (string.IsNullOrEmpty(config.SecretKey) || string.IsNullOrEmpty(config.SecretKey.Trim()) || config.SecretKey.Length <= 0)
@@ -161,6 +207,7 @@ internal void GrantAccess(PNCallback callback)
"channels", pubnubChannelNames,
"channelGroups", pubnubChannelGroupNames,
"uuids", pubnubTargetUuids,
+ "categories", pubnubCategories,
"authKeys", pamAuthenticationKeys,
"read", grantRead,
"write", grantWrite,
@@ -212,6 +259,7 @@ internal async Task> GrantAccess()
"channels", pubnubChannelNames,
"channelGroups", pubnubChannelGroupNames,
"uuids", pubnubTargetUuids,
+ "categories", pubnubCategories,
"authKeys", pamAuthenticationKeys,
"read", grantRead,
"write", grantWrite,
@@ -277,6 +325,7 @@ private RequestParameter CreateRequestParameter()
List channelList = new List();
List channelGroupList = new List();
List uuidList = new List();
+ List categoryList = new List();
List authList = new List();
if (pubnubChannelNames != null && pubnubChannelNames.Length > 0)
@@ -297,6 +346,11 @@ private RequestParameter CreateRequestParameter()
uuidList = uuidList.Where(uuid => !string.IsNullOrEmpty(uuid) && uuid.Trim().Length > 0).Distinct().ToList();
}
+ if (pubnubCategories != null && pubnubCategories.Length > 0)
+ {
+ categoryList = pubnubCategories.Select(GetCategoryQueryValue).Distinct().ToList();
+ }
+
if (pamAuthenticationKeys != null && pamAuthenticationKeys.Length > 0)
{
authList = new List(pamAuthenticationKeys);
@@ -306,6 +360,7 @@ private RequestParameter CreateRequestParameter()
string channelsCommaDelimited = string.Join(",", channelList.OrderBy(x => x).ToArray());
string channelGroupsCommaDelimited = string.Join(",", channelGroupList.OrderBy(x => x).ToArray());
string targetUuidsCommaDelimited = string.Join(",", uuidList.OrderBy(x => x).ToArray());
+ string categoriesCommaDelimited = string.Join(",", categoryList.OrderBy(x => x).ToArray());
string authKeysCommaDelimited = string.Join(",", authList.OrderBy(x => x).ToArray());
List pathSegments = new List() {
@@ -338,6 +393,11 @@ private RequestParameter CreateRequestParameter()
requestQueryStringParams.Add("target-uuid", UriUtil.EncodeUriComponent(targetUuidsCommaDelimited, PNOperationType.PNAccessManagerGrant, false, false, false));
}
+ if (!string.IsNullOrEmpty(categoriesCommaDelimited))
+ {
+ requestQueryStringParams.Add("category", UriUtil.EncodeUriComponent(categoriesCommaDelimited, PNOperationType.PNAccessManagerGrant, false, false, false));
+ }
+
if (grantTTL > -1)
{
requestQueryStringParams.Add("ttl", grantTTL.ToString(CultureInfo.InvariantCulture));
diff --git a/src/Api/PubnubApi/EndPoint/Access/GrantTokenOperation.cs b/src/Api/PubnubApi/EndPoint/Access/GrantTokenOperation.cs
index b2efcc99e..d88e90858 100644
--- a/src/Api/PubnubApi/EndPoint/Access/GrantTokenOperation.cs
+++ b/src/Api/PubnubApi/EndPoint/Access/GrantTokenOperation.cs
@@ -44,6 +44,7 @@ public class GrantTokenOperation : PubnubCoreBase
private string pubnubAuthorizedUuid = string.Empty;
private string pubnubAuthorizedUserId = string.Empty;
private PNDataSyncProjections pubnubDataSyncProjections;
+ private PNTokenCategories pubnubCategories;
public GrantTokenOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, EndPoint.TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, tokenManager, instance)
{
@@ -135,6 +136,16 @@ public GrantTokenOperation Patterns(PNTokenPatterns patterns)
return this;
}
+ ///
+ /// Category-level App Context permissions, e.g. listing all channel or uuid metadata.
+ /// Resource-level or pattern Get permissions do not imply them.
+ ///
+ public GrantTokenOperation Categories(PNTokenCategories categories)
+ {
+ this.pubnubCategories = categories;
+ return this;
+ }
+
///
/// Assigns Data Sync projections to resources/patterns. The projection name
/// per resource is encoded into the token's meta "pn-projections" section.
@@ -167,6 +178,7 @@ public GrantTokenOperation QueryParam(Dictionary customQueryPara
public void Execute(PNCallback callback)
{
logger?.Trace($"{GetType().Name} Execute invoked");
+ savedCallbackGrantToken = callback;
GrantAccess(callback);
}
@@ -194,6 +206,7 @@ internal void GrantAccess(PNCallback callback)
logger?.Debug(() => $"{GetType().Name} " + PubnubLogFormatter.Parameters("GrantToken",
"resources", pubnubResources,
"patterns", pubnubPatterns,
+ "categories", BuildCategoryPermissions(),
"ttl", grantTTL,
"authorizedUuid", pubnubAuthorizedUuid,
"authorizedUserId", pubnubAuthorizedUserId,
@@ -275,6 +288,21 @@ private bool AddDataSyncScope(Dictionary collection, string key,
return atleastOnePermission;
}
+ private Dictionary BuildCategoryPermissions()
+ {
+ Dictionary categories = new Dictionary();
+ if (this.pubnubCategories == null) {
+ return categories;
+ }
+ if (this.pubnubCategories.Channels != null && this.pubnubCategories.Channels.Get) {
+ categories.Add("channels", (int)GrantBitFlag.GET);
+ }
+ if (this.pubnubCategories.Uuids != null && this.pubnubCategories.Uuids.Get) {
+ categories.Add("uuids", (int)GrantBitFlag.GET);
+ }
+ return categories;
+ }
+
private Dictionary BuildProjectionsMeta()
{
if (this.pubnubDataSyncProjections == null) {
@@ -332,6 +360,7 @@ internal async Task> GrantAccess()
logger?.Debug(() => $"{GetType().Name} " + PubnubLogFormatter.Parameters("GrantToken",
"resources", pubnubResources,
"patterns", pubnubPatterns,
+ "categories", BuildCategoryPermissions(),
"ttl", grantTTL,
"authorizedUuid", pubnubAuthorizedUuid,
"authorizedUserId", pubnubAuthorizedUserId,
@@ -483,8 +512,13 @@ private RequestParameter CreateRequestParameter()
atleastOnePermission = AddDataSyncScopes(resourcesCollection, this.pubnubResources.DataSync, atleastOnePermission);
atleastOnePermission = AddDataSyncScopes(patternsCollection, this.pubnubPatterns.DataSync, atleastOnePermission);
+ Dictionary categoryBitmaskPermCollection = BuildCategoryPermissions();
+ if (categoryBitmaskPermCollection.Count > 0) {
+ atleastOnePermission = true;
+ }
+
if (!atleastOnePermission) {
- config?.Logger?.Warn("GrantToken At least one permission is needed for at least one or more of uuids/users, channels/spaces, groups or datasync entities/relationships/memberships");
+ config?.Logger?.Warn("GrantToken At least one permission is needed for at least one or more of uuids/users, channels/spaces, groups, categories or datasync entities/relationships/memberships");
}
Dictionary optimizedMeta = new Dictionary();
@@ -503,6 +537,9 @@ private RequestParameter CreateRequestParameter()
{ "patterns", patternsCollection },
{ "meta", optimizedMeta }
};
+ if (categoryBitmaskPermCollection.Count > 0) {
+ permissionCollection.Add("categories", categoryBitmaskPermCollection);
+ }
if (!string.IsNullOrEmpty(this.pubnubAuthorizedUuid) && this.pubnubAuthorizedUuid.Trim().Length > 0) {
permissionCollection.Add("uuid", this.pubnubAuthorizedUuid);
} else if (!string.IsNullOrEmpty(this.pubnubAuthorizedUserId) && this.pubnubAuthorizedUserId.Trim().Length > 0) {
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/Channel/CreateChannelParameters.cs b/src/Api/PubnubApi/EndPoint/DataSync/Channel/CreateChannelParameters.cs
index 638d6ce58..69d82a3c6 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/Channel/CreateChannelParameters.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/Channel/CreateChannelParameters.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
-namespace PubnubApi.EndPoint
+namespace PubnubApi
{
public class CreateChannelParameters
{
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/Channel/DeleteChannelParameters.cs b/src/Api/PubnubApi/EndPoint/DataSync/Channel/DeleteChannelParameters.cs
index dc3d6d918..176d89c6d 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/Channel/DeleteChannelParameters.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/Channel/DeleteChannelParameters.cs
@@ -1,4 +1,4 @@
-namespace PubnubApi.EndPoint
+namespace PubnubApi
{
public class DeleteChannelParameters
{
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/Channel/GetChannelParameters.cs b/src/Api/PubnubApi/EndPoint/DataSync/Channel/GetChannelParameters.cs
index 02b016b1a..1721f9972 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/Channel/GetChannelParameters.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/Channel/GetChannelParameters.cs
@@ -1,4 +1,4 @@
-namespace PubnubApi.EndPoint
+namespace PubnubApi
{
public class GetChannelParameters
{
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/Channel/GetChannelsParameters.cs b/src/Api/PubnubApi/EndPoint/DataSync/Channel/GetChannelsParameters.cs
index 0fc648c96..d69db0ca5 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/Channel/GetChannelsParameters.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/Channel/GetChannelsParameters.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
-namespace PubnubApi.EndPoint
+namespace PubnubApi
{
public class GetChannelsParameters
{
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/Channel/PNDataSyncChannelResult.cs b/src/Api/PubnubApi/EndPoint/DataSync/Channel/PNDataSyncChannelResult.cs
index 9828b6ad9..493291c7a 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/Channel/PNDataSyncChannelResult.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/Channel/PNDataSyncChannelResult.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
-namespace PubnubApi.EndPoint;
+namespace PubnubApi;
public class PNDataSyncChannelResult
{
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/Channel/PNDataSyncDeleteChannelResult.cs b/src/Api/PubnubApi/EndPoint/DataSync/Channel/PNDataSyncDeleteChannelResult.cs
index f1169ac68..14a646302 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/Channel/PNDataSyncDeleteChannelResult.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/Channel/PNDataSyncDeleteChannelResult.cs
@@ -1,4 +1,4 @@
-namespace PubnubApi.EndPoint;
+namespace PubnubApi;
public class PNDataSyncDeleteChannelResult
{
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/Channel/SetChannelParameters.cs b/src/Api/PubnubApi/EndPoint/DataSync/Channel/SetChannelParameters.cs
index 855f6a2d5..79b5bc0f3 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/Channel/SetChannelParameters.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/Channel/SetChannelParameters.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
-namespace PubnubApi.EndPoint
+namespace PubnubApi
{
public class SetChannelParameters
{
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/Channel/UpdateChannelParameters.cs b/src/Api/PubnubApi/EndPoint/DataSync/Channel/UpdateChannelParameters.cs
index cbaaa61f8..aff574b82 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/Channel/UpdateChannelParameters.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/Channel/UpdateChannelParameters.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
-namespace PubnubApi.EndPoint
+namespace PubnubApi
{
public class UpdateChannelParameters
{
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/DataSync.cs b/src/Api/PubnubApi/EndPoint/DataSync/DataSync.cs
index 645948593..73d0517e0 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/DataSync.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/DataSync.cs
@@ -1,6 +1,7 @@
using System.Threading.Tasks;
+using PubnubApi.EndPoint;
-namespace PubnubApi.EndPoint;
+namespace PubnubApi;
///
/// Entrypoint for PubNub Data Sync operations
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/Entity/CreateEntityParameters.cs b/src/Api/PubnubApi/EndPoint/DataSync/Entity/CreateEntityParameters.cs
index 690ef3742..aa141a649 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/Entity/CreateEntityParameters.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/Entity/CreateEntityParameters.cs
@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
-namespace PubnubApi.EndPoint
+namespace PubnubApi
{
///
/// Parameters for creating a new entity via DataSync.
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/Entity/DeleteEntityParameters.cs b/src/Api/PubnubApi/EndPoint/DataSync/Entity/DeleteEntityParameters.cs
index 926a6025e..e40fa7e85 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/Entity/DeleteEntityParameters.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/Entity/DeleteEntityParameters.cs
@@ -1,4 +1,4 @@
-namespace PubnubApi.EndPoint
+namespace PubnubApi
{
///
/// Parameters for deleting an entity by ID via DataSync.
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/Entity/GetEntitiesParameters.cs b/src/Api/PubnubApi/EndPoint/DataSync/Entity/GetEntitiesParameters.cs
index 4ba572956..0cc991139 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/Entity/GetEntitiesParameters.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/Entity/GetEntitiesParameters.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
-namespace PubnubApi.EndPoint
+namespace PubnubApi
{
///
/// Parameters for listing entities via DataSync.
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/Entity/GetEntityParameters.cs b/src/Api/PubnubApi/EndPoint/DataSync/Entity/GetEntityParameters.cs
index be6c079f8..2a716d85d 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/Entity/GetEntityParameters.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/Entity/GetEntityParameters.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
-namespace PubnubApi.EndPoint
+namespace PubnubApi
{
///
/// Parameters for retrieving an entity by ID via DataSync.
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/Entity/PNDataSyncDeleteEntityResult.cs b/src/Api/PubnubApi/EndPoint/DataSync/Entity/PNDataSyncDeleteEntityResult.cs
index 49705f0eb..e2fc7dcdb 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/Entity/PNDataSyncDeleteEntityResult.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/Entity/PNDataSyncDeleteEntityResult.cs
@@ -1,4 +1,4 @@
-namespace PubnubApi.EndPoint;
+namespace PubnubApi;
public class PNDataSyncDeleteEntityResult
{
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/Entity/PNDataSyncEntityResult.cs b/src/Api/PubnubApi/EndPoint/DataSync/Entity/PNDataSyncEntityResult.cs
index 824825670..c6d99b9fd 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/Entity/PNDataSyncEntityResult.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/Entity/PNDataSyncEntityResult.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
-namespace PubnubApi.EndPoint;
+namespace PubnubApi;
///
/// Result returned by a single-entity operation (Create, Get, Update, Patch).
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/Entity/SetEntityParameters.cs b/src/Api/PubnubApi/EndPoint/DataSync/Entity/SetEntityParameters.cs
index 466851587..60a1049af 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/Entity/SetEntityParameters.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/Entity/SetEntityParameters.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
-namespace PubnubApi.EndPoint
+namespace PubnubApi
{
///
/// Parameters for updating an entity with complete resource replacement (PUT) via DataSync.
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/Entity/UpdateEntityParameters.cs b/src/Api/PubnubApi/EndPoint/DataSync/Entity/UpdateEntityParameters.cs
index ea1a5f597..ae0074eaa 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/Entity/UpdateEntityParameters.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/Entity/UpdateEntityParameters.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
-namespace PubnubApi.EndPoint
+namespace PubnubApi
{
public class UpdateEntityParameters
{
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/Membership/CreateMembershipParameters.cs b/src/Api/PubnubApi/EndPoint/DataSync/Membership/CreateMembershipParameters.cs
index 78e9a0280..db6dd1705 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/Membership/CreateMembershipParameters.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/Membership/CreateMembershipParameters.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
-namespace PubnubApi.EndPoint
+namespace PubnubApi
{
public class CreateMembershipParameters
{
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/Membership/DeleteMembershipParameters.cs b/src/Api/PubnubApi/EndPoint/DataSync/Membership/DeleteMembershipParameters.cs
index b9f26d685..5c15a9c1c 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/Membership/DeleteMembershipParameters.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/Membership/DeleteMembershipParameters.cs
@@ -1,4 +1,4 @@
-namespace PubnubApi.EndPoint
+namespace PubnubApi
{
public class DeleteMembershipParameters
{
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/Membership/GetMembershipParameters.cs b/src/Api/PubnubApi/EndPoint/DataSync/Membership/GetMembershipParameters.cs
index 46365381e..6dafa551d 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/Membership/GetMembershipParameters.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/Membership/GetMembershipParameters.cs
@@ -1,4 +1,4 @@
-namespace PubnubApi.EndPoint
+namespace PubnubApi
{
public class GetMembershipParameters
{
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/Membership/GetMembershipsParameters.cs b/src/Api/PubnubApi/EndPoint/DataSync/Membership/GetMembershipsParameters.cs
index 687f779a1..c023dd53e 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/Membership/GetMembershipsParameters.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/Membership/GetMembershipsParameters.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
-namespace PubnubApi.EndPoint
+namespace PubnubApi
{
public class GetMembershipsParameters
{
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/Membership/PNDataSyncDeleteMembershipResult.cs b/src/Api/PubnubApi/EndPoint/DataSync/Membership/PNDataSyncDeleteMembershipResult.cs
index 9d7896dce..c8ee09e0b 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/Membership/PNDataSyncDeleteMembershipResult.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/Membership/PNDataSyncDeleteMembershipResult.cs
@@ -1,4 +1,4 @@
-namespace PubnubApi.EndPoint;
+namespace PubnubApi;
public class PNDataSyncDeleteMembershipResult
{
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/Membership/PNDataSyncMembershipResult.cs b/src/Api/PubnubApi/EndPoint/DataSync/Membership/PNDataSyncMembershipResult.cs
index 6c584a2b4..2c11ec1e8 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/Membership/PNDataSyncMembershipResult.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/Membership/PNDataSyncMembershipResult.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
-namespace PubnubApi.EndPoint;
+namespace PubnubApi;
public class PNDataSyncMembershipResult
{
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/Membership/SetMembershipParameters.cs b/src/Api/PubnubApi/EndPoint/DataSync/Membership/SetMembershipParameters.cs
index 3763735dc..0733c92f0 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/Membership/SetMembershipParameters.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/Membership/SetMembershipParameters.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
-namespace PubnubApi.EndPoint
+namespace PubnubApi
{
public class UpdateMembershipParameters
{
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/Membership/UpdateMembershipParameters.cs b/src/Api/PubnubApi/EndPoint/DataSync/Membership/UpdateMembershipParameters.cs
index 16e45831d..c4d990cb8 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/Membership/UpdateMembershipParameters.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/Membership/UpdateMembershipParameters.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
-namespace PubnubApi.EndPoint
+namespace PubnubApi
{
public class PatchMembershipParameters
{
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/Relationship/CreateRelationshipParameters.cs b/src/Api/PubnubApi/EndPoint/DataSync/Relationship/CreateRelationshipParameters.cs
index 03afac7ef..8d30eeb72 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/Relationship/CreateRelationshipParameters.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/Relationship/CreateRelationshipParameters.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
-namespace PubnubApi.EndPoint
+namespace PubnubApi
{
///
/// Parameters for creating a new relationship via DataSync.
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/Relationship/DeleteRelationshipParameters.cs b/src/Api/PubnubApi/EndPoint/DataSync/Relationship/DeleteRelationshipParameters.cs
index 55dcbba8e..5586168d4 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/Relationship/DeleteRelationshipParameters.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/Relationship/DeleteRelationshipParameters.cs
@@ -1,4 +1,4 @@
-namespace PubnubApi.EndPoint
+namespace PubnubApi
{
///
/// Parameters for deleting a relationship by ID via DataSync.
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/Relationship/GetRelationshipParameters.cs b/src/Api/PubnubApi/EndPoint/DataSync/Relationship/GetRelationshipParameters.cs
index 51d859de1..1b79c5b16 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/Relationship/GetRelationshipParameters.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/Relationship/GetRelationshipParameters.cs
@@ -1,4 +1,4 @@
-namespace PubnubApi.EndPoint
+namespace PubnubApi
{
///
/// Parameters for retrieving a relationship by ID via DataSync.
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/Relationship/GetRelationshipsParameters.cs b/src/Api/PubnubApi/EndPoint/DataSync/Relationship/GetRelationshipsParameters.cs
index d5e6b17ce..c4eb02b6b 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/Relationship/GetRelationshipsParameters.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/Relationship/GetRelationshipsParameters.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
-namespace PubnubApi.EndPoint
+namespace PubnubApi
{
///
/// Parameters for listing relationships via DataSync.
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/Relationship/PNDataSyncDeleteRelationshipResult.cs b/src/Api/PubnubApi/EndPoint/DataSync/Relationship/PNDataSyncDeleteRelationshipResult.cs
index 7ba18de2f..9c8d316a4 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/Relationship/PNDataSyncDeleteRelationshipResult.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/Relationship/PNDataSyncDeleteRelationshipResult.cs
@@ -1,4 +1,4 @@
-namespace PubnubApi.EndPoint;
+namespace PubnubApi;
public class PNDataSyncDeleteRelationshipResult
{
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/Relationship/PNDataSyncRelationshipResult.cs b/src/Api/PubnubApi/EndPoint/DataSync/Relationship/PNDataSyncRelationshipResult.cs
index 39a464999..16f54b3a6 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/Relationship/PNDataSyncRelationshipResult.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/Relationship/PNDataSyncRelationshipResult.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
-namespace PubnubApi.EndPoint;
+namespace PubnubApi;
///
/// Result returned by a single-relationship operation (Create, Get, Update, Patch).
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/Relationship/SetRelationshipParameters.cs b/src/Api/PubnubApi/EndPoint/DataSync/Relationship/SetRelationshipParameters.cs
index dfa637da6..f26bc4bad 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/Relationship/SetRelationshipParameters.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/Relationship/SetRelationshipParameters.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
-namespace PubnubApi.EndPoint
+namespace PubnubApi
{
///
/// Parameters for updating a relationship with complete resource replacement (PUT) via DataSync.
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/Relationship/UpdateRelationshipParameters.cs b/src/Api/PubnubApi/EndPoint/DataSync/Relationship/UpdateRelationshipParameters.cs
index 3013ac337..8a1f009ec 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/Relationship/UpdateRelationshipParameters.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/Relationship/UpdateRelationshipParameters.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
-namespace PubnubApi.EndPoint
+namespace PubnubApi
{
///
/// Parameters for partially updating a relationship via JSON Patch (RFC 6902).
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/User/CreateUserParameters.cs b/src/Api/PubnubApi/EndPoint/DataSync/User/CreateUserParameters.cs
index f7270bf9b..143b5db0b 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/User/CreateUserParameters.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/User/CreateUserParameters.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
-namespace PubnubApi.EndPoint
+namespace PubnubApi
{
public class CreateUserParameters
{
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/User/DeleteUserParameters.cs b/src/Api/PubnubApi/EndPoint/DataSync/User/DeleteUserParameters.cs
index 3b3633fa8..48f3e5d66 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/User/DeleteUserParameters.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/User/DeleteUserParameters.cs
@@ -1,4 +1,4 @@
-namespace PubnubApi.EndPoint
+namespace PubnubApi
{
public class DeleteUserParameters
{
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/User/GetUserParameters.cs b/src/Api/PubnubApi/EndPoint/DataSync/User/GetUserParameters.cs
index f4522bf3f..e33ff69d1 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/User/GetUserParameters.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/User/GetUserParameters.cs
@@ -1,4 +1,4 @@
-namespace PubnubApi.EndPoint
+namespace PubnubApi
{
public class GetUserParameters
{
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/User/GetUsersParameters.cs b/src/Api/PubnubApi/EndPoint/DataSync/User/GetUsersParameters.cs
index 97f9b517b..4d8608731 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/User/GetUsersParameters.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/User/GetUsersParameters.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
-namespace PubnubApi.EndPoint
+namespace PubnubApi
{
public class GetUsersParameters
{
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/User/PNDataSyncDeleteUserResult.cs b/src/Api/PubnubApi/EndPoint/DataSync/User/PNDataSyncDeleteUserResult.cs
index 717226c98..206d80322 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/User/PNDataSyncDeleteUserResult.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/User/PNDataSyncDeleteUserResult.cs
@@ -1,4 +1,4 @@
-namespace PubnubApi.EndPoint;
+namespace PubnubApi;
public class PNDataSyncDeleteUserResult
{
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/User/PNDataSyncUserResult.cs b/src/Api/PubnubApi/EndPoint/DataSync/User/PNDataSyncUserResult.cs
index 9bcdd191b..ba79eafa6 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/User/PNDataSyncUserResult.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/User/PNDataSyncUserResult.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
-namespace PubnubApi.EndPoint;
+namespace PubnubApi;
public class PNDataSyncUserResult
{
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/User/SetUserParameters.cs b/src/Api/PubnubApi/EndPoint/DataSync/User/SetUserParameters.cs
index 758eebc90..9c07fce7d 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/User/SetUserParameters.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/User/SetUserParameters.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
-namespace PubnubApi.EndPoint
+namespace PubnubApi
{
public class SetUserParameters
{
diff --git a/src/Api/PubnubApi/EndPoint/DataSync/User/UpdateUserParameters.cs b/src/Api/PubnubApi/EndPoint/DataSync/User/UpdateUserParameters.cs
index 983912a5b..8f23bb27e 100644
--- a/src/Api/PubnubApi/EndPoint/DataSync/User/UpdateUserParameters.cs
+++ b/src/Api/PubnubApi/EndPoint/DataSync/User/UpdateUserParameters.cs
@@ -1,6 +1,6 @@
using System.Collections.Generic;
-namespace PubnubApi.EndPoint
+namespace PubnubApi
{
public class UpdateUserParameters
{
diff --git a/src/Api/PubnubApi/EndPoint/PubSub/UnsubscribeAllEndpoint.cs b/src/Api/PubnubApi/EndPoint/PubSub/UnsubscribeAllEndpoint.cs
index c21a85de5..89e1cea29 100644
--- a/src/Api/PubnubApi/EndPoint/PubSub/UnsubscribeAllEndpoint.cs
+++ b/src/Api/PubnubApi/EndPoint/PubSub/UnsubscribeAllEndpoint.cs
@@ -1,4 +1,6 @@
-using PubnubApi.EventEngine.Presence;
+using System.Collections.Generic;
+using System.Linq;
+using PubnubApi.EventEngine.Presence;
using PubnubApi.EventEngine.Subscribe;
namespace PubnubApi.EndPoint
@@ -10,13 +12,15 @@ public class UnsubscribeAllEndpoint: UnsubscribeAllOperation
private readonly IPubnubUnitTest unit;
private readonly SubscribeEventEngineFactory subscribeEventEngineFactory;
private readonly PresenceEventEngineFactory presenceEventEngineFactory;
+ private readonly LeaveOperation leaveOperation;
private readonly string instanceId;
- public UnsubscribeAllEndpoint(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, EndPoint.TokenManager tokenManager, SubscribeEventEngineFactory subscribeEventEngineFactory, PresenceEventEngineFactory presenceEventEngineFactory ,Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, tokenManager, instance)
+ public UnsubscribeAllEndpoint(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, EndPoint.TokenManager tokenManager, LeaveOperation leaveOperation, SubscribeEventEngineFactory subscribeEventEngineFactory, PresenceEventEngineFactory presenceEventEngineFactory ,Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, tokenManager, instance, false)
{
config = pubnubConfig;
jsonLibrary = jsonPluggableLibrary;
unit = pubnubUnit;
+ this.leaveOperation = leaveOperation;
this.subscribeEventEngineFactory = subscribeEventEngineFactory;
this.presenceEventEngineFactory = presenceEventEngineFactory;
instanceId = PubnubInstance.InstanceId;
@@ -28,24 +32,32 @@ private void UnsubscribeAll()
{
logger?.Trace($"{GetType().Name} Execute invoked");
+ var subscribeEventEngines = new List();
if (config.SplitSubscribeCalls)
{
- var allEngines = subscribeEventEngineFactory.GetAllEngineInstances(instanceId);
- foreach (var engine in allEngines)
- {
- engine.UnsubscribeAll();
- }
+ subscribeEventEngines = subscribeEventEngineFactory.GetAllEngineInstances(instanceId);
+ }
+ else if (subscribeEventEngineFactory.HasEventEngine(instanceId))
+ {
+ logger?.Trace($"EventEngine instance found.");
+ subscribeEventEngines.Add(subscribeEventEngineFactory.GetEventEngine(instanceId));
}
- else
+
+ bool usePresenceEventEngine = config.PresenceInterval > 0 && presenceEventEngineFactory.HasEventEngine(instanceId);
+ foreach (var subscribeEventEngine in subscribeEventEngines)
{
- if (subscribeEventEngineFactory.HasEventEngine(instanceId)) {
- logger?.Trace($"EventEngine instance found.");
- SubscribeEventEngine subscribeEventEngine = subscribeEventEngineFactory.GetEventEngine(instanceId);
- subscribeEventEngine.UnsubscribeAll();
+ var channelsToLeave = subscribeEventEngine.Channels.Where(c => !c.EndsWith(Constants.Pnpres)).Distinct().ToArray();
+ var channelGroupsToLeave = subscribeEventEngine.ChannelGroups.Where(cg => !cg.EndsWith(Constants.Pnpres)).Distinct().ToArray();
+
+ subscribeEventEngine.UnsubscribeAll();
+
+ if (!usePresenceEventEngine && !config.SuppressLeaveEvents && (channelsToLeave.Length > 0 || channelGroupsToLeave.Length > 0))
+ {
+ SendLeave(channelsToLeave, channelGroupsToLeave);
}
}
- if (config.PresenceInterval > 0 && presenceEventEngineFactory.HasEventEngine(instanceId)) {
+ if (usePresenceEventEngine) {
PresenceEventEngine presenceEventEngine = presenceEventEngineFactory.GetEventEngine(instanceId);
presenceEventEngine.EventQueue.Enqueue(new EventEngine.Presence.Events.LeftAllEvent());
}
@@ -54,11 +66,21 @@ private void UnsubscribeAll()
if (ChannelLocalUserState.TryGetValue(instanceId, out var channelStates)) {
channelStates.Clear();
}
- if (ChannelLocalUserState.TryGetValue(instanceId, out var channelGroupStates)) {
+ if (ChannelGroupLocalUserState.TryGetValue(instanceId, out var channelGroupStates)) {
channelGroupStates.Clear();
}
}
}
+
+ private void SendLeave(string[] channels, string[] channelGroups)
+ {
+ leaveOperation.LeaveRequest(channels, channelGroups).ContinueWith(t =>
+ {
+ if (t.Result is { Error: true } status)
+ {
+ logger?.Warn($"UnsubscribeAll leave request failed for channel(s)={string.Join(",", channels)} channelGroup(s)={string.Join(",", channelGroups)}: {status.ErrorData?.Information}");
+ }
+ }, System.Threading.Tasks.TaskContinuationOptions.OnlyOnRanToCompletion);
+ }
}
}
-
diff --git a/src/Api/PubnubApi/EndPoint/PubSub/UnsubscribeAllOperation.cs b/src/Api/PubnubApi/EndPoint/PubSub/UnsubscribeAllOperation.cs
index cbef4f05b..2f5e3c43e 100644
--- a/src/Api/PubnubApi/EndPoint/PubSub/UnsubscribeAllOperation.cs
+++ b/src/Api/PubnubApi/EndPoint/PubSub/UnsubscribeAllOperation.cs
@@ -12,7 +12,15 @@ public class UnsubscribeAllOperation : PubnubCoreBase
private readonly TokenManager pubnubTokenManager;
private Dictionary queryParam;
- public UnsubscribeAllOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, TokenManager tokenManager, Pubnub instance) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, tokenManager, instance)
+ public UnsubscribeAllOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, TokenManager tokenManager, Pubnub instance) : this(pubnubConfig, jsonPluggableLibrary, pubnubUnit, tokenManager, instance, true)
+ {
+ }
+
+ ///
+ /// When false, the legacy SubscribeManager logic is skipped. Derived types use this to run their own
+ /// unsubscribe logic, which cannot be done through a virtual call from this constructor.
+ ///
+ protected UnsubscribeAllOperation(PNConfiguration pubnubConfig, IJsonPluggableLibrary jsonPluggableLibrary, IPubnubUnitTest pubnubUnit, TokenManager tokenManager, Pubnub instance, bool runLegacyUnsubscribe) : base(pubnubConfig, jsonPluggableLibrary, pubnubUnit, tokenManager, instance)
{
config = pubnubConfig;
jsonLibrary = jsonPluggableLibrary;
@@ -20,7 +28,10 @@ public UnsubscribeAllOperation(PNConfiguration pubnubConfig, IJsonPluggableLibra
pubnubTokenManager = tokenManager;
CurrentPubnubInstance(instance);
- UnsubscribeAll();
+ if (runLegacyUnsubscribe)
+ {
+ UnsubscribeAll();
+ }
}
public UnsubscribeAllOperation QueryParam(Dictionary customQueryParam)
diff --git a/src/Api/PubnubApi/EndPoint/TokenManager.cs b/src/Api/PubnubApi/EndPoint/TokenManager.cs
index 793d2db15..ab8141dc4 100644
--- a/src/Api/PubnubApi/EndPoint/TokenManager.cs
+++ b/src/Api/PubnubApi/EndPoint/TokenManager.cs
@@ -89,6 +89,7 @@ public PNTokenContent ParseToken(string token)
Spaces = new Dictionary(),
DataSync = NewDataSyncScopes()
};
+ result.Categories = new PNTokenCategories();
ParseCBOR(cborDict, ref result);
}
}
@@ -178,6 +179,34 @@ private void FillTokenPermissionMapping(Dictionary