FRAModelsFromDatabase.m revision 465ea459a87d4605e145d8f45b6a9c104b696e3b
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"
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni#import "FRAHMACAlgorithm.h"
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott#import "FRAIdentity.h"
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott#import "FRAModelObjectProtected.h"
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott#import "FRAModelsFromDatabase.h"
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott#import "FRANotification.h"
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni#import "FRAOathMechanism.h"
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni#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 {
6a2ae9c7fb4d2c40d75cab0edaf940f22c18224fDiego Colantoni
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];
78c07714ec1113f7f21c75b818f2bf6a7021618aDiego Colantoni return nil;
78c07714ec1113f7f21c75b818f2bf6a7021618aDiego Colantoni }
78c07714ec1113f7f21c75b818f2bf6a7021618aDiego Colantoni
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]) {
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Identity
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSString *issuer = [FRASerialization nullToEmpty:[results stringForColumn:@"issuer"]];
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert 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"]];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Mechanism
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSString *type = [FRASerialization nullToEmpty:[results stringForColumn:@"type"]];
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott NSInteger version = [results intForColumn:@"version"];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSString *mechanismUID = [FRASerialization nullToEmpty:[results stringForColumn:@"mechanismUID"]];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSString *optionsJSON = [FRASerialization nullToEmpty:[results stringForColumn:@"options"]];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Notification
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSString *timeReceived = [FRASerialization nullToEmpty:[results stringForColumn:@"timeReceived"]];
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert 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
f877f6ca2428244a6d0954a1dbef471577b32c60Diego Colantoni issuer:issuer
f877f6ca2428244a6d0954a1dbef471577b32c60Diego Colantoni image:[[NSURL alloc]initWithString:imageURL]
f877f6ca2428244a6d0954a1dbef471577b32c60Diego Colantoni backgroundColor:bgColor];
f877f6ca2428244a6d0954a1dbef471577b32c60Diego Colantoni
f877f6ca2428244a6d0954a1dbef471577b32c60Diego Colantoni // Check if we already have generated this identity, in which case re-use.
f877f6ca2428244a6d0954a1dbef471577b32c60Diego Colantoni 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.
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni
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];
0fc1bec9becddcbec0d26541dd7ef40b43c0a67bKen Stubbings
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Algorithm - String enumeration
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSString *algorithmValue = [optionsMap objectForKey:OATH_MECHANISM_ALGORITHM];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott CCHmacAlgorithm algorithm = [FRAHMACAlgorithm fromString:algorithmValue];
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Digits - String value of Integer
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni NSString *digitsValue = [optionsMap objectForKey:OATH_MECHANISM_DIGITS];
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni int digits = [[numberFormatter numberFromString:digitsValue] intValue];
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni // Period - String value of unsigned Integer
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni NSString *periodValue = [optionsMap objectForKey:OATH_MECHANISM_PERIOD];
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni u_int32_t period = [[numberFormatter numberFromString:periodValue] unsignedIntValue];
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni // Counter - String value of unsigned Long Long
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni NSString *counterValue = [optionsMap objectForKey:OATH_MECHANISM_COUNTER];
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni u_int64_t counter = [[numberFormatter numberFromString:counterValue] unsignedLongLongValue];
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni FRAOathMechanism *newMechanism = [FRAOathMechanism
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni oathMechanismWithDatabase:identityDatabase
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni type:type
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni usingSecretKey:secret
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni andHMACAlgorithm:algorithm
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni withKeyLength:digits
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni andEitherPeriod:period
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni orCounter:counter];
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni // Note: We are not de-duplicating OATH Mechanism becuase they will not be duplicated in the SQL results.
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni if (![newIdentity addMechanism:newMechanism error:error]) {
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni return nil;
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni }
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni } else if ([type isEqualToString:@"push"]) {
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni // Options Map is a String to String mapping stored in JSON.
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni NSDictionary *optionsMap;
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni if (![FRASerialization deserializeJSON:optionsJSON intoDictionary:&optionsMap error:error]) {
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni return nil;
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni }
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni // Secret stored as String (Base64?)
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni NSString *secretValue = [optionsMap objectForKey:PUSH_MECHANISM_SECRET];
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni // Auth Endpoint as string
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni NSString *authEndpointValue = [optionsMap objectForKey:PUSH_MECHANISM_AUTH_END_POINT];
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni
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
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni FRAPushMechanism *newMechanism = [FRAPushMechanism pushMechanismWithDatabase:identityDatabase authEndpoint:authEndpointValue secret:secretValue version:version mechanismIdentifier:mechanismUID];
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni // Check to see if we already have this PushMechanism present, otherwise add it in.
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni BOOL add = true;
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni for (FRAMechanism *mechanism in newIdentity.mechanisms) {
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott if ([mechanism isKindOfClass:[FRAPushMechanism class]]) {
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni FRAPushMechanism *pushMechanism = (FRAPushMechanism *)mechanism;
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott if ([pushMechanism.mechanismUID isEqualToString:newMechanism.mechanismUID]) {
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott newMechanism = pushMechanism;
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott add = false;
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott break;
caa9e77dc369fea8df9ae2c598d3c83b7214c1cfDiego Colantoni }
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
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert 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.
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott if (timeReceived != nil && [timeReceived length] > 0) {
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Time stamp of the notification
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSDate *received = [NSDate dateWithTimeIntervalSince1970:[timeReceived doubleValue]];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Data map
f877f6ca2428244a6d0954a1dbef471577b32c60Diego Colantoni NSDictionary *dataMap;
f877f6ca2428244a6d0954a1dbef471577b32c60Diego Colantoni if (![FRASerialization deserializeJSON:data intoDictionary:&dataMap error:error]) {
f877f6ca2428244a6d0954a1dbef471577b32c60Diego Colantoni return nil;
f877f6ca2428244a6d0954a1dbef471577b32c60Diego Colantoni }
f877f6ca2428244a6d0954a1dbef471577b32c60Diego Colantoni
f877f6ca2428244a6d0954a1dbef471577b32c60Diego Colantoni // Data: Message ID
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSString *messageId = [dataMap valueForKey:NOTIFICATION_MESSAGE_ID];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Data: Challenge
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSString *challenge = [[NSString alloc] initWithData:[FRASerialization deserializeBytes:[dataMap valueForKey:NOTIFICATION_PUSH_CHALLENGE]] encoding:NSUTF8StringEncoding];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Data: TTL
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSTimeInterval ttl = [[dataMap valueForKey:NOTIFICATION_TIME_TO_LIVE] doubleValue];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott FRANotification *notification = [FRANotification notificationWithDatabase:identityDatabase
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott messageId:messageId
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott challenge:challenge
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott timeReceived:received
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott timeToLive:ttl
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott pending:pending
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott approved:approved];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott if (![newMechanism addNotification:notification error:error]) {
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott return nil;
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott }
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott }
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott } else {
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott @throw [FRAError createIllegalStateException:@"Invalid mechanism"];
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott }
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott }
5d37db6a3aca50ba14cba8909d3ae44f7d43e407Ken Stubbings
5d37db6a3aca50ba14cba8909d3ae44f7d43e407Ken Stubbings // As we have read the objects from the database, marked them as stored.
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott for (FRAIdentity* identity in identities) {
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott identity.stored = YES;
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott for (FRAMechanism *mechanism in identity.mechanisms) {
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott mechanism.stored = YES;
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott for (FRANotification *notification in mechanism.notifications) {
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott notification.stored = YES;
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott }
5d37db6a3aca50ba14cba8909d3ae44f7d43e407Ken Stubbings }
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott }
5d37db6a3aca50ba14cba8909d3ae44f7d43e407Ken Stubbings
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott
f877f6ca2428244a6d0954a1dbef471577b32c60Diego Colantoni return identities;
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott }
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott @finally {
5d37db6a3aca50ba14cba8909d3ae44f7d43e407Ken Stubbings [sqlDatabase closeConnectionToDatabase:database];
465ea459a87d4605e145d8f45b6a9c104b696e3bCraig McDonnell }
5d37db6a3aca50ba14cba8909d3ae44f7d43e407Ken Stubbings}
465ea459a87d4605e145d8f45b6a9c104b696e3bCraig McDonnell
465ea459a87d4605e145d8f45b6a9c104b696e3bCraig McDonnell@end