Skip to content
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

New ARTPush/getDevicePushDetails method for simplifying push state access #1186

Closed
wants to merge 15 commits into from
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Ably.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@
84569FA626B46F4E00457CF5 /* ClientOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84569FA226B46ADC00457CF5 /* ClientOptions.swift */; };
84569FA726B46F4F00457CF5 /* ClientOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84569FA226B46ADC00457CF5 /* ClientOptions.swift */; };
84569FA826B46F5100457CF5 /* ClientOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84569FA226B46ADC00457CF5 /* ClientOptions.swift */; };
8489D2F127176BA3009C6A54 /* ARTDevicePushDetails+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 8489D2F027176BA3009C6A54 /* ARTDevicePushDetails+Private.h */; };
8489D2F227176BA3009C6A54 /* ARTDevicePushDetails+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 8489D2F027176BA3009C6A54 /* ARTDevicePushDetails+Private.h */; };
8489D2F327176BA3009C6A54 /* ARTDevicePushDetails+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 8489D2F027176BA3009C6A54 /* ARTDevicePushDetails+Private.h */; };
848ED97326E50D0F0087E800 /* ObjcppTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 848ED97226E50D0F0087E800 /* ObjcppTest.mm */; settings = {COMPILER_FLAGS = "-fmodules"; }; };
848ED97426E50D0F0087E800 /* ObjcppTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 848ED97226E50D0F0087E800 /* ObjcppTest.mm */; settings = {COMPILER_FLAGS = "-fmodules"; }; };
848ED97526E50D0F0087E800 /* ObjcppTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 848ED97226E50D0F0087E800 /* ObjcppTest.mm */; settings = {COMPILER_FLAGS = "-fmodules"; }; };
Expand Down Expand Up @@ -1012,6 +1015,7 @@
8412FDF32661AC7B001FE9E6 /* Quick.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Quick.xcframework; path = Carthage/Build/Quick.xcframework; sourceTree = "<group>"; };
8412FDF42661AC7B001FE9E6 /* Nimble.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Nimble.xcframework; path = Carthage/Build/Nimble.xcframework; sourceTree = "<group>"; };
84569FA226B46ADC00457CF5 /* ClientOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientOptions.swift; sourceTree = "<group>"; };
8489D2F027176BA3009C6A54 /* ARTDevicePushDetails+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ARTDevicePushDetails+Private.h"; sourceTree = "<group>"; };
848ED97226E50D0F0087E800 /* ObjcppTest.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ObjcppTest.mm; sourceTree = "<group>"; };
850BFB4A1B79323C009D0ADD /* ARTPaginatedResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARTPaginatedResult.h; sourceTree = "<group>"; };
850BFB4B1B79323C009D0ADD /* ARTPaginatedResult.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ARTPaginatedResult.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1831,6 +1835,7 @@
D7B621921E4A6FE600684474 /* ARTDeviceDetails.h */,
D7B621931E4A6FE600684474 /* ARTDeviceDetails.m */,
D768C6AA1E4B5B0200436011 /* ARTDevicePushDetails.h */,
8489D2F027176BA3009C6A54 /* ARTDevicePushDetails+Private.h */,
D768C6AB1E4B5B0200436011 /* ARTDevicePushDetails.m */,
D777EEDE206285CF002EBA03 /* ARTDeviceIdentityTokenDetails.h */,
D777EEDF206285CF002EBA03 /* ARTDeviceIdentityTokenDetails.m */,
Expand Down Expand Up @@ -1960,6 +1965,7 @@
D7D5A69C1CA40C350071BD6D /* ARTConnectionDetails+Private.h in Headers */,
D75F49C4205ACFEC003DE04F /* ARTDeviceStorage.h in Headers */,
D7B621901E4A6E0200684474 /* ARTPush.h in Headers */,
8489D2F127176BA3009C6A54 /* ARTDevicePushDetails+Private.h in Headers */,
96E408471A3895E800087F77 /* ARTWebSocketTransport.h in Headers */,
EB503C8A1C7F1FE40053AF00 /* ARTLog+Private.h in Headers */,
96E4083F1A3892C700087F77 /* ARTRealtimeTransport.h in Headers */,
Expand Down Expand Up @@ -2154,6 +2160,7 @@
D710D61F21949DEC008F54AD /* ARTNSHTTPURLResponse+ARTPaginated.h in Headers */,
D710D69F21949F0D008F54AD /* ARTJsonLikeEncoder.h in Headers */,
D710D4A721949ADF008F54AD /* ARTRestChannel.h in Headers */,
8489D2F227176BA3009C6A54 /* ARTDevicePushDetails+Private.h in Headers */,
D710D64721949E61008F54AD /* ARTLog+Private.h in Headers */,
D710D57C21949CC8008F54AD /* ARTPushAdmin+Private.h in Headers */,
D710D61B21949DEC008F54AD /* ARTDataQuery+Private.h in Headers */,
Expand Down Expand Up @@ -2292,6 +2299,7 @@
D710D5B321949D2A008F54AD /* ARTPresenceMap.h in Headers */,
D710D57121949CBA008F54AD /* ARTPushDeviceRegistrations.h in Headers */,
D710D62C21949DED008F54AD /* ARTNSMutableURLRequest+ARTPaginated.h in Headers */,
8489D2F327176BA3009C6A54 /* ARTDevicePushDetails+Private.h in Headers */,
D710D4B221949AF9008F54AD /* ARTAuth.h in Headers */,
D710D5B121949D2A008F54AD /* ARTPresence.h in Headers */,
D710D4E921949BFB008F54AD /* ARTQueuedMessage.h in Headers */,
Expand Down
13 changes: 13 additions & 0 deletions Source/ARTDevicePushDetails+Private.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#import <Ably/ARTDevicePushDetails.h>

