2
0

Compare commits

..

5 Commits

Author SHA1 Message Date
Maarten Billemont
b2c688a1ce Always scope sites query to active user. 2020-09-03 14:31:10 -04:00
Maarten Billemont
aee1030758 Copy device identifier from macOS menu item. 2020-09-03 14:10:08 -04:00
Maarten Billemont
f665aeccc4 Load store synchronously to not return racy or invalid contexts. 2020-09-03 13:57:16 -04:00
Maarten Billemont
e58b9ef34f Fetch request syntax update. 2020-09-03 13:56:46 -04:00
Maarten Billemont
968de6026f Build fixes. 2020-09-03 13:56:10 -04:00
11 changed files with 82 additions and 64 deletions

View File

@@ -3024,7 +3024,6 @@
CLANG_WARN_OBJC_RECEIVER_WEAK = NO; CLANG_WARN_OBJC_RECEIVER_WEAK = NO;
CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = NO; CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = NO;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
@@ -3126,7 +3125,6 @@
CLANG_WARN_OBJC_RECEIVER_WEAK = NO; CLANG_WARN_OBJC_RECEIVER_WEAK = NO;
CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = NO; CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = NO;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
@@ -3202,7 +3200,7 @@
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_ARC = YES;
CODE_SIGN_ENTITLEMENTS = Source/Mac/MasterPassword.entitlements; CODE_SIGN_ENTITLEMENTS = Source/Mac/MasterPassword.entitlements;
CODE_SIGN_IDENTITY = "-"; CODE_SIGN_IDENTITY = "Apple Development";
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
GCC_PREFIX_HEADER = "Source/MasterPassword-Prefix.pch"; GCC_PREFIX_HEADER = "Source/MasterPassword-Prefix.pch";
@@ -3242,7 +3240,7 @@
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_ARC = YES;
CODE_SIGN_ENTITLEMENTS = Source/Mac/MasterPassword.entitlements; CODE_SIGN_ENTITLEMENTS = Source/Mac/MasterPassword.entitlements;
CODE_SIGN_IDENTITY = "-"; CODE_SIGN_IDENTITY = "Apple Development";
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
GCC_PREFIX_HEADER = "Source/MasterPassword-Prefix.pch"; GCC_PREFIX_HEADER = "Source/MasterPassword-Prefix.pch";

View File

