FRAModelsFromDatabase.m revision 2ff6fc247a59e7bebd6f71595469a511fe7456ef
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott/*
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott * The contents of this file are subject to the terms of the Common Development and
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott * Distribution License (the License). You may not use this file except in compliance with the
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott * License.
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott *
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott * specific language governing permission and limitations under the License.
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott *
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott * When distributing Covered Software, include this CDDL Header Notice in each file and include
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott * Header, with the fields enclosed by brackets [] replaced by your own identifying
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott * information: "Portions copyright [year] [name of copyright owner]".
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott *
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott * Copyright 2016 ForgeRock AS.
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott */
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott#import "FMDatabase.h"
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott#import "FRAError.h"
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott#import "FRAFMDatabaseConnectionHelper.h"
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott#import "FRAHMACAlgorithm.h"
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott#import "FRAIdentity.h"
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott#import "FRAModelObjectProtected.h"
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott#import "FRAModelsFromDatabase.h"
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott#import "FRANotification.h"
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott#import "FRAOathMechanism.h"
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott#import "FRAPushMechanism.h"
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott#import "FRASerialization.h"
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott/*!
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott*/
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott@implementation FRAModelsFromDatabase
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott/*!
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott * The parsing logic operates as follows:
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott *
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott * Perform SQL query to fetch all Identities, Mechanisms and Notifications where each
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott * Identity may have multiple associated Mechanisms and PushMechanisms may have multiple
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott * associated Notifications.
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott *
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott * The function will re-use matching Identities and Push Mechanisms as appropriate.
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott *
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott * TODO: Split into smaller functions.
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott */
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott+ (NSArray<FRAIdentity*> *)getAllIdentitiesFrom:(FRAFMDatabaseConnectionHelper *)sqlDatabase including:(FRAIdentityDatabase *)identityDatabase catchingErrorsWith:(NSError *__autoreleasing *)error {
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSString *sql = [FRAFMDatabaseConnectionHelper readSchema:@"read_all" withError:error];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott if (!sql) {
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott return nil;
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott }
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Open Database
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott FMDatabase *database;
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott @try {
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott database = [sqlDatabase getConnectionWithError:error];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott if (!database) {
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott return nil;
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott }
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Perform update
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott FMResultSet *results = [database executeQuery:sql];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott if (!results) {
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott [FRAError createErrorForLastFailure:database withError:error];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott return nil;
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott }
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Output rows for debugging purposes.
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // TODO: Sanitise data.
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSLog(@"Reading all rows from the database:");
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSMutableArray* identities = [[NSMutableArray alloc] init];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott int row = 0;
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott while ([results next]) {
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott // Identity
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSString *issuer = [FRASerialization nullToEmpty:[results stringForColumn:@"issuer"]];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSString *accountName = [FRASerialization nullToEmpty:[results stringForColumn:@"accountName"]];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSString *imageURL = [FRASerialization nullToEmpty:[results stringForColumn:@"imageURL"]];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSString *bgColor = [FRASerialization nullToEmpty:[results stringForColumn:@"bgColor"]];
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott // Mechanism
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSString *type = [FRASerialization nullToEmpty:[results stringForColumn:@"type"]];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSInteger version = [results intForColumn:@"version"];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSString *mechanismUID = [FRASerialization nullToEmpty:[results stringForColumn:@"mechanismUID"]];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSString *optionsJSON = [FRASerialization nullToEmpty:[results stringForColumn:@"options"]];
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott // Notification
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSString *timeReceived = [FRASerialization nullToEmpty:[results stringForColumn:@"timeReceived"]];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSString *timeExpired = [FRASerialization nullToEmpty:[results stringForColumn:@"timeExpired"]];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSString *data = [FRASerialization nullToEmpty:[results stringForColumn:@"data"]];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott int pending = [results intForColumn:@"pending"];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott int approved = [results intForColumn:@"approved"];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSLog(@"[%d] %@ %@ %@ %@ %@ %ld %@ %@ %@ %d %d",
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott row,
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott issuer,
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott accountName,
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott imageURL,
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott bgColor,
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott type,
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott (long)version,
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott mechanismUID,
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott timeReceived,
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott timeExpired,
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott pending,
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott approved);
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott row++;
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Create an Identity
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott FRAIdentity* newIdentity = [FRAIdentity
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott identityWithDatabase:identityDatabase
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott accountName:accountName
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott issuer:issuer
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott image:[[NSURL alloc]initWithString:imageURL]
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott backgroundColor:bgColor];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Check if we already have generated this identity, in which case re-use.
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott BOOL add = true;
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott for (FRAIdentity *identity in identities) {
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott if ([newIdentity.issuer isEqualToString:identity.issuer] && [newIdentity.accountName isEqualToString:identity.accountName]) {
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott newIdentity = identity;
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott add = false;
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott break;
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott }
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott }
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott if (add) {
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott [identities addObject:newIdentity];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott }
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Formatter for parsing numbers from Strings.
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott numberFormatter.numberStyle = NSNumberFormatterDecimalStyle;
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Create the Mechanism
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott if ([type isEqualToString:@"hotp"] || [type isEqualToString:@"totp"]) {
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // TODO: Null checking on errors.
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Options Map is a String to String mapping stored in JSON.
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSDictionary *optionsMap;
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott if (![FRASerialization deserializeJSON:optionsJSON intoDictionary:&optionsMap error:error]) {
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott return nil;
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott }
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Secret Key - Base 64 encoded bytes
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSString *secretValue = [optionsMap objectForKey:OATH_MECHANISM_SECRET];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSData* secret = [FRASerialization deserializeBytes:secretValue];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Algorithm - String enumeration
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSString *algorithmValue = [optionsMap objectForKey:OATH_MECHANISM_ALGORITHM];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott CCHmacAlgorithm algorithm = [FRAHMACAlgorithm fromString:algorithmValue];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Digits - String value of Integer
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSString *digitsValue = [optionsMap objectForKey:OATH_MECHANISM_DIGITS];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott int digits = [[numberFormatter numberFromString:digitsValue] intValue];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Period - String value of unsigned Integer
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSString *periodValue = [optionsMap objectForKey:OATH_MECHANISM_PERIOD];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott u_int32_t period = [[numberFormatter numberFromString:periodValue] unsignedIntValue];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Counter - String value of unsigned Long Long
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSString *counterValue = [optionsMap objectForKey:OATH_MECHANISM_COUNTER];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott u_int64_t counter = [[numberFormatter numberFromString:counterValue] unsignedLongLongValue];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott FRAOathMechanism *newMechanism = [FRAOathMechanism
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott oathMechanismWithDatabase:identityDatabase
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott type:type
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott usingSecretKey:secret
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott andHMACAlgorithm:algorithm
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott withKeyLength:digits
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott andEitherPeriod:period
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott orCounter:counter];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Note: We are not de-duplicating OATH Mechanism becuase they will not be duplicated in the SQL results.
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott if (![newIdentity addMechanism:newMechanism error:error]) {
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott return nil;
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott }
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott } else if ([type isEqualToString:@"push"]) {
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Options Map is a String to String mapping stored in JSON.
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSDictionary *optionsMap;
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott if (![FRASerialization deserializeJSON:optionsJSON intoDictionary:&optionsMap error:error]) {
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott return nil;
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott }
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Secret stored as String (Base64?)
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSString *secretValue = [optionsMap objectForKey:PUSH_MECHANISM_SECRET];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Auth Endpoint as string
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSString *authEndpointValue = [optionsMap objectForKey:PUSH_MECHANISM_AUTH_END_POINT];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Version as string
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSString *versionString = [optionsMap objectForKey:PUSH_MECHANISM_VERSION];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSInteger version = [[numberFormatter numberFromString:versionString] integerValue];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott FRAPushMechanism *newMechanism = [FRAPushMechanism pushMechanismWithDatabase:identityDatabase authEndpoint:authEndpointValue secret:secretValue version:version];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Check to see if we already have this PushMechanism present, otherwise add it in.
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott BOOL add = true;
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott for (FRAMechanism *mechanism in newIdentity.mechanisms) {
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott if ([mechanism isKindOfClass:[FRAPushMechanism class]]) {
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott FRAPushMechanism *pushMechanism = (FRAPushMechanism *)mechanism;
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott if ([pushMechanism.mechanismUID isEqualToString:newMechanism.mechanismUID]) {
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott newMechanism = pushMechanism;
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott add = false;
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott break;
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott }
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott }
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott }
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott if (add) {
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott if (![newIdentity addMechanism:newMechanism error:error]) {
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott return nil;
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott }
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott }
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott // If we have a notification, parse and create the Notification for the Push Mechanism.
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Note: Notifications can only currently exist for PushMechanisms.
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott if (timeReceived != nil && [timeReceived length] > 0) {
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott // Time stamp of the notification
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott NSDate *received = [NSDate dateWithTimeIntervalSince1970:[timeReceived doubleValue]];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott // Data map
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott NSDictionary *dataMap;
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott if (![FRASerialization deserializeJSON:data intoDictionary:&dataMap error:error]) {
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott return nil;
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott }
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott // Data: Message ID
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott NSString *messageId = [dataMap valueForKey:NOTIFICATION_MESSAGE_ID];
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott // Data: Challenge
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott NSString *challenge = [[NSString alloc] initWithData:[FRASerialization deserializeBytes:[dataMap valueForKey:NOTIFICATION_PUSH_CHALLENGE]] encoding:NSUTF8StringEncoding];
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott // Data: TTL
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott NSTimeInterval ttl = [[dataMap valueForKey:NOTIFICATION_TIME_TO_LIVE] doubleValue];
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott FRANotification *notification = [FRANotification notificationWithDatabase:identityDatabase
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott messageId:messageId
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott challenge:challenge
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott timeReceived:received
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott timeToLive:ttl];
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott if (![newMechanism addNotification:notification error:error]) {
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott return nil;
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott }
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott }
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott } else {
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott @throw [FRAError createIllegalStateException:@"Invalid mechanism"];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott }
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott }
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott // As we have read the objects from the database, marked them as stored.
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott for (FRAIdentity* identity in identities) {
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott identity.uid = YES;
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott for (FRAMechanism *mechanism in identity.mechanisms) {
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott mechanism.uid = YES;
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott for (FRANotification *notification in mechanism.notifications) {
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott notification.uid = YES;
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott }
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott }
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott }
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott return identities;
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott }
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott @finally {
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott [sqlDatabase closeConnectionToDatabase:database];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott }
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott}
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott@end