NS_ASSUME_NONNULL_BEGIN

@interface ARTDevicePushDetails ()

- (NSString *)stateString;

+ (ARTPushState)stateFromString:(NSString *)string;

@end

NS_ASSUME_NONNULL_END
6 changes: 3 additions & 3 deletions Source/ARTDevicePushDetails.h
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
#import <Foundation/Foundation.h>
#import <Ably/ARTTypes.h>

@class ARTErrorInfo;

NS_ASSUME_NONNULL_BEGIN

@interface ARTDevicePushDetails : NSObject

@property (nonatomic) NSMutableDictionary<NSString *, NSString *> *recipient;
@property (nullable, nonatomic) NSString *state;
@property (nonatomic) ARTPushState state;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this change (string to enum) can be a separate thing, which we should do regardless of how we solve the LocalDevice issue. I've created an issue for it: #1264.

@property (nullable, nonatomic) ARTErrorInfo *errorReason;
@property (nonatomic) NSMutableDictionary<NSString *, NSString *> *recipient;

- (instancetype)init;

Expand Down
30 changes: 29 additions & 1 deletion Source/ARTDevicePushDetails.m
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#import "ARTDevicePushDetails.h"
#import "ARTDevicePushDetails+Private.h"
#import "ARTPush.h"

@implementation ARTDevicePushDetails
Expand All @@ -20,8 +21,35 @@ - (id)copyWithZone:(NSZone *)zone {
return push;
}

- (NSString *)stateString {
switch (_state) {
case ARTPushStateActive:
return @"ARTPushStateActive";
case ARTPushStateFailing:
return @"ARTPushStateFailing";
case ARTPushStateFailed:
return @"ARTPushStateFailed";
default:
return @"ARTPushStateUnknown";
}
}

+ (ARTPushState)stateFromString:(NSString *)string {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably just naming, but I expect to use here values from stateString like ARTPushStateActive, ARTPushStateFailing etc.
Maybe additionally checking these values in this method could be a better idea than renaming this method.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I'm not sure what you are saying here, this method is for obtaining ARTPushState values from strings that came from JSON data. Am I missing something?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, so you should rename it to stateFromJsonString.
I meant you have this method:

- (NSString *)stateString {
    switch (_state) {
        case ARTPushStateActive:
            return @"ARTPushStateActive";
        case ARTPushStateFailing:
            return @"ARTPushStateFailing";
        case ARTPushStateFailed:
            return @"ARTPushStateFailed";
        default:
            return @"ARTPushStateUnknown";
    }
}

which also produce strings from ARTPushState and the method name stateFromString is a bit confusing because I don't know "from which string" it creates the ARTPushState

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point b03a251

string = string.lowercaseString;
if ([string isEqualToString:@"active"]) {
return ARTPushStateActive;
}
else if ([string isEqualToString:@"failing"]) {
return ARTPushStateFailing;
}
else if ([string isEqualToString:@"failed"]) {
return ARTPushStateFailed;
}
return ARTPushStateUnknown;
}

- (NSString *)description {
return [NSString stringWithFormat:@"%@ - \n\t recipient: %@; \n\t state: %@; \n\t errorReason: %@;", [super description], self.recipient, self.state, self.errorReason];
return [NSString stringWithFormat:@"%@ - \n\t recipient: %@; \n\t state: %@; \n\t errorReason: %@;", [super description], self.recipient, self.stateString, self.errorReason];
ben-xD marked this conversation as resolved.
Show resolved Hide resolved
}

@end
4 changes: 2 additions & 2 deletions Source/ARTJsonLikeEncoder.m
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#import "ARTPush.h"
#import "ARTDeviceDetails.h"
#import "ARTDeviceIdentityTokenDetails.h"
#import "ARTDevicePushDetails.h"
#import "ARTDevicePushDetails+Private.h"
#import "ARTConnectionDetails.h"
#import "ARTRest+Private.h"
#import "ARTJsonEncoder.h"
Expand Down Expand Up @@ -699,7 +699,7 @@ - (ARTDevicePushDetails *)devicePushDetailsFromDictionary:(NSDictionary *)input
}