@@ -88,7 +88,7 @@ static NSOperationQueue *_mpwQueue = nil;
- (BOOL)tryMigrateUser:(MPUserEntity *)user inContext:(NSManagedObjectContext *)moc { - (BOOL)tryMigrateUser:(MPUserEntity *)user inContext:(NSManagedObjectContext *)moc {
NSError *error = nil; NSError *error = nil;
NSFetchRequest *migrationRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPSiteEntity class] )]; NSFetchRequest *migrationRequest = [MPSiteEntity fetchRequest];
migrationRequest.predicate = [NSPredicate predicateWithFormat:@"version_ < %d AND user == %@", self.version, user]; migrationRequest.predicate = [NSPredicate predicateWithFormat:@"version_ < %d AND user == %@", self.version, user];
NSArray *migrationSites = [moc executeFetchRequest:migrationRequest error:&error]; NSArray *migrationSites = [moc executeFetchRequest:migrationRequest error:&error];
if (!migrationSites) { if (!migrationSites) {

View File

@@ -51,7 +51,6 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
+ (NSManagedObjectContext *)managedObjectContextForMainThreadIfReady { + (NSManagedObjectContext *)managedObjectContextForMainThreadIfReady {
NSAssert( [[NSThread currentThread] isMainThread], @"Can only access main MOC from the main thread." );
NSManagedObjectContext *mainManagedObjectContext = [[self get] mainManagedObjectContextIfReady]; NSManagedObjectContext *mainManagedObjectContext = [[self get] mainManagedObjectContextIfReady];
if (!mainManagedObjectContext || ![[NSThread currentThread] isMainThread]) if (!mainManagedObjectContext || ![[NSThread currentThread] isMainThread])
return nil; return nil;
@@ -155,7 +154,42 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
- (NSManagedObjectContext *)mainManagedObjectContextIfReady { - (NSManagedObjectContext *)mainManagedObjectContextIfReady {
NSAssert( [[NSThread currentThread] isMainThread], @"Can only access main MOC from the main thread." );
[self loadStore]; [self loadStore];
if (!self.mainManagedObjectContext && self.privateManagedObjectContext.persistentStoreCoordinator) {
self.mainManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
self.mainManagedObjectContext.parentContext = self.privateManagedObjectContext;
if (@available( iOS 10.0, macOS 10.12, * ))
self.mainManagedObjectContext.automaticallyMergesChangesFromParent = YES;
else
// When privateManagedObjectContext is saved, import the changes into mainManagedObjectContext.
PearlAddNotificationObserverTo( self.mainManagedObjectContext, NSManagedObjectContextDidSaveNotification,
self.privateManagedObjectContext, nil, ^(NSManagedObjectContext *mainContext, NSNotification *note) {
[mainContext performBlock:^{
@try {
[mainContext mergeChangesFromContextDidSaveNotification:note];
}
@catch (NSException *exception) {
err( @"While merging changes:\n%@", [exception fullDescription] );
}
}];
} );
#if TARGET_OS_IPHONE
PearlAddNotificationObserver( UIApplicationWillResignActiveNotification, UIApp, [NSOperationQueue mainQueue],
^(MPAppDelegate_Shared *self, NSNotification *note) {
[self.mainManagedObjectContext saveToStore];
} );
#else
PearlAddNotificationObserver( NSApplicationWillResignActiveNotification, NSApp, [NSOperationQueue mainQueue],
^(MPAppDelegate_Shared *self, NSNotification *note) {
[self.mainManagedObjectContext saveToStore];
} );
#endif
}
return self.mainManagedObjectContext; return self.mainManagedObjectContext;
} }
@@ -183,12 +217,12 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
} ); } );
// Do nothing if already fully set up, otherwise (re-)load the store. // Do nothing if already fully set up, otherwise (re-)load the store.
if (self.mainManagedObjectContext && self.privateManagedObjectContext) if ([self.storeCoordinator.persistentStores count])
return; return;
[self.storeQueue addOperationWithBlock:^{ NSOperation *storeOperation = [NSBlockOperation blockOperationWithBlock:^{
// Do nothing if already fully set up, otherwise (re-)load the store. // Do nothing if already fully set up, otherwise (re-)load the store.
if (self.mainManagedObjectContext && self.privateManagedObjectContext) if ([self.storeCoordinator.persistentStores count])
return; return;
// Unregister any existing observers and contexts. // Unregister any existing observers and contexts.
@@ -201,12 +235,6 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
[self.privateManagedObjectContext reset]; [self.privateManagedObjectContext reset];
self.privateManagedObjectContext = nil; self.privateManagedObjectContext = nil;
}]; }];
NSError *error = nil;
for (NSPersistentStore *store in self.storeCoordinator.persistentStores)
if (![self.storeCoordinator removePersistentStore:store error:&error] || error) {
MPError( error, @"Couldn't remove persistence store from coordinator." );
return;
}
// Don't load when the store is corrupted. // Don't load when the store is corrupted.
if ([self.storeCorrupted boolValue]) if ([self.storeCorrupted boolValue])
@@ -217,12 +245,10 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
// Create a new store coordinator. // Create a new store coordinator.
NSURL *localStoreURL = [self localStoreURL]; NSURL *localStoreURL = [self localStoreURL];
NSError *error = nil;
if (![[NSFileManager defaultManager] createDirectoryAtURL:[localStoreURL URLByDeletingLastPathComponent] if (![[NSFileManager defaultManager] createDirectoryAtURL:[localStoreURL URLByDeletingLastPathComponent]
withIntermediateDirectories:YES attributes:nil error:&error]) { withIntermediateDirectories:YES attributes:nil error:&error]) {
MPError( error, @"Couldn't create our application support directory." ); MPError( error, @"Couldn't create our application support directory." );
PearlRemoveNotificationObserversFrom( self.mainManagedObjectContext );
self.mainManagedObjectContext = nil;
self.privateManagedObjectContext = nil;
return; return;
} }
if (![self.storeCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:localStoreURL if (![self.storeCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:localStoreURL
@@ -232,9 +258,6 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
STORE_OPTIONS STORE_OPTIONS
} error:&error]) { } error:&error]) {
MPError( error, @"Failed to open store." ); MPError( error, @"Failed to open store." );
PearlRemoveNotificationObserversFrom( self.mainManagedObjectContext );
self.mainManagedObjectContext = nil;
self.privateManagedObjectContext = nil;
self.storeCorrupted = @YES; self.storeCorrupted = @YES;
[self handleCoordinatorError:error]; [self handleCoordinatorError:error];
return; return;
@@ -246,42 +269,14 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
self.privateManagedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy; self.privateManagedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy;
self.privateManagedObjectContext.persistentStoreCoordinator = self.storeCoordinator; self.privateManagedObjectContext.persistentStoreCoordinator = self.storeCoordinator;
self.mainManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
self.mainManagedObjectContext.parentContext = self.privateManagedObjectContext;
if (@available( iOS 10.0, macOS 10.12, * ))
self.mainManagedObjectContext.automaticallyMergesChangesFromParent = YES;
else
// When privateManagedObjectContext is saved, import the changes into mainManagedObjectContext.
PearlAddNotificationObserverTo( self.mainManagedObjectContext, NSManagedObjectContextDidSaveNotification,
self.privateManagedObjectContext, nil, ^(NSManagedObjectContext *mainContext, NSNotification *note) {
[mainContext performBlock:^{
@try {
[mainContext mergeChangesFromContextDidSaveNotification:note];
}
@catch (NSException *exception) {
err( @"While merging changes:\n%@", [exception fullDescription] );
}
}];
} );
#if TARGET_OS_IPHONE
PearlAddNotificationObserver( UIApplicationWillResignActiveNotification, UIApp, [NSOperationQueue mainQueue],
^(MPAppDelegate_Shared *self, NSNotification *note) {
[self.mainManagedObjectContext saveToStore];
} );
#else
PearlAddNotificationObserver( NSApplicationWillResignActiveNotification, NSApp, [NSOperationQueue mainQueue],
^(MPAppDelegate_Shared *self, NSNotification *note) {
[self.mainManagedObjectContext saveToStore];
} );
#endif
// Perform a data sanity check on the newly loaded store to find and fix any issues. // Perform a data sanity check on the newly loaded store to find and fix any issues.
if ([[MPConfig get].checkInconsistency boolValue]) if ([[MPConfig get].checkInconsistency boolValue])
[MPAppDelegate_Shared managedObjectContextPerformBlockAndWait:^(NSManagedObjectContext *context) { [MPAppDelegate_Shared managedObjectContextPerformBlockAndWait:^(NSManagedObjectContext *context) {
[self findAndFixInconsistenciesSaveInContext:context]; [self findAndFixInconsistenciesSaveInContext:context];
}]; }];
}]; }];
[self.storeQueue addOperations:@[ storeOperation ] waitUntilFinished:YES];
} }
- (void)retryCorruptStore { - (void)retryCorruptStore {
@@ -623,7 +618,7 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
// Find an existing user to update. // Find an existing user to update.
NSError *error = nil; NSError *error = nil;
NSFetchRequest *userFetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPUserEntity class] )]; NSFetchRequest *userFetchRequest = [MPUserEntity fetchRequest];
userFetchRequest.predicate = [NSPredicate predicateWithFormat:@"name == %@", @(importUser->fullName)]; userFetchRequest.predicate = [NSPredicate predicateWithFormat:@"name == %@", @(importUser->fullName)];
NSArray *users = [context executeFetchRequest:userFetchRequest error:&error]; NSArray *users = [context executeFetchRequest:userFetchRequest error:&error];
if (!users) if (!users)
@@ -661,7 +656,7 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
MPMarshalledSite *importSite = &importUser->sites[s]; MPMarshalledSite *importSite = &importUser->sites[s];
// Find an existing site to update. // Find an existing site to update.
NSFetchRequest *siteFetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPSiteEntity class] )]; NSFetchRequest *siteFetchRequest = [MPSiteEntity fetchRequest];
siteFetchRequest.predicate = [NSPredicate predicateWithFormat:@"name == %@ AND user == %@", @(importSite->siteName), user]; siteFetchRequest.predicate = [NSPredicate predicateWithFormat:@"name == %@ AND user == %@", @(importSite->siteName), user];
NSArray *existingSites = [context executeFetchRequest:siteFetchRequest error:&error]; NSArray *existingSites = [context executeFetchRequest:siteFetchRequest error:&error];
if (!existingSites) if (!existingSites)
@@ -735,9 +730,9 @@ PearlAssociatedObjectProperty( NSNumber*, StoreCorrupted, storeCorrupted );
return nil; return nil;
} }
for (NSString *feature in @[MPProductGenerateLogins, MPProductGenerateAnswers, MPProductOSIntegration, MPProductTouchID]) for (NSString *feature in @[ MPProductGenerateLogins, MPProductGenerateAnswers, MPProductOSIntegration, MPProductTouchID ])
if ([[MPAppDelegate_Shared get] isFeatureUnlocked:feature]) if ([[MPAppDelegate_Shared get] isFeatureUnlocked:feature])
mpw_marshal_data_set_str( digest( strf( @"%@/%@", user.name, feature )).UTF8String, exportFile->data, mpw_marshal_data_set_str( digest( strf( @"%@/%@", user.name, feature ) ).UTF8String, exportFile->data,
"user", "_ext_mpw", feature.UTF8String, nil ); "user", "_ext_mpw", feature.UTF8String, nil );
MPKey *key = [[MPKey alloc] initForFullName:user.name withMasterPassword:masterPassword]; MPKey *key = [[MPKey alloc] initForFullName:user.name withMasterPassword:masterPassword];

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="16096" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES"> <document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="16097.3" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies> <dependencies>
<deployment identifier="macosx"/> <deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="16096"/> <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="16097.3"/>
</dependencies> </dependencies>
<objects> <objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication"> <customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
@@ -199,6 +199,7 @@
</attributedString> </attributedString>
<modifierMask key="keyEquivalentModifierMask"/> <modifierMask key="keyEquivalentModifierMask"/>
</menuItem> </menuItem>
<menuItem isSeparatorItem="YES" id="lhE-aV-1P4"/>
<menuItem title="Diagnostics" id="GSN-f0-q7s"> <menuItem title="Diagnostics" id="GSN-f0-q7s">
<modifierMask key="keyEquivalentModifierMask"/> <modifierMask key="keyEquivalentModifierMask"/>
<connections> <connections>
@@ -216,6 +217,23 @@
</attributedString> </attributedString>
<modifierMask key="keyEquivalentModifierMask"/> <modifierMask key="keyEquivalentModifierMask"/>
</menuItem> </menuItem>
<menuItem title="Copy Device Identifier" id="c2c-Vy-iqg">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="copyIdentifier:" target="494" id="dDF-fR-z6h"/>
</connections>
</menuItem>
<menuItem title="Your anonymous device identifier allows support to find your diagnostic reports." enabled="NO" id="xMa-pq-Bqg">
<attributedString key="attributedTitle">
<fragment content="Your anonymous device identifier allows support to find your diagnostic reports.">
<attributes>
<font key="NSFont" size="11" name="Helvetica"/>
<paragraphStyle key="NSParagraphStyle" alignment="natural" lineBreakMode="wordWrapping" baseWritingDirection="natural" firstLineHeadIndent="8"/>
</attributes>
</fragment>
</attributedString>
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
</items> </items>
</menu> </menu>
</menuItem> </menuItem>

