FRAIdentityDatabaseSQLiteOperations.m revision 465ea459a87d4605e145d8f45b6a9c104b696e3b
0N/A/*
0N/A * The contents of this file are subject to the terms of the Common Development and
0N/A * Distribution License (the License). You may not use this file except in compliance with the
0N/A * License.
0N/A *
0N/A * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
0N/A * specific language governing permission and limitations under the License.
0N/A *
0N/A * When distributing Covered Software, include this CDDL Header Notice in each file and include
0N/A * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
0N/A * Header, with the fields enclosed by brackets [] replaced by your own identifying
0N/A * information: "Portions copyright [year] [name of copyright owner]".
0N/A *
0N/A * Copyright 2016 ForgeRock AS.
0N/A */
0N/A
0N/A#import "FMDatabase.h"
0N/A#import "FRAError.h"
0N/A#import "FRAHMACAlgorithm.h"
0N/A#import "FRAIdentity.h"
0N/A#import "FRAIdentityDatabaseSQLiteOperations.h"
0N/A#import "FRAMechanism.h"
0N/A#import "FRANotification.h"
0N/A#import "FRAOathCode.h"
0N/A#import "FRAOathMechanism.h"
0N/A#import "FRAPushMechanism.h"
0N/A#import "FRAFMDatabaseConnectionHelper.h"
0N/A#import "FRASerialization.h"
0N/A
0N/A@implementation FRAIdentityDatabaseSQLiteOperations {
0N/A FRAFMDatabaseConnectionHelper *sqlDatabase;
0N/A}
0N/A
0N/A#pragma mark -
0N/A#pragma Life cycle Functions
0N/A
0N/A- (instancetype)initWithDatabase:(FRAFMDatabaseConnectionHelper *)database {
0N/A self = [super init];
0N/A if (self) {
0N/A sqlDatabase = database;
0N/A }
0N/A return self;
0N/A}
0N/A
0N/A#pragma mark -
0N/A#pragma SQL Functions
0N/A
0N/A- (BOOL)performStatement:(NSString *)schema withValues:(NSArray *)values error:(NSError * __autoreleasing *)error {
0N/A // Get schema
0N/A NSString *sql = [FRAFMDatabaseConnectionHelper readSchema:schema withError:error];
0N/A if (sql == nil) {
0N/A return NO;
0N/A }
0N/A
0N/A // Open Database
0N/A FMDatabase *database;
0N/A @try {
0N/A database = [sqlDatabase getConnectionWithError:error];
0N/A if (database == nil) {
0N/A return NO;
0N/A }
0N/A
0N/A // Perform update
0N/A BOOL result = [database executeUpdate:sql values:values error:error];
0N/A NSLog(@"Result: %@\nValues: %@\nSQL: %@", result ? @"YES" : @"NO", values, sql);
0N/A return result;
0N/A }
0N/A @finally {
0N/A [sqlDatabase closeConnectionToDatabase:database];
0N/A }
0N/A}
0N/A
0N/A#pragma mark -
0N/A#pragma mark Identity Functions
0N/A
0N/A- (BOOL)insertIdentity:(FRAIdentity *)identity error:(NSError *__autoreleasing *)error {
0N/A NSMutableArray *arguments = [[NSMutableArray alloc] init];
0N/A // Issuer
0N/A [arguments addObject:[FRASerialization nonNilString:identity.issuer]];
0N/A
0N/A // Account Name
0N/A [arguments addObject:[FRASerialization nonNilString:identity.accountName]];
0N/A
0N/A // Image Blob
0N/A [arguments addObject:[NSNull null]];
0N/A
0N/A // Image URL
0N/A if (identity.image) {
0N/A NSURL *imageUrl = identity.image;
0N/A [arguments addObject:[imageUrl absoluteString]];
0N/A } else {
0N/A [arguments addObject:[NSNull null]];
0N/A }
0N/A
0N/A // Background Color
0N/A if (identity.backgroundColor) {
0N/A [arguments addObject:identity.backgroundColor];
0N/A } else {
0N/A [arguments addObject:[NSNull null]];
0N/A }
0N/A
0N/A return [self performStatement:@"insert_identity" withValues:arguments error:error];
0N/A}
0N/A
0N/A- (BOOL)deleteIdentity:(FRAIdentity *)identity error:(NSError *__autoreleasing *)error {
0N/A NSMutableArray* arguments = [[NSMutableArray alloc] init];
0N/A
0N/A // Issuer
0N/A [arguments addObject:[FRASerialization nonNilString:identity.issuer]];
0N/A
0N/A // Account Name
0N/A [arguments addObject:[FRASerialization nonNilString:identity.accountName]];
0N/A
0N/A return [self performStatement:@"delete_identity" withValues:arguments error:error];
0N/A}
0N/A
0N/A#pragma mark -
0N/A#pragma mark Mechanism Functions
0N/A
0N/A- (BOOL)insertMechanism:(FRAMechanism *)mechanism error:(NSError *__autoreleasing *)error {
0N/A NSMutableArray *arguments = [[NSMutableArray alloc] init];
0N/A
0N/A FRAIdentity *parent = mechanism.parent;
0N/A
0N/A // idIssuer
0N/A [arguments addObject:[FRASerialization nonNilString:parent.issuer]];
0N/A
0N/A // idAccountName
0N/A [arguments addObject:[FRASerialization nonNilString:parent.accountName]];
0N/A
0N/A // mechanismUID - Special case for PushMechanism
0N/A if ([mechanism isKindOfClass:[FRAOathMechanism class]]) {
0N/A [arguments addObject:[NSNull null]];
0N/A } else if ([mechanism isKindOfClass:[FRAPushMechanism class]]) {
0N/A FRAPushMechanism* pushMechanism = (FRAPushMechanism*)mechanism;
0N/A [arguments addObject:[FRASerialization nonNilString:pushMechanism.mechanismUID]];
0N/A } else {
0N/A @throw [FRAError createIllegalStateException:@"Unrecognised class of Mechanism"];
0N/A }
0N/A
0N/A // type
0N/A NSString *type;
0N/A if ([mechanism isKindOfClass:[FRAOathMechanism class]]) {
0N/A FRAOathMechanism *oathMechanism = (FRAOathMechanism *)mechanism;
0N/A type = oathMechanism.type;
0N/A } else if ([mechanism isKindOfClass:[FRAPushMechanism class]]) {
0N/A FRAPushMechanism *pushMechanism = (FRAPushMechanism *)mechanism;
0N/A type = pushMechanism.type;
0N/A } else {
0N/A @throw [FRAError createIllegalStateException:@"Unrecognised class of Mechanism"];
0N/A }
0N/A [arguments addObject:[FRASerialization nonNilString:type]];
0N/A
0N/A // Version
0N/A NSInteger version;
0N/A if ([mechanism isKindOfClass:[FRAOathMechanism class]]) {
0N/A FRAOathMechanism *oathMechanism = (FRAOathMechanism *)mechanism;
0N/A version = oathMechanism.version;
0N/A } else if ([mechanism isKindOfClass:[FRAPushMechanism class]]) {
0N/A FRAPushMechanism *pushMechanism = (FRAPushMechanism *)mechanism;
0N/A version = pushMechanism.version;
0N/A } else {
0N/A @throw [FRAError createIllegalStateException:@"Unrecognised class of Mechanism"];
0N/A }
0N/A [arguments addObject:[NSNumber numberWithInteger:version]];
0N/A
0N/A // Options
0N/A NSMutableDictionary *options = [[NSMutableDictionary alloc] init];
0N/A if ([mechanism isKindOfClass:[FRAOathMechanism class]]) {
0N/A FRAOathMechanism *oathMechanism = (FRAOathMechanism *)mechanism;
0N/A
0N/A // Secret Key
0N/A NSString *base64Key = [FRASerialization serializeBytes:oathMechanism.secretKey];
0N/A [options setObject:[FRASerialization nonNilString:base64Key] forKey:OATH_MECHANISM_SECRET];
0N/A
0N/A // Algorithm
0N/A NSString *algorithm = [FRAHMACAlgorithm asString:oathMechanism.algorithm];
0N/A [options setObject:[FRASerialization nonNilString:algorithm] forKey:OATH_MECHANISM_ALGORITHM];
0N/A
0N/A // Digits
0N/A NSString *digitsString = [[NSNumber numberWithUnsignedInteger:oathMechanism.digits] stringValue];
0N/A [options setObject:[FRASerialization nonNilString:digitsString] forKey:OATH_MECHANISM_DIGITS];
0N/A
0N/A // Period
0N/A NSString *periodString = [[NSNumber numberWithUnsignedInteger:oathMechanism.period] stringValue];
0N/A [options setObject:[FRASerialization nonNilString:periodString] forKey:OATH_MECHANISM_PERIOD];
0N/A
0N/A // Counter
0N/A NSString *counterString = [[NSNumber numberWithUnsignedLongLong:oathMechanism.counter] stringValue];
0N/A [options setObject:[FRASerialization nonNilString:counterString] forKey:OATH_MECHANISM_COUNTER];
0N/A
0N/A } else if ([mechanism isKindOfClass:[FRAPushMechanism class]]) {
0N/A
0N/A FRAPushMechanism *pushMechanism = (FRAPushMechanism *)mechanism;
0N/A
0N/A // Secret Key as String
0N/A [options setObject:[FRASerialization nonNilString:pushMechanism.secret] forKey:PUSH_MECHANISM_SECRET];
0N/A
0N/A // Auth Endpoint as String
0N/A [options setObject:[FRASerialization nonNilString:pushMechanism.authEndpoint] forKey:PUSH_MECHANISM_AUTH_END_POINT];
0N/A
0N/A // Version integer as String
0N/A NSString *versionString = [[NSNumber numberWithInteger:pushMechanism.version] stringValue];
0N/A [options setObject:[FRASerialization nonNilString:versionString] forKey:PUSH_MECHANISM_VERSION];
0N/A
0N/A } else {
0N/A @throw [FRAError createIllegalStateException:@"Unrecognised class of Mechanism"];
0N/A }
0N/A
0N/A // Convert options to JSON
0N/A NSString *jsonString;
0N/A if (![FRASerialization serializeMap:options intoString:&jsonString error:error]) {
0N/A return NO;
0N/A }
0N/A [arguments addObject:jsonString];
0N/A
0N/A return [self performStatement:@"insert_mechanism" withValues:arguments error:error];
0N/A}
0N/A
0N/A- (BOOL)deleteMechanism:(FRAMechanism *)mechanism error:(NSError *__autoreleasing *)error {
0N/A NSMutableArray *arguments = [[NSMutableArray alloc] init];
0N/A
0N/A FRAIdentity *parent = mechanism.parent;
0N/A
0N/A // Issuer
0N/A [arguments addObject:[FRASerialization nonNilString:parent.issuer]];
0N/A
0N/A // Account Name
0N/A [arguments addObject:[FRASerialization nonNilString:parent.accountName]];
0N/A
0N/A // Type
0N/A NSString *type;
0N/A if ([mechanism isKindOfClass:[FRAOathMechanism class]]) {
0N/A FRAOathMechanism *oathMechanism = (FRAOathMechanism *)mechanism;
0N/A type = oathMechanism.type;
0N/A } else if ([mechanism isKindOfClass:[FRAPushMechanism class]]) {
0N/A FRAPushMechanism *pushMechanism = (FRAPushMechanism *)mechanism;
0N/A type = pushMechanism.type;
0N/A } else {
0N/A @throw [FRAError createIllegalStateException:@"Unrecognised class of Mechanism"];
0N/A }
0N/A [arguments addObject:[FRASerialization nonNilString:type]];
0N/A
0N/A return [self performStatement:@"delete_mechanism" withValues:arguments error:error];
0N/A}
0N/A
0N/A- (BOOL)updateMechanism:(FRAMechanism *)mechanism error:(NSError *__autoreleasing *)error {
0N/A return [self insertMechanism:mechanism error:error];
0N/A}
0N/A
0N/A#pragma mark -
0N/A#pragma mark Notification Functions
0N/A
0N/A- (BOOL)insertNotification:(FRANotification *)notification error:(NSError *__autoreleasing *)error {
0N/A NSMutableArray* arguments = [[NSMutableArray alloc] init];
0N/A
0N/A FRAMechanism *parent = notification.parent;
0N/A // mechanismUID
0N/A NSString *mechanismUID;
0N/A if ([parent isKindOfClass:[FRAOathMechanism class]]) {
0N/A mechanismUID = nil;
0N/A } else if ([parent isKindOfClass:[FRAPushMechanism class]]) {
0N/A FRAPushMechanism *pushMechanism = (FRAPushMechanism *)parent;
0N/A mechanismUID = pushMechanism.mechanismUID;
0N/A } else {
0N/A @throw [[NSException alloc] initWithName:@"Illegal State" reason:@"Unrecognised class of Mechanism" userInfo:nil];
0N/A }
0N/A [arguments addObject:[FRASerialization nonNilString:mechanismUID]];
0N/A
0N/A // timeReceived
0N/A [arguments addObject:[FRASerialization nonNilDate:notification.timeReceived]];
0N/A
0N/A // timeExpired
0N/A [arguments addObject:[FRASerialization nonNilDate:notification.timeExpired]];
0N/A
0N/A // Data Json Map
0N/A NSMutableDictionary *dataMap = [[NSMutableDictionary alloc] init];
0N/A
0N/A // Data: Message ID
0N/A [dataMap setObject:notification.messageId forKey:NOTIFICATION_MESSAGE_ID];
0N/A
0N/A // Data: Push Challenge
0N/A [dataMap setObject:notification.challenge forKey:NOTIFICATION_PUSH_CHALLENGE];
0N/A
0N/A // Data: Time to Live
0N/A NSString *ttlString = [NSString stringWithFormat:@"%f", notification.timeToLive];
0N/A [dataMap setObject:ttlString forKey:NOTIFICATION_TIME_TO_LIVE];
0N/A
0N/A // Convert map to JSON
0N/A NSString *jsonString;
0N/A if (![FRASerialization serializeMap:dataMap intoString:&jsonString error:error]) {
0N/A return NO;
0N/A }
0N/A [arguments addObject:jsonString];
0N/A
0N/A // pending
0N/A [arguments addObject:[NSNumber numberWithBool:[notification isPending]]];
0N/A
0N/A // approved
0N/A [arguments addObject:[NSNumber numberWithBool:[notification isApproved]]];
0N/A
0N/A return [self performStatement:@"insert_notification" withValues:arguments error:error];
0N/A}
0N/A
0N/A- (BOOL)deleteNotification:(FRANotification *)notification error:(NSError *__autoreleasing *)error {
0N/A NSMutableArray *arguments = [[NSMutableArray alloc] init];
0N/A
0N/A FRAMechanism *parent = notification.parent;
0N/A
0N/A // mechanismUID
0N/A NSString *mechanismUID;
0N/A if ([parent isKindOfClass:[FRAOathMechanism class]]) {
0N/A mechanismUID = nil;
0N/A } else if ([parent isKindOfClass:[FRAPushMechanism class]]) {
0N/A FRAPushMechanism *pushMechanism = (FRAPushMechanism *)parent;
0N/A mechanismUID = pushMechanism.mechanismUID;
0N/A } else {
0N/A @throw [[NSException alloc] initWithName:@"Illegal State" reason:@"Unrecognised class of Mechanism" userInfo:nil];
0N/A }
0N/A [arguments addObject:[FRASerialization nonNilString:mechanismUID]];
0N/A
0N/A // timeReceived
0N/A [arguments addObject:[FRASerialization nonNilDate:notification.timeReceived]];
0N/A
0N/A return [self performStatement:@"delete_notification" withValues:arguments error:error];
0N/A}
0N/A
0N/A- (BOOL)updateNotification:(FRANotification *)notification error:(NSError *__autoreleasing *)error {
0N/A return [self insertNotification:notification error:error];
0N/A}
0N/A
0N/A
0N/A@end
0N/A