ARTDevicePushDetails *devicePushDetails = [[ARTDevicePushDetails alloc] init];
devicePushDetails.state = [input artString:@"state"];
devicePushDetails.state = [ARTDevicePushDetails stateFromString:[input artString:@"state"]];
NSDictionary *errorReason = [input valueForKey:@"errorReason"];
if (errorReason) {
devicePushDetails.errorReason = [ARTErrorInfo createWithCode:[[errorReason artNumber:@"code"] intValue] status:[[errorReason artNumber:@"statusCode"] intValue] message:[errorReason artString:@"message"]];
Expand Down
2 changes: 2 additions & 0 deletions Source/ARTPush.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (void)deactivate;

- (void)getDevicePushDetails:(ARTPushStateCallback)callback;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this needs to be agreed cross-platform (i.e. via the features spec) before we add it here. I think https://github.com/ably/docs/issues/1288 would be the best place to come to a consensus on this.


#endif

@end
Expand Down
14 changes: 14 additions & 0 deletions Source/ARTPush.m
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ - (void)deactivate {
[_internal deactivate];
}

- (void)getDevicePushDetails:(nonnull ARTPushStateCallback)callback {
[_internal getDevicePushDetails:callback];
}

#endif

@end
Expand Down Expand Up @@ -235,6 +239,16 @@ - (void)deactivate {
}];
}

- (void)getDevicePushDetails:(nonnull ARTPushStateCallback)callback {
[_admin.deviceRegistrations get:_rest.device.id callback:^(ARTDeviceDetails *device, ARTErrorInfo *error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interestingly, it is using the push admin class, but when I removed the push admin capability from the API key, it stil works. In other words: I did not need push admin. I wonder why this is the case. We should confirm and document if this method requires Push Admin. WDYT?

Copy link
Collaborator Author

@maratal maratal Oct 15, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I've found out is if the Admin capability got turned off you need to deactivate/activate push on the device to changes to take effect. In my case not only I've lost admin capability, it stops me from doing anything with pushes, even publish them with deviceId with an error:

{
   code = 40160;
   href = "https://help.ably.io/error/40160";
   message = "action not permitted, app = 5****g";
   serverId = "frontend.****";
   statusCode = 401;
} 

WDYT @ben-xD

Copy link
Contributor

@ben-xD ben-xD Oct 15, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can't publish by device ID without push admin, so that makes sense. So in summary, you discovered that this method (& endpoint) requires push admin?

I think this is a feature that we want clients without push-admin to have access to. Perhaps a separate endpoint should be created then?

Copy link
Collaborator Author

@maratal maratal Oct 15, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can't publish by device ID without push admin, so that makes sense. So in summary, you discovered that this endpoint requires push admin?

No, I've discovered that I can't send pushes neither by deviceId not clientId, but that's I guess how it should be.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can only send pushes by messages (with push payload), if you don't have push admin. To send by client ID, you also need push admin.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It appears like the _admin instance is being used, which would be very confusing

As we can see here in java https://github.com/ably/ably-java/blob/main/lib/src/main/java/io/ably/lib/push/PushBase.java
DeviceRegistrations is on the same level as Admin, and the latter contains nothing except publish method. So I assume ARTPushAdmin in cocoa contains ARTPushDeviceRegistrations and ARTPushChannelSubscriptions by mistake. So I moved it from there into the ARTPush namespace - b6f1eaf
@QuintinWillison @lawrence-forooghian @lukasz-szyszkowski

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved files out of Admin group as well d447d2c

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@QuintinWillison if you are not against these changes please resolve this conversation since Ben started it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lawrence-forooghian could you please take a look and resolve this conversation if you feel it can be. I've not got enough context or time to get involved right now.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@maratal is your question "can we move deviceRegistrations and channelSubscriptions from ARTPushAdmin to ARTPush"? If so, I think this comment of mine addresses it.

if (error != nil) {
callback(nil, error);
return;
}
callback(device.push, nil);
}];
}

#endif

@end
9 changes: 9 additions & 0 deletions Source/ARTTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
@class ARTStats;
@class ARTPushChannelSubscription;
@class ARTDeviceDetails;
@class ARTDevicePushDetails;
@protocol ARTTokenDetailsCompatible;

// More context
Expand All @@ -38,6 +39,12 @@ typedef NS_ENUM(NSUInteger, ARTAuthMethod) {
ARTAuthMethodToken
};

typedef NS_ENUM(NSUInteger, ARTPushState) {
ARTPushStateUnknown,
ARTPushStateActive,
ARTPushStateFailing,
ARTPushStateFailed
};

#pragma mark - ARTRealtimeConnectionState

Expand Down Expand Up @@ -279,6 +286,8 @@ typedef void (^ARTPaginatedMessagesCallback)(ARTPaginatedResult<ARTMessage *> *_
typedef void (^ARTPaginatedDeviceDetailsCallback)(ARTPaginatedResult<ARTDeviceDetails *> *_Nullable result, ARTErrorInfo *_Nullable error);
typedef void (^ARTPaginatedTextCallback)(ARTPaginatedResult<NSString *> *_Nullable result, ARTErrorInfo *_Nullable error);

typedef void (^ARTPushStateCallback)(ARTDevicePushDetails *_Nullable details, ARTErrorInfo *_Nullable error);

#pragma mark - Functions

/**
Expand Down