View File

@@ -42,6 +42,7 @@
- (IBAction)showPasswordWindow:(id)sender; - (IBAction)showPasswordWindow:(id)sender;
- (void)setLoginItemEnabled:(BOOL)enabled; - (void)setLoginItemEnabled:(BOOL)enabled;
- (IBAction)togglePreference:(id)sender; - (IBAction)togglePreference:(id)sender;
- (IBAction)copyIdentifier:(id)sender;
- (IBAction)newUser:(NSMenuItem *)sender; - (IBAction)newUser:(NSMenuItem *)sender;
- (IBAction)lock:(id)sender; - (IBAction)lock:(id)sender;
- (IBAction)terminate:(id)sender; - (IBAction)terminate:(id)sender;

View File

@@ -435,6 +435,12 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
[self updateMenuItems]; [self updateMenuItems];
} }
- (IBAction)copyIdentifier:(id)sender {
[[NSPasteboard generalPasteboard] declareTypes:@[ NSStringPboardType ] owner:nil];
if (![[NSPasteboard generalPasteboard] setString:[PearlKeyChain deviceIdentifier] forType:NSPasteboardTypeString])
wrn( @"Couldn't copy device identifier to pasteboard." );
}
- (IBAction)newUser:(NSMenuItem *)sender { - (IBAction)newUser:(NSMenuItem *)sender {
NSAlert *alert = [NSAlert new]; NSAlert *alert = [NSAlert new];
@@ -646,7 +652,7 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
self.deleteUserItem.toolTip = mainActiveUser? nil: @"First select the user to delete."; self.deleteUserItem.toolTip = mainActiveUser? nil: @"First select the user to delete.";
NSError *error = nil; NSError *error = nil;
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPUserEntity class] )]; NSFetchRequest *fetchRequest = [MPUserEntity fetchRequest];
fetchRequest.sortDescriptors = @[ [NSSortDescriptor sortDescriptorWithKey:@"lastUsed" ascending:NO] ]; fetchRequest.sortDescriptors = @[ [NSSortDescriptor sortDescriptorWithKey:@"lastUsed" ascending:NO] ];
NSArray *users = [mainContext executeFetchRequest:fetchRequest error:&error]; NSArray *users = [mainContext executeFetchRequest:fetchRequest error:&error];
if (!users) if (!users)

