mirror of https://github.com/oxen-io/session-ios
parent
d48fd158b7
commit
a99fde4d3b
@ -0,0 +1,21 @@
|
||||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
|
||||
#import "TSYapDatabaseObject.h"
|
||||
#import <Mantle/MTLJSONAdapter.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface OWSDevice : TSYapDatabaseObject <MTLJSONSerializing>
|
||||
|
||||
@property (nonatomic, readonly) NSInteger deviceId;
|
||||
@property (nullable, nonatomic, readonly) NSString *name;
|
||||
@property (nonatomic, readonly) NSDate *createdAt;
|
||||
@property (nonatomic, readonly) NSDate *lastSeenAt;
|
||||
|
||||
+ (instancetype)deviceFromJSONDictionary:(NSDictionary *)deviceAttributes error:(NSError **)error;
|
||||
+ (NSArray<OWSDevice *> *)secondaryDevices;
|
||||
+ (void)replaceAll:(NSArray<OWSDevice *> *)devices;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@ -0,0 +1,120 @@
|
||||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
|
||||
#import "OWSDevice.h"
|
||||
#import "NSDate+millisecondTimeStamp.h"
|
||||
#import "OWSError.h"
|
||||
#import "YapDatabaseConnection.h"
|
||||
#import "YapDatabaseTransaction.h"
|
||||
#import <Mantle/MTLValueTransformer.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
static MTLValueTransformer *_millisecondTimestampToDateTransformer;
|
||||
static int const OWSDevicePrimaryDeviceId = 1;
|
||||
|
||||
@implementation OWSDevice
|
||||
|
||||
@synthesize name = _name;
|
||||
|
||||
+ (instancetype)deviceFromJSONDictionary:(NSDictionary *)deviceAttributes error:(NSError **)error
|
||||
{
|
||||
return [MTLJSONAdapter modelOfClass:[self class] fromJSONDictionary:deviceAttributes error:error];
|
||||
}
|
||||
|
||||
+ (NSDictionary *)JSONKeyPathsByPropertyKey
|
||||
{
|
||||
return @{
|
||||
@"createdAt": @"created",
|
||||
@"lastSeenAt": @"lastSeen",
|
||||
@"deviceId": @"id",
|
||||
@"name": @"name"
|
||||
};
|
||||
}
|
||||
|
||||
+ (MTLValueTransformer *)createdAtJSONTransformer
|
||||
{
|
||||
return self.millisecondTimestampToDateTransformer;
|
||||
}
|
||||
|
||||
+ (MTLValueTransformer *)lastSeenAtJSONTransformer
|
||||
{
|
||||
return self.millisecondTimestampToDateTransformer;
|
||||
}
|
||||
|
||||
+ (void)replaceAll:(NSArray<OWSDevice *> *)devices
|
||||
{
|
||||
[self.dbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[transaction removeAllObjectsInCollection:[self collection]];
|
||||
for (OWSDevice *device in devices) {
|
||||
[device saveWithTransaction:transaction];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
+ (MTLValueTransformer *)millisecondTimestampToDateTransformer
|
||||
{
|
||||
if (!_millisecondTimestampToDateTransformer) {
|
||||
_millisecondTimestampToDateTransformer =
|
||||
[MTLValueTransformer transformerUsingForwardBlock:^id(id value, BOOL *success, NSError **error) {
|
||||
if ([value isKindOfClass:[NSNumber class]]) {
|
||||
NSNumber *number = (NSNumber *)value;
|
||||
NSDate *result = [NSDate ows_dateWithMillisecondsSince1970:[number longLongValue]];
|
||||
if (result) {
|
||||
*success = YES;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
*success = NO;
|
||||
*error = OWSErrorWithCodeDescription(OWSErrorCodeFailedToDecodeJson,
|
||||
[NSString stringWithFormat:@"unable to decode date from %@", value]);
|
||||
return nil;
|
||||
}
|
||||
reverseBlock:^id(id value, BOOL *success, NSError **error) {
|
||||
if ([value isKindOfClass:[NSDate class]]) {
|
||||
NSDate *date = (NSDate *)value;
|
||||
NSNumber *result = [NSNumber numberWithLongLong:[NSDate ows_millisecondsSince1970ForDate:date]];
|
||||
if (result) {
|
||||
*success = YES;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
*error = OWSErrorWithCodeDescription(OWSErrorCodeFailedToEncodeJson,
|
||||
[NSString stringWithFormat:@"unable to encode date from %@", value]);
|
||||
*success = NO;
|
||||
return nil;
|
||||
}];
|
||||
}
|
||||
return _millisecondTimestampToDateTransformer;
|
||||
}
|
||||
|
||||
+ (NSArray<OWSDevice *> *)secondaryDevices
|
||||
{
|
||||
NSMutableArray<OWSDevice *> *devices = [NSMutableArray new];
|
||||
|
||||
[self enumerateCollectionObjectsUsingBlock:^(id obj, BOOL *stop) {
|
||||
if ([obj isKindOfClass:[OWSDevice class]]) {
|
||||
OWSDevice *device = (OWSDevice *)obj;
|
||||
if (device.deviceId != OWSDevicePrimaryDeviceId) {
|
||||
[devices addObject:device];
|
||||
}
|
||||
}
|
||||
}];
|
||||
|
||||
return [devices copy];
|
||||
}
|
||||
|
||||
- (nullable NSString *)name
|
||||
{
|
||||
if (_name) {
|
||||
return _name;
|
||||
}
|
||||
|
||||
if (self.deviceId == OWSDevicePrimaryDeviceId) {
|
||||
return @"This Device";
|
||||
}
|
||||
return NSLocalizedString(@"UNNAMED_DEVICE", @"Label text in device manager for a device with no name");
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@ -0,0 +1,18 @@
|
||||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class OWSDevice;
|
||||
|
||||
@interface OWSDevicesService : NSObject
|
||||
|
||||
- (void)getDevicesWithSuccess:(void (^)(NSArray<OWSDevice *> *))successCallback
|
||||
failure:(void (^)(NSError *))failureCallback;
|
||||
|
||||
- (void)unlinkDevice:(OWSDevice *)device
|
||||
success:(void (^)())successCallback
|
||||
failure:(void (^)(NSError *))failureCallback;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@ -0,0 +1,84 @@
|
||||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
|
||||
#import "OWSDevicesService.h"
|
||||
#import "OWSDeleteDeviceRequest.h"
|
||||
#import "OWSDevice.h"
|
||||
#import "OWSError.h"
|
||||
#import "OWSGetDevicesRequest.h"
|
||||
#import "TSNetworkManager.h"
|
||||
#import <Mantle/MTLJSONAdapter.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@implementation OWSDevicesService
|
||||
|
||||
- (void)getDevicesWithSuccess:(void (^)(NSArray<OWSDevice *> *))successCallback
|
||||
failure:(void (^)(NSError *))failureCallback
|
||||
{
|
||||
OWSGetDevicesRequest *request = [OWSGetDevicesRequest new];
|
||||
[[TSNetworkManager sharedManager] makeRequest:request
|
||||
success:^(NSURLSessionDataTask *task, id responseObject) {
|
||||
DDLogVerbose(@"Get devices request succeeded");
|
||||
NSArray<OWSDevice *> *devices = [self parseResponse:responseObject];
|
||||
|
||||
if (devices) {
|
||||
successCallback(devices);
|
||||
} else {
|
||||
failureCallback(OWSErrorWithCodeDescription(
|
||||
OWSErrorCodeUnableToProcessServerResponse, @"Unable to parse server response"));
|
||||
}
|
||||
}
|
||||
failure:^(NSURLSessionDataTask *task, NSError *error) {
|
||||
DDLogVerbose(@"Get devices request failed with error: %@", error);
|
||||
failureCallback(error);
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)unlinkDevice:(OWSDevice *)device
|
||||
success:(void (^)())successCallback
|
||||
failure:(void (^)(NSError *))failureCallback
|
||||
{
|
||||
OWSDeleteDeviceRequest *request = [[OWSDeleteDeviceRequest alloc] initWithDevice:device];
|
||||
|
||||
[[TSNetworkManager sharedManager] makeRequest:request
|
||||
success:^(NSURLSessionDataTask *task, id responseObject) {
|
||||
DDLogVerbose(@"Delete device request succeeded");
|
||||
successCallback();
|
||||
}
|
||||
failure:^(NSURLSessionDataTask *task, NSError *error) {
|
||||
DDLogVerbose(@"Get devices request failed with error: %@", error);
|
||||
failureCallback(error);
|
||||
}];
|
||||
}
|
||||
|
||||
- (NSArray<OWSDevice *> *)parseResponse:(id)responseObject
|
||||
{
|
||||
if (![responseObject isKindOfClass:[NSDictionary class]]) {
|
||||
DDLogError(@"Device response was not a dictionary.");
|
||||
return nil;
|
||||
}
|
||||
NSDictionary *response = (NSDictionary *)responseObject;
|
||||
|
||||
NSArray<NSDictionary *> *devicesAttributes = response[@"devices"];
|
||||
if (!devicesAttributes) {
|
||||
DDLogError(@"Device response had no devices.");
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSMutableArray<OWSDevice *> *devices = [NSMutableArray new];
|
||||
for (NSDictionary *deviceAttributes in devicesAttributes) {
|
||||
NSError *error;
|
||||
OWSDevice *device = [OWSDevice deviceFromJSONDictionary:deviceAttributes error:&error];
|
||||
if (error) {
|
||||
DDLogError(@"Failed to build device from dictionary with error: %@", error);
|
||||
} else {
|
||||
[devices addObject:device];
|
||||
}
|
||||
}
|
||||
|
||||
return [devices copy];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@ -0,0 +1,15 @@
|
||||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
|
||||
#import "TSRequest.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class OWSDevice;
|
||||
|
||||
@interface OWSDeleteDeviceRequest : TSRequest
|
||||
|
||||
- (instancetype)initWithDevice:(OWSDevice *)device;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@ -0,0 +1,27 @@
|
||||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
|
||||
#import "OWSDeleteDeviceRequest.h"
|
||||
#import "OWSDevice.h"
|
||||
#import "TSConstants.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@implementation OWSDeleteDeviceRequest
|
||||
|
||||
- (instancetype)initWithDevice:(OWSDevice *)device
|
||||
{
|
||||
NSString *deleteDevicePath = [NSString
|
||||
stringWithFormat:textSecureDevicesAPIFormat, [NSString stringWithFormat:@"%ld", (long)device.deviceId]];
|
||||
self = [super initWithURL:[NSURL URLWithString:deleteDevicePath]];
|
||||
if (!self) {
|
||||
return self;
|
||||
}
|
||||
|
||||
[self setHTTPMethod:@"DELETE"];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@ -0,0 +1,11 @@
|
||||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
|
||||
#import "TSRequest.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface OWSGetDevicesRequest : TSRequest
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@ -0,0 +1,25 @@
|
||||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
|
||||
#import "OWSGetDevicesRequest.h"
|
||||
#import "TSConstants.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@implementation OWSGetDevicesRequest
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
NSString *getDevicesPath = [NSString stringWithFormat:textSecureDevicesAPIFormat, @""];
|
||||
self = [super initWithURL:[NSURL URLWithString:getDevicesPath]];
|
||||
if (!self) {
|
||||
return self;
|
||||
}
|
||||
|
||||
[self setHTTPMethod:@"GET"];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
@ -1,13 +1,11 @@
|
||||
//
|
||||
// NSDate+millisecondTimeStamp.h
|
||||
// Signal
|
||||
//
|
||||
// Created by Frederic Jacobs on 25/11/14.
|
||||
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface NSDate (millisecondTimeStamp)
|
||||
|
||||
+ (uint64_t)ows_millisecondTimeStamp;
|
||||
+ (NSDate *)ows_dateWithMillisecondsSince1970:(uint64_t)milliseconds;
|
||||
+ (uint64_t)ows_millisecondsSince1970ForDate:(NSDate *)date;
|
||||
|
||||
@end
|
||||
|
Loading…
Reference in New Issue