FRAModelsFromDatabase.m revision 0fc1bec9becddcbec0d26541dd7ef40b43c0a67b
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 "FRAOathCode.h"
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott#import "FRAIdentity.h"
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott#import "FRAModelObjectProtected.h"
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott#import "FRAModelsFromDatabase.h"
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott#import "FRANotification.h"
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott#import "FRAHotpOathMechanism.h"
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott#import "FRATotpOathMechanism.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*> *)allIdentitiesWithDatabase:(FRAFMDatabaseConnectionHelper *)sqlDatabase identityDatabase:(FRAIdentityDatabase *)identityDatabase identityModel:(FRAIdentityModel *)identityModel error:(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 if (error) {
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott *error = [FRAError createErrorForLastFailure:database];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott }
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott return nil;
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott }
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Output rows for debugging purposes.
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSLog(@"Reading all rows from the database:");
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSMutableArray* identities = [[NSMutableArray alloc] init];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott int row = 0;
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott while ([results next]) {
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Identity
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSString *issuer = [FRASerialization nullToEmpty:[results stringForColumn:@"issuer"]];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSString *accountName = [FRASerialization nullToEmpty:[results stringForColumn:@"accountName"]];
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert 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"]];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSInteger version = [results intForColumn:@"version"];
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert 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"]];
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 identityModel:identityModel
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:[FRAHotpOathMechanism mechanismType]]) {
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 deserializeSecret:secretValue];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Algorithm - String enumeration
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSString *algorithmValue = [optionsMap objectForKey:OATH_MECHANISM_ALGORITHM];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott CCHmacAlgorithm algorithm = [FRAOathCode fromString:algorithmValue];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Code Length - String value of Integer
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSString *codeLengthValue = [optionsMap objectForKey:OATH_MECHANISM_DIGITS];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott int codeLength = [[numberFormatter numberFromString:codeLengthValue] intValue];
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 FRAHotpOathMechanism *newMechanism = [FRAHotpOathMechanism mechanismWithDatabase:identityDatabase
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott identityModel:identityModel
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott secretKey:secret
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott HMACAlgorithm:algorithm
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott codeLength:codeLength
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott counter:counter];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Note: We are not de-duplicating OATH Mechanism because 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:[FRATotpOathMechanism mechanismType]]) {
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 = [FRAOathCode fromString:algorithmValue];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Code Length - String value of Integer
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSString *codeLengthValue = [optionsMap objectForKey:OATH_MECHANISM_DIGITS];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott int codeLength = [[numberFormatter numberFromString:codeLengthValue] 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
465ea459a87d4605e145d8f45b6a9c104b696e3bCraig McDonnell FRATotpOathMechanism *newMechanism = [FRATotpOathMechanism mechanismWithDatabase:identityDatabase
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott identityModel:identityModel
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott secretKey:secret
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott HMACAlgorithm:algorithm
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott codeLength:codeLength
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott period:period];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Note: We are not de-duplicating OATH Mechanism because 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:[FRAPushMechanism mechanismType]]) {
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];
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott // Auth Endpoint as string
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott NSString *authEndpointValue = [optionsMap objectForKey:PUSH_MECHANISM_AUTH_END_POINT];
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott // Version as string
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott NSString *versionString = [optionsMap objectForKey:PUSH_MECHANISM_VERSION];
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott NSInteger version = [[numberFormatter numberFromString:versionString] integerValue];
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott FRAPushMechanism *newMechanism = [FRAPushMechanism pushMechanismWithDatabase:identityDatabase
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott identityModel:identityModel
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott authEndpoint:authEndpointValue
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott secret:secretValue
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott version:version
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott mechanismIdentifier:mechanismUID];
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott // Check to see if we already have this PushMechanism present, otherwise add it in.
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott BOOL add = true;
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott for (FRAMechanism *mechanism in newIdentity.mechanisms) {
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott if ([mechanism isKindOfClass:[FRAPushMechanism class]]) {
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott FRAPushMechanism *pushMechanism = (FRAPushMechanism *)mechanism;
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott if ([pushMechanism.mechanismUID isEqualToString:newMechanism.mechanismUID]) {
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott newMechanism = pushMechanism;
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott add = false;
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott break;
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott }
465ea459a87d4605e145d8f45b6a9c104b696e3bCraig McDonnell }
465ea459a87d4605e145d8f45b6a9c104b696e3bCraig McDonnell }
465ea459a87d4605e145d8f45b6a9c104b696e3bCraig McDonnell
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott if (add) {
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott if (![newIdentity addMechanism:newMechanism error:error]) {
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott return nil;
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert 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 // Extract notifcation data from database
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott NSDate *dateTimeReceived = [NSDate dateWithTimeIntervalSince1970:[timeReceived doubleValue]];
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott NSDictionary *dataMap;
55abfb9b58693eddac5205e74aac84f50c9798d2Robert Wapshott if (![FRASerialization deserializeJSON:data intoDictionary:&dataMap error:error]) {
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott return nil;
55abfb9b58693eddac5205e74aac84f50c9798d2Robert Wapshott }
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott NSString *messageId = [dataMap valueForKey:NOTIFICATION_MESSAGE_ID];
55abfb9b58693eddac5205e74aac84f50c9798d2Robert Wapshott NSString *challenge = [[NSString alloc] initWithData:[FRASerialization deserializeBytes:[dataMap valueForKey:NOTIFICATION_PUSH_CHALLENGE]] encoding:NSUTF8StringEncoding];
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott NSTimeInterval ttl = [[dataMap valueForKey:NOTIFICATION_TIME_TO_LIVE] doubleValue];
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott NSString *loadBalancerCookieData = [dataMap valueForKey:NOTIFICATION_LOAD_BALANCER_COOKIE];
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott // recreate notificaiton
2ff6fc247a59e7bebd6f71595469a511fe7456efRobert Wapshott FRANotification *notification = [FRANotification notificationWithDatabase:identityDatabase
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott identityModel:identityModel
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott messageId:messageId
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott challenge:challenge
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott timeReceived:dateTimeReceived
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott timeToLive:ttl
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott loadBalancerCookieData:loadBalancerCookieData
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott pending:pending
721bb987c406979bcfe705fa1ca8d54497d40fcbRobert Wapshott approved:approved];
if (![newMechanism addNotification:notification error:error]) {
return nil;
}
}
} else {
@throw [FRAError createIllegalStateException:@"Invalid mechanism"];
}
}
// As we have read the objects from the database, marked them as stored.
for (FRAIdentity* identity in identities) {
identity.stored = YES;
for (FRAMechanism *mechanism in identity.mechanisms) {
mechanism.stored = YES;
for (FRANotification *notification in mechanism.notifications) {
notification.stored = YES;
}
}
}
return identities;
}
@finally {
[sqlDatabase closeConnectionToDatabase:database];
}
}
@end