View File

@@ -213,12 +213,12 @@
- (BOOL)generated { - (BOOL)generated {
return self.type & MPResultTypeClassTemplate; return (self.type & MPResultTypeClassTemplate) == MPResultTypeClassTemplate;
} }
- (BOOL)stored { - (BOOL)stored {
return self.type & MPResultTypeClassStateful; return (self.type & MPResultTypeClassStateful) == MPResultTypeClassStateful;
} }
- (BOOL)transient { - (BOOL)transient {

View File

@@ -628,7 +628,7 @@
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) { [MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
prof_rewind( @"moc" ); prof_rewind( @"moc" );
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPSiteEntity class] )]; NSFetchRequest *fetchRequest = [MPSiteEntity fetchRequest];
fetchRequest.sortDescriptors = @[ [[NSSortDescriptor alloc] initWithKey:@"lastUsed" ascending:NO] ]; fetchRequest.sortDescriptors = @[ [[NSSortDescriptor alloc] initWithKey:@"lastUsed" ascending:NO] ];
fetchRequest.predicate = fetchRequest.predicate =
[NSPredicate predicateWithFormat:@"name LIKE[cd] %@ AND user == %@", queryPattern, [MPMacAppDelegate get].activeUserOID]; [NSPredicate predicateWithFormat:@"name LIKE[cd] %@ AND user == %@", queryPattern, [MPMacAppDelegate get].activeUserOID];

View File

@@ -423,6 +423,7 @@ typedef NS_OPTIONS( NSUInteger, MPPasswordsTips ) {
fetchRequest.sortDescriptors = @[ fetchRequest.sortDescriptors = @[
[[NSSortDescriptor alloc] initWithKey:NSStringFromSelector( @selector( lastUsed ) ) ascending:NO] [[NSSortDescriptor alloc] initWithKey:NSStringFromSelector( @selector( lastUsed ) ) ascending:NO]
]; ];
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"user == %@", [MPiOSAppDelegate get].activeUserOID];
(self.fetchedResultsController = [[NSFetchedResultsController alloc] (self.fetchedResultsController = [[NSFetchedResultsController alloc]
initWithFetchRequest:fetchRequest managedObjectContext:mainContext initWithFetchRequest:fetchRequest managedObjectContext:mainContext

View File

@@ -696,7 +696,7 @@ referenceSizeForFooterInSection:(NSInteger)section {
[self afterUpdatesMainQueue:^{ [self afterUpdatesMainQueue:^{
if (![MPiOSAppDelegate managedObjectContextForMainThreadPerformBlockAndWait:^(NSManagedObjectContext *mainContext) { if (![MPiOSAppDelegate managedObjectContextForMainThreadPerformBlockAndWait:^(NSManagedObjectContext *mainContext) {
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPUserEntity class] )]; NSFetchRequest *fetchRequest = [MPUserEntity fetchRequest];
fetchRequest.sortDescriptors = @[ fetchRequest.sortDescriptors = @[
[NSSortDescriptor sortDescriptorWithKey:NSStringFromSelector( @selector( lastUsed ) ) ascending:NO] [NSSortDescriptor sortDescriptorWithKey:NSStringFromSelector( @selector( lastUsed ) ) ascending:NO]
]; ];

View File

@@ -475,8 +475,7 @@ MP_LIBS_END
for (NSURLQueryItem *item in [NSURLComponents componentsWithString:[url absoluteString]].queryItems) for (NSURLQueryItem *item in [NSURLComponents componentsWithString:[url absoluteString]].queryItems)
if ([item.name isEqualToString:@"fullName"]) { if ([item.name isEqualToString:@"fullName"]) {
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) { [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
NSFetchRequest NSFetchRequest *fetchRequest = [MPUserEntity fetchRequest];
*fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPUserEntity class] )];
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"name == %@", item.value]; fetchRequest.predicate = [NSPredicate predicateWithFormat:@"name == %@", item.value];
NSArray *users = [context executeFetchRequest:fetchRequest error:nil]; NSArray *users = [context executeFetchRequest:fetchRequest error:nil];
[self migrateFor:users.firstObject]; [self migrateFor:users.firstObject];