mirror of
https://github.com/MacPass/MacPass.git
synced 2025-12-14 00:02:28 +00:00
Changed outline view to display the root node as a normal node and added a separate Group header
This commit is contained in:
@@ -73,6 +73,7 @@
|
|||||||
4C5A11FE1708DE8700223D8A /* MPPasswordCreatorViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C5A11FC1708DE8700223D8A /* MPPasswordCreatorViewController.m */; };
|
4C5A11FE1708DE8700223D8A /* MPPasswordCreatorViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C5A11FC1708DE8700223D8A /* MPPasswordCreatorViewController.m */; };
|
||||||
4C5A11FF1708DE8800223D8A /* PasswordCreatorView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4C5A11FD1708DE8700223D8A /* PasswordCreatorView.xib */; };
|
4C5A11FF1708DE8800223D8A /* PasswordCreatorView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4C5A11FD1708DE8700223D8A /* PasswordCreatorView.xib */; };
|
||||||
4C5BF67B175C01F300D53DF7 /* MPUppercaseStringValueTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C5BF67A175C01F300D53DF7 /* MPUppercaseStringValueTransformer.m */; };
|
4C5BF67B175C01F300D53DF7 /* MPUppercaseStringValueTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C5BF67A175C01F300D53DF7 /* MPUppercaseStringValueTransformer.m */; };
|
||||||
|
4C5EC302177B700D00DA955B /* MPRootAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C5EC301177B700D00DA955B /* MPRootAdapter.m */; };
|
||||||
4C61EA0316D2FD0800AC519E /* MPOutlineViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C61EA0216D2FD0800AC519E /* MPOutlineViewController.m */; };
|
4C61EA0316D2FD0800AC519E /* MPOutlineViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C61EA0216D2FD0800AC519E /* MPOutlineViewController.m */; };
|
||||||
4C61EA0516D2FFE200AC519E /* OutlineView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4C61EA0416D2FFE200AC519E /* OutlineView.xib */; };
|
4C61EA0516D2FFE200AC519E /* OutlineView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4C61EA0416D2FFE200AC519E /* OutlineView.xib */; };
|
||||||
4C65C79C16DD283900E32CFF /* MPToolbarButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C65C79B16DD283900E32CFF /* MPToolbarButton.m */; };
|
4C65C79C16DD283900E32CFF /* MPToolbarButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C65C79B16DD283900E32CFF /* MPToolbarButton.m */; };
|
||||||
@@ -303,6 +304,8 @@
|
|||||||
4C5A11FD1708DE8700223D8A /* PasswordCreatorView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PasswordCreatorView.xib; sourceTree = "<group>"; };
|
4C5A11FD1708DE8700223D8A /* PasswordCreatorView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PasswordCreatorView.xib; sourceTree = "<group>"; };
|
||||||
4C5BF679175C01F300D53DF7 /* MPUppercaseStringValueTransformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPUppercaseStringValueTransformer.h; sourceTree = "<group>"; };
|
4C5BF679175C01F300D53DF7 /* MPUppercaseStringValueTransformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPUppercaseStringValueTransformer.h; sourceTree = "<group>"; };
|
||||||
4C5BF67A175C01F300D53DF7 /* MPUppercaseStringValueTransformer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPUppercaseStringValueTransformer.m; sourceTree = "<group>"; };
|
4C5BF67A175C01F300D53DF7 /* MPUppercaseStringValueTransformer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPUppercaseStringValueTransformer.m; sourceTree = "<group>"; };
|
||||||
|
4C5EC300177B700D00DA955B /* MPRootAdapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPRootAdapter.h; sourceTree = "<group>"; };
|
||||||
|
4C5EC301177B700D00DA955B /* MPRootAdapter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPRootAdapter.m; sourceTree = "<group>"; };
|
||||||
4C61EA0116D2FD0800AC519E /* MPOutlineViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPOutlineViewController.h; sourceTree = "<group>"; };
|
4C61EA0116D2FD0800AC519E /* MPOutlineViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPOutlineViewController.h; sourceTree = "<group>"; };
|
||||||
4C61EA0216D2FD0800AC519E /* MPOutlineViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPOutlineViewController.m; sourceTree = "<group>"; };
|
4C61EA0216D2FD0800AC519E /* MPOutlineViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPOutlineViewController.m; sourceTree = "<group>"; };
|
||||||
4C61EA0416D2FFE200AC519E /* OutlineView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = OutlineView.xib; sourceTree = "<group>"; };
|
4C61EA0416D2FFE200AC519E /* OutlineView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = OutlineView.xib; sourceTree = "<group>"; };
|
||||||
@@ -784,6 +787,8 @@
|
|||||||
6E719715172058BA00E4C5FC /* MPDatabaseVersion.h */,
|
6E719715172058BA00E4C5FC /* MPDatabaseVersion.h */,
|
||||||
4CE5B548173AFBA700207B39 /* MPDocument.h */,
|
4CE5B548173AFBA700207B39 /* MPDocument.h */,
|
||||||
4CE5B549173AFBA700207B39 /* MPDocument.m */,
|
4CE5B549173AFBA700207B39 /* MPDocument.m */,
|
||||||
|
4C5EC300177B700D00DA955B /* MPRootAdapter.h */,
|
||||||
|
4C5EC301177B700D00DA955B /* MPRootAdapter.m */,
|
||||||
);
|
);
|
||||||
name = Model;
|
name = Model;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -1426,6 +1431,7 @@
|
|||||||
4C2724DA17790E7C00FD8456 /* NSMutableData+Base64.m in Sources */,
|
4C2724DA17790E7C00FD8456 /* NSMutableData+Base64.m in Sources */,
|
||||||
4C2A6134177A1D5F00C9826C /* KPLErrorCodes.m in Sources */,
|
4C2A6134177A1D5F00C9826C /* KPLErrorCodes.m in Sources */,
|
||||||
4CD5D705177A5F3300100649 /* MPDocumentSettingsWindowController.m in Sources */,
|
4CD5D705177A5F3300100649 /* MPDocumentSettingsWindowController.m in Sources */,
|
||||||
|
4C5EC302177B700D00DA955B /* MPRootAdapter.m in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1220,11 +1220,6 @@
|
|||||||
<reference key="object" ref="943587685"/>
|
<reference key="object" ref="943587685"/>
|
||||||
<reference key="parent" ref="222890410"/>
|
<reference key="parent" ref="222890410"/>
|
||||||
</object>
|
</object>
|
||||||
<object class="IBObjectRecord">
|
|
||||||
<int key="objectID">537</int>
|
|
||||||
<reference key="object" ref="19198291"/>
|
|
||||||
<reference key="parent" ref="1005"/>
|
|
||||||
</object>
|
|
||||||
<object class="IBObjectRecord">
|
<object class="IBObjectRecord">
|
||||||
<int key="objectID">630</int>
|
<int key="objectID">630</int>
|
||||||
<reference key="object" ref="1066302408"/>
|
<reference key="object" ref="1066302408"/>
|
||||||
@@ -1253,11 +1248,6 @@
|
|||||||
<reference key="object" ref="476689522"/>
|
<reference key="object" ref="476689522"/>
|
||||||
<reference key="parent" ref="60918609"/>
|
<reference key="parent" ref="60918609"/>
|
||||||
</object>
|
</object>
|
||||||
<object class="IBObjectRecord">
|
|
||||||
<int key="objectID">721</int>
|
|
||||||
<reference key="object" ref="528706521"/>
|
|
||||||
<reference key="parent" ref="1005"/>
|
|
||||||
</object>
|
|
||||||
<object class="IBObjectRecord">
|
<object class="IBObjectRecord">
|
||||||
<int key="objectID">759</int>
|
<int key="objectID">759</int>
|
||||||
<reference key="object" ref="376978074"/>
|
<reference key="object" ref="376978074"/>
|
||||||
@@ -1268,11 +1258,6 @@
|
|||||||
<reference key="object" ref="871797750"/>
|
<reference key="object" ref="871797750"/>
|
||||||
<reference key="parent" ref="326334884"/>
|
<reference key="parent" ref="326334884"/>
|
||||||
</object>
|
</object>
|
||||||
<object class="IBObjectRecord">
|
|
||||||
<int key="objectID">788</int>
|
|
||||||
<reference key="object" ref="772519144"/>
|
|
||||||
<reference key="parent" ref="60918609"/>
|
|
||||||
</object>
|
|
||||||
<object class="IBObjectRecord">
|
<object class="IBObjectRecord">
|
||||||
<int key="objectID">784</int>
|
<int key="objectID">784</int>
|
||||||
<reference key="object" ref="1014678196"/>
|
<reference key="object" ref="1014678196"/>
|
||||||
@@ -1298,16 +1283,6 @@
|
|||||||
<reference key="object" ref="1063893674"/>
|
<reference key="object" ref="1063893674"/>
|
||||||
<reference key="parent" ref="1005"/>
|
<reference key="parent" ref="1005"/>
|
||||||
</object>
|
</object>
|
||||||
<object class="IBObjectRecord">
|
|
||||||
<int key="objectID">799</int>
|
|
||||||
<reference key="object" ref="250630005"/>
|
|
||||||
<reference key="parent" ref="1005"/>
|
|
||||||
</object>
|
|
||||||
<object class="IBObjectRecord">
|
|
||||||
<int key="objectID">800</int>
|
|
||||||
<reference key="object" ref="213536579"/>
|
|
||||||
<reference key="parent" ref="1005"/>
|
|
||||||
</object>
|
|
||||||
<object class="IBObjectRecord">
|
<object class="IBObjectRecord">
|
||||||
<int key="objectID">801</int>
|
<int key="objectID">801</int>
|
||||||
<reference key="object" ref="806133159"/>
|
<reference key="object" ref="806133159"/>
|
||||||
@@ -1351,6 +1326,31 @@
|
|||||||
<reference key="object" ref="287888619"/>
|
<reference key="object" ref="287888619"/>
|
||||||
<reference key="parent" ref="60918609"/>
|
<reference key="parent" ref="60918609"/>
|
||||||
</object>
|
</object>
|
||||||
|
<object class="IBObjectRecord">
|
||||||
|
<int key="objectID">537</int>
|
||||||
|
<reference key="object" ref="19198291"/>
|
||||||
|
<reference key="parent" ref="1005"/>
|
||||||
|
</object>
|
||||||
|
<object class="IBObjectRecord">
|
||||||
|
<int key="objectID">721</int>
|
||||||
|
<reference key="object" ref="528706521"/>
|
||||||
|
<reference key="parent" ref="1005"/>
|
||||||
|
</object>
|
||||||
|
<object class="IBObjectRecord">
|
||||||
|
<int key="objectID">800</int>
|
||||||
|
<reference key="object" ref="213536579"/>
|
||||||
|
<reference key="parent" ref="1005"/>
|
||||||
|
</object>
|
||||||
|
<object class="IBObjectRecord">
|
||||||
|
<int key="objectID">799</int>
|
||||||
|
<reference key="object" ref="250630005"/>
|
||||||
|
<reference key="parent" ref="1005"/>
|
||||||
|
</object>
|
||||||
|
<object class="IBObjectRecord">
|
||||||
|
<int key="objectID">788</int>
|
||||||
|
<reference key="object" ref="772519144"/>
|
||||||
|
<reference key="parent" ref="60918609"/>
|
||||||
|
</object>
|
||||||
</array>
|
</array>
|
||||||
</object>
|
</object>
|
||||||
<dictionary class="NSMutableDictionary" key="flattenedProperties">
|
<dictionary class="NSMutableDictionary" key="flattenedProperties">
|
||||||
@@ -1471,18 +1471,17 @@
|
|||||||
<nil key="activeLocalization"/>
|
<nil key="activeLocalization"/>
|
||||||
<dictionary class="NSMutableDictionary" key="localizations"/>
|
<dictionary class="NSMutableDictionary" key="localizations"/>
|
||||||
<nil key="sourceID"/>
|
<nil key="sourceID"/>
|
||||||
<int key="maxID">810</int>
|
<int key="maxID">814</int>
|
||||||
</object>
|
</object>
|
||||||
<object class="IBClassDescriber" key="IBDocument.Classes">
|
<object class="IBClassDescriber" key="IBDocument.Classes">
|
||||||
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
|
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
|
||||||
<object class="IBPartialClassDescription">
|
<object class="IBPartialClassDescription">
|
||||||
<string key="className">MPGeneralSettingsController</string>
|
<string key="className">MPGeneralSettingsController</string>
|
||||||
<string key="superclassName">NSViewController</string>
|
<string key="superclassName">MPViewController</string>
|
||||||
<dictionary class="NSMutableDictionary" key="outlets">
|
<dictionary class="NSMutableDictionary" key="outlets">
|
||||||
<string key="clearPasteboardOnQuitCheckButton">NSButton</string>
|
<string key="clearPasteboardOnQuitCheckButton">NSButton</string>
|
||||||
<string key="clearPasteboardTimeoutPopup">NSPopUpButton</string>
|
<string key="clearPasteboardTimeoutPopup">NSPopUpButton</string>
|
||||||
<string key="idleTimeOutPopup">NSPopUpButton</string>
|
<string key="idleTimeOutPopup">NSPopUpButton</string>
|
||||||
<string key="imageView">NSImageView</string>
|
|
||||||
<string key="lockOnSleepCheckButton">NSButton</string>
|
<string key="lockOnSleepCheckButton">NSButton</string>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
|
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
|
||||||
@@ -1498,10 +1497,6 @@
|
|||||||
<string key="name">idleTimeOutPopup</string>
|
<string key="name">idleTimeOutPopup</string>
|
||||||
<string key="candidateClassName">NSPopUpButton</string>
|
<string key="candidateClassName">NSPopUpButton</string>
|
||||||
</object>
|
</object>
|
||||||
<object class="IBToOneOutletInfo" key="imageView">
|
|
||||||
<string key="name">imageView</string>
|
|
||||||
<string key="candidateClassName">NSImageView</string>
|
|
||||||
</object>
|
|
||||||
<object class="IBToOneOutletInfo" key="lockOnSleepCheckButton">
|
<object class="IBToOneOutletInfo" key="lockOnSleepCheckButton">
|
||||||
<string key="name">lockOnSleepCheckButton</string>
|
<string key="name">lockOnSleepCheckButton</string>
|
||||||
<string key="candidateClassName">NSButton</string>
|
<string key="candidateClassName">NSButton</string>
|
||||||
@@ -1512,6 +1507,14 @@
|
|||||||
<string key="minorKey">./Classes/MPGeneralSettingsController.h</string>
|
<string key="minorKey">./Classes/MPGeneralSettingsController.h</string>
|
||||||
</object>
|
</object>
|
||||||
</object>
|
</object>
|
||||||
|
<object class="IBPartialClassDescription">
|
||||||
|
<string key="className">MPViewController</string>
|
||||||
|
<string key="superclassName">NSViewController</string>
|
||||||
|
<object class="IBClassDescriptionSource" key="sourceIdentifier">
|
||||||
|
<string key="majorKey">IBProjectSource</string>
|
||||||
|
<string key="minorKey">./Classes/MPViewController.h</string>
|
||||||
|
</object>
|
||||||
|
</object>
|
||||||
<object class="IBPartialClassDescription">
|
<object class="IBPartialClassDescription">
|
||||||
<string key="className">NSLayoutConstraint</string>
|
<string key="className">NSLayoutConstraint</string>
|
||||||
<string key="superclassName">NSObject</string>
|
<string key="superclassName">NSObject</string>
|
||||||
|
|||||||
@@ -10,6 +10,6 @@
|
|||||||
|
|
||||||
@interface Kdb3Tree (NewTree)
|
@interface Kdb3Tree (NewTree)
|
||||||
|
|
||||||
+ (Kdb3Tree *)newTemplateTree;
|
+ (Kdb3Tree *)templateTree;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
@implementation Kdb3Tree (NewTree)
|
@implementation Kdb3Tree (NewTree)
|
||||||
|
|
||||||
+ (Kdb3Tree *)newTemplateTree {
|
+ (Kdb3Tree *)templateTree {
|
||||||
Kdb3Tree *tree = [[Kdb3Tree alloc] init];
|
Kdb3Tree *tree = [[Kdb3Tree alloc] init];
|
||||||
|
|
||||||
Kdb3Group *rootGroup = [[Kdb3Group alloc] init];
|
Kdb3Group *rootGroup = [[Kdb3Group alloc] init];
|
||||||
@@ -49,7 +49,7 @@
|
|||||||
|
|
||||||
[rootGroup release];
|
[rootGroup release];
|
||||||
|
|
||||||
return tree;
|
return [tree autorelease];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -10,6 +10,6 @@
|
|||||||
|
|
||||||
@interface Kdb4Tree (NewTree)
|
@interface Kdb4Tree (NewTree)
|
||||||
|
|
||||||
+(Kdb4Tree *)newTemplateTree;
|
+(Kdb4Tree *)templateTree;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
@implementation Kdb4Tree (NewTree)
|
@implementation Kdb4Tree (NewTree)
|
||||||
|
|
||||||
+ (Kdb4Tree *)newTemplateTree {
|
+ (Kdb4Tree *)templateTree {
|
||||||
NSDate *currentTime = [NSDate date];
|
NSDate *currentTime = [NSDate date];
|
||||||
|
|
||||||
Kdb4Tree *tree = [[Kdb4Tree alloc] init];
|
Kdb4Tree *tree = [[Kdb4Tree alloc] init];
|
||||||
@@ -71,7 +71,7 @@
|
|||||||
group.image = 37;
|
group.image = 37;
|
||||||
[parentGroup addGroup:group];
|
[parentGroup addGroup:group];
|
||||||
|
|
||||||
return tree;
|
return [tree autorelease];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ APPKIT_EXTERN NSString *const MPDocumentGroupKey;
|
|||||||
@class UUID;
|
@class UUID;
|
||||||
@class Binary;
|
@class Binary;
|
||||||
@class BinaryRef;
|
@class BinaryRef;
|
||||||
|
@class MPRootAdapter;
|
||||||
|
|
||||||
@interface MPDocument : NSDocument
|
@interface MPDocument : NSDocument
|
||||||
|
|
||||||
@@ -34,11 +35,13 @@ APPKIT_EXTERN NSString *const MPDocumentGroupKey;
|
|||||||
@property (assign, getter = isLocked) BOOL locked;
|
@property (assign, getter = isLocked) BOOL locked;
|
||||||
/* true, if document is loaded and decrypted (tree is loaded) */
|
/* true, if document is loaded and decrypted (tree is loaded) */
|
||||||
@property (assign, readonly, getter = isDecrypted) BOOL decrypted;
|
@property (assign, readonly, getter = isDecrypted) BOOL decrypted;
|
||||||
@property (retain, readonly) KdbTree *tree;
|
@property (retain, readonly, nonatomic) KdbTree *tree;
|
||||||
@property (assign, readonly, nonatomic) KdbGroup *root;
|
@property (assign, readonly, nonatomic) KdbGroup *root;
|
||||||
|
@property (readonly, retain) MPRootAdapter *rootAdapter;
|
||||||
@property (nonatomic, retain) NSString *password;
|
@property (nonatomic, retain) NSString *password;
|
||||||
@property (nonatomic, retain) NSURL *key;
|
@property (nonatomic, retain) NSURL *key;
|
||||||
@property (assign, readonly) MPDatabaseVersion version;
|
@property (assign, readonly) MPDatabaseVersion version;
|
||||||
|
@property (assign, readonly, getter = isReadOnly) BOOL readOnly;
|
||||||
|
|
||||||
- (id)initWithVersion:(MPDatabaseVersion)version;
|
- (id)initWithVersion:(MPDatabaseVersion)version;
|
||||||
- (BOOL)decryptWithPassword:(NSString *)password keyFileURL:(NSURL *)keyFileURL;
|
- (BOOL)decryptWithPassword:(NSString *)password keyFileURL:(NSURL *)keyFileURL;
|
||||||
|
|||||||
@@ -12,7 +12,10 @@
|
|||||||
#import "Kdb3Node.h"
|
#import "Kdb3Node.h"
|
||||||
#import "Kdb4Node.h"
|
#import "Kdb4Node.h"
|
||||||
#import "KdbPassword.h"
|
#import "KdbPassword.h"
|
||||||
|
|
||||||
#import "MPDatabaseVersion.h"
|
#import "MPDatabaseVersion.h"
|
||||||
|
#import "MPRootAdapter.h"
|
||||||
|
|
||||||
#import "KdbGroup+Undo.h"
|
#import "KdbGroup+Undo.h"
|
||||||
#import "KdbGroup+KVOAdditions.h"
|
#import "KdbGroup+KVOAdditions.h"
|
||||||
#import "KdbGroup+MPTreeTools.h"
|
#import "KdbGroup+MPTreeTools.h"
|
||||||
@@ -30,14 +33,22 @@ NSString *const MPDocumentEntryKey = @"MPDocumentEntryKey";
|
|||||||
NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey";
|
NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey";
|
||||||
|
|
||||||
|
|
||||||
@interface MPDocument ()
|
@interface MPDocument () {
|
||||||
|
@private
|
||||||
|
BOOL _didLockFile;
|
||||||
|
}
|
||||||
|
|
||||||
@property (assign, nonatomic) BOOL secured;
|
|
||||||
@property (retain) KdbTree *tree;
|
@property (retain, nonatomic) KdbTree *tree;
|
||||||
@property (assign, nonatomic) KdbGroup *root;
|
@property (assign, nonatomic) KdbGroup *root;
|
||||||
@property (nonatomic, readonly) KdbPassword *passwordHash;
|
@property (nonatomic, readonly) KdbPassword *passwordHash;
|
||||||
@property (assign) MPDatabaseVersion version;
|
@property (assign) MPDatabaseVersion version;
|
||||||
|
|
||||||
|
@property (assign, nonatomic) BOOL secured;
|
||||||
@property (assign) BOOL decrypted;
|
@property (assign) BOOL decrypted;
|
||||||
|
@property (assign) BOOL readOnly;
|
||||||
|
|
||||||
|
@property (retain) NSURL *lockFileURL;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@@ -52,15 +63,18 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey";
|
|||||||
- (id)initWithVersion:(MPDatabaseVersion)version {
|
- (id)initWithVersion:(MPDatabaseVersion)version {
|
||||||
self = [super init];
|
self = [super init];
|
||||||
if(self) {
|
if(self) {
|
||||||
|
_didLockFile = NO;
|
||||||
_decrypted = YES;
|
_decrypted = YES;
|
||||||
_secured = NO;
|
_secured = NO;
|
||||||
_locked = NO;
|
_locked = NO;
|
||||||
|
_readOnly = NO;
|
||||||
|
_rootAdapter = [[MPRootAdapter alloc] init];
|
||||||
switch(version) {
|
switch(version) {
|
||||||
case MPDatabaseVersion3:
|
case MPDatabaseVersion3:
|
||||||
_tree = [Kdb3Tree newTemplateTree];
|
self.tree = [Kdb3Tree templateTree];
|
||||||
break;
|
break;
|
||||||
case MPDatabaseVersion4:
|
case MPDatabaseVersion4:
|
||||||
_tree = [Kdb4Tree newTemplateTree];
|
self.tree = [Kdb4Tree templateTree];
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
[self release];
|
[self release];
|
||||||
@@ -71,9 +85,12 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey";
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)dealloc {
|
- (void)dealloc {
|
||||||
|
[self _cleanupLock];
|
||||||
[_tree release];
|
[_tree release];
|
||||||
[_password release];
|
[_password release];
|
||||||
[_key release];
|
[_key release];
|
||||||
|
[_lockFileURL release];
|
||||||
|
[_rootAdapter release];
|
||||||
[super dealloc];
|
[super dealloc];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,12 +116,20 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey";
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)readFromURL:(NSURL *)url ofType:(NSString *)typeName error:(NSError **)outError {
|
- (BOOL)readFromURL:(NSURL *)url ofType:(NSString *)typeName error:(NSError **)outError {
|
||||||
|
self.lockFileURL = [url URLByAppendingPathExtension:@"lock"];
|
||||||
|
if([[NSFileManager defaultManager] fileExistsAtPath:[_lockFileURL path]]) {
|
||||||
|
self.readOnly = YES;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
[[NSFileManager defaultManager] createFileAtPath:[_lockFileURL path] contents:nil attributes:nil];
|
||||||
|
_didLockFile = YES;
|
||||||
|
}
|
||||||
self.decrypted = NO;
|
self.decrypted = NO;
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)revertToContentsOfURL:(NSURL *)absoluteURL ofType:(NSString *)typeName error:(NSError **)outError {
|
- (BOOL)revertToContentsOfURL:(NSURL *)absoluteURL ofType:(NSString *)typeName error:(NSError **)outError {
|
||||||
[self _resetTree];
|
self.tree = nil;
|
||||||
if([self readFromURL:absoluteURL ofType:typeName error:outError]) {
|
if([self readFromURL:absoluteURL ofType:typeName error:outError]) {
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPDocumentDidRevertNotifiation object:self];
|
[[NSNotificationCenter defaultCenter] postNotificationName:MPDocumentDidRevertNotifiation object:self];
|
||||||
return YES;
|
return YES;
|
||||||
@@ -116,7 +141,18 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey";
|
|||||||
return _decrypted;
|
return _decrypted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)close {
|
||||||
|
[self _cleanupLock];
|
||||||
|
[super close];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)anItem {
|
||||||
|
NSLog(@"Validating %@", anItem);
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark Protection
|
#pragma mark Protection
|
||||||
|
|
||||||
- (BOOL)decryptWithPassword:(NSString *)password keyFileURL:(NSURL *)keyFileURL {
|
- (BOOL)decryptWithPassword:(NSString *)password keyFileURL:(NSURL *)keyFileURL {
|
||||||
self.key = keyFileURL;
|
self.key = keyFileURL;
|
||||||
self.password = [password length] > 0 ? password : nil;
|
self.password = [password length] > 0 ? password : nil;
|
||||||
@@ -133,9 +169,7 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey";
|
|||||||
else if( [self.tree isKindOfClass:[Kdb3Tree class]]) {
|
else if( [self.tree isKindOfClass:[Kdb3Tree class]]) {
|
||||||
self.version = MPDatabaseVersion3;
|
self.version = MPDatabaseVersion3;
|
||||||
}
|
}
|
||||||
/* reset the root to inform KVO listeners */
|
self.decrypted = YES;
|
||||||
self.root = self.tree.root;
|
|
||||||
_decrypted = YES;
|
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,14 +200,16 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey";
|
|||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark Data Accesors
|
#pragma mark Data Accesors
|
||||||
- (KdbGroup *)root {
|
- (void)setTree:(KdbTree *)tree {
|
||||||
return self.tree.root;
|
if(_tree != tree) {
|
||||||
|
[_tree release];
|
||||||
|
_tree = [tree retain];
|
||||||
|
self.rootAdapter.tree = _tree;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setRoot:(KdbGroup *)root {
|
- (KdbGroup *)root {
|
||||||
if(self.root != root) {
|
return self.tree.root;
|
||||||
self.tree.root = root;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (KdbEntry *)findEntry:(UUID *)uuid {
|
- (KdbEntry *)findEntry:(UUID *)uuid {
|
||||||
@@ -232,6 +268,7 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey";
|
|||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
BOOL isMovable = YES;
|
BOOL isMovable = YES;
|
||||||
|
|
||||||
KdbGroup *ancestor = target.parent;
|
KdbGroup *ancestor = target.parent;
|
||||||
while(ancestor.parent) {
|
while(ancestor.parent) {
|
||||||
if(ancestor == group) {
|
if(ancestor == group) {
|
||||||
@@ -290,10 +327,11 @@ NSString *const MPDocumentGroupKey = @"MPDocumentGroupKey";
|
|||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark Private
|
#pragma mark Private
|
||||||
- (void)_resetTree {
|
- (void)_cleanupLock {
|
||||||
// Reset both values to inform any KVO listener
|
if(_didLockFile) {
|
||||||
self.root = nil;
|
[[NSFileManager defaultManager] removeItemAtURL:_lockFileURL error:nil];
|
||||||
self.tree = nil;
|
_didLockFile = NO;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -176,10 +176,12 @@ NSString *const MPCurrentItemChangedNotification = @"com.hicknhack.macpass.MPCur
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem {
|
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem {
|
||||||
return YES;
|
MPDocument *document = [self document];
|
||||||
|
return !( document.isLocked || document.isReadOnly );
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)validateToolbarItem:(NSToolbarItem *)theItem {
|
- (BOOL)validateToolbarItem:(NSToolbarItem *)theItem {
|
||||||
|
NSLog(@"Validate ToolbarItem: %@", theItem);
|
||||||
MPDocument *document = [self document];
|
MPDocument *document = [self document];
|
||||||
if(document.isLocked) {
|
if(document.isLocked) {
|
||||||
return NO;
|
return NO;
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#import "Kdb3Node.h"
|
#import "Kdb3Node.h"
|
||||||
#import "KdbGroup+Undo.h"
|
#import "KdbGroup+Undo.h"
|
||||||
#import "KdbEntry+Undo.h"
|
#import "KdbEntry+Undo.h"
|
||||||
|
#import "NSMutableData+Base64.h"
|
||||||
|
|
||||||
#import "HNHGradientView.h"
|
#import "HNHGradientView.h"
|
||||||
|
|
||||||
@@ -299,8 +300,9 @@ enum {
|
|||||||
Kdb4Entry *entry = (Kdb4Entry *)self.selectedEntry;
|
Kdb4Entry *entry = (Kdb4Entry *)self.selectedEntry;
|
||||||
BinaryRef *binaryRef = entry.binaries[row];
|
BinaryRef *binaryRef = entry.binaries[row];
|
||||||
[[view textField] bind:NSValueBinding toObject:binaryRef withKeyPath:@"key" options:nil];
|
[[view textField] bind:NSValueBinding toObject:binaryRef withKeyPath:@"key" options:nil];
|
||||||
// MPDocument *document = [[self windowController] document];
|
MPDocument *document = [[self windowController] document];
|
||||||
// [document binaryForRef:binaryRef];
|
Binary *binary = [document binaryForRef:binaryRef];
|
||||||
|
NSLog(@"%@", binary.data);
|
||||||
}
|
}
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,11 +8,15 @@
|
|||||||
|
|
||||||
#import "MPOutlineDataSource.h"
|
#import "MPOutlineDataSource.h"
|
||||||
#import "MPDocument.h"
|
#import "MPDocument.h"
|
||||||
|
#import "MPConstants.h"
|
||||||
|
#import "MPRootAdapter.h"
|
||||||
|
|
||||||
#import "KdbLib.h"
|
#import "KdbLib.h"
|
||||||
#import "KdbGroup+Undo.h"
|
#import "KdbGroup+Undo.h"
|
||||||
#import "KdbGroup+MPTreeTools.h"
|
#import "KdbGroup+MPTreeTools.h"
|
||||||
#import "KdbEntry+MPTreeTools.h"
|
#import "KdbEntry+MPTreeTools.h"
|
||||||
#import "MPConstants.h"
|
|
||||||
|
|
||||||
#import "UUID.h"
|
#import "UUID.h"
|
||||||
|
|
||||||
@implementation MPOutlineDataSource
|
@implementation MPOutlineDataSource
|
||||||
@@ -37,12 +41,16 @@
|
|||||||
oprationMask = NSDragOperationCopy;
|
oprationMask = NSDragOperationCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
KdbGroup *target = [item representedObject];
|
id targetItem = [item representedObject];
|
||||||
if( target == nil) {
|
if(targetItem == nil) {
|
||||||
return oprationMask; // Draggin over root
|
return NSDragOperationNone; // no Target
|
||||||
}
|
}
|
||||||
|
if([targetItem isKindOfClass:[MPRootAdapter class]]) {
|
||||||
|
return NSDragOperationNone; // Drag over group header
|
||||||
|
}
|
||||||
|
KdbGroup *targetGroup = targetItem;
|
||||||
BOOL validTarget = YES;
|
BOOL validTarget = YES;
|
||||||
if( _draggedItem.parent == target ) {
|
if( _draggedItem.parent == targetGroup ) {
|
||||||
validTarget &= index != NSOutlineViewDropOnItemIndex;
|
validTarget &= index != NSOutlineViewDropOnItemIndex;
|
||||||
validTarget &= index != [_draggedItem.parent.groups indexOfObject:_draggedItem];
|
validTarget &= index != [_draggedItem.parent.groups indexOfObject:_draggedItem];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,14 +9,15 @@
|
|||||||
#import "MPOutlineViewController.h"
|
#import "MPOutlineViewController.h"
|
||||||
#import "MPOutlineDataSource.h"
|
#import "MPOutlineDataSource.h"
|
||||||
#import "MPDocument.h"
|
#import "MPDocument.h"
|
||||||
#import "MPAppDelegate.h"
|
|
||||||
#import "MPContextMenuHelper.h"
|
#import "MPContextMenuHelper.h"
|
||||||
#import "MPConstants.h"
|
#import "MPConstants.h"
|
||||||
#import "MPActionHelper.h"
|
#import "MPActionHelper.h"
|
||||||
#import "MPIconHelper.h"
|
#import "MPIconHelper.h"
|
||||||
#import "MPUppercaseStringValueTransformer.h"
|
#import "MPUppercaseStringValueTransformer.h"
|
||||||
|
#import "MPRootAdapter.h"
|
||||||
|
|
||||||
#import "KdbLib.h"
|
#import "KdbLib.h"
|
||||||
|
#import "Kdb4Node.h"
|
||||||
#import "KdbGroup+Undo.h"
|
#import "KdbGroup+Undo.h"
|
||||||
|
|
||||||
#import "HNHGradientView.h"
|
#import "HNHGradientView.h"
|
||||||
@@ -78,7 +79,7 @@ NSString *const _MPOutlinveViewHeaderViewIdentifier = @"HeaderCell";
|
|||||||
if(!_bindingEstablished) {
|
if(!_bindingEstablished) {
|
||||||
MPDocument *document = [[self windowController] document];
|
MPDocument *document = [[self windowController] document];
|
||||||
[_treeController setChildrenKeyPath:@"groups"];
|
[_treeController setChildrenKeyPath:@"groups"];
|
||||||
[_treeController bind:NSContentBinding toObject:document withKeyPath:@"root" options:nil];
|
[_treeController bind:NSContentBinding toObject:document withKeyPath:@"rootAdapter" options:nil];
|
||||||
[_outlineView bind:NSContentBinding toObject:_treeController withKeyPath:@"arrangedObjects" options:nil];
|
[_outlineView bind:NSContentBinding toObject:_treeController withKeyPath:@"arrangedObjects" options:nil];
|
||||||
[_outlineView setDataSource:self.datasource];
|
[_outlineView setDataSource:self.datasource];
|
||||||
_bindingEstablished = YES;
|
_bindingEstablished = YES;
|
||||||
@@ -154,16 +155,14 @@ NSString *const _MPOutlinveViewHeaderViewIdentifier = @"HeaderCell";
|
|||||||
|
|
||||||
#pragma mark NSOutlineViewDelegate
|
#pragma mark NSOutlineViewDelegate
|
||||||
- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item {
|
- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item {
|
||||||
NSTreeNode *treeNode = item;
|
|
||||||
KdbGroup *group = [treeNode representedObject];
|
|
||||||
//KdbGroup *group = item;
|
|
||||||
NSTableCellView *view;
|
NSTableCellView *view;
|
||||||
if(![group parent]) {
|
if( [self _itemIsRootNodeAdapter:item] ) {
|
||||||
NSDictionary *options = @{ NSValueTransformerBindingOption : [NSValueTransformer valueTransformerForName:MPUppsercaseStringValueTransformerName] };
|
//NSDictionary *options = @{ NSValueTransformerBindingOption : [NSValueTransformer valueTransformerForName:MPUppsercaseStringValueTransformerName] };
|
||||||
view = [outlineView makeViewWithIdentifier:_MPOutlinveViewHeaderViewIdentifier owner:self];
|
view = [outlineView makeViewWithIdentifier:_MPOutlinveViewHeaderViewIdentifier owner:self];
|
||||||
[view.textField bind:NSValueBinding toObject:group withKeyPath:@"name" options:options];
|
[view.textField setStringValue:NSLocalizedString(@"GROUPS", @"")];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
KdbGroup *group = [item representedObject];
|
||||||
view = [outlineView makeViewWithIdentifier:_MPOutlineViewDataViewIdentifier owner:self];
|
view = [outlineView makeViewWithIdentifier:_MPOutlineViewDataViewIdentifier owner:self];
|
||||||
NSImage *icon = [MPIconHelper icon:(MPIconType)[group image]];
|
NSImage *icon = [MPIconHelper icon:(MPIconType)[group image]];
|
||||||
[view.imageView setImage:icon];
|
[view.imageView setImage:icon];
|
||||||
@@ -175,20 +174,11 @@ NSString *const _MPOutlinveViewHeaderViewIdentifier = @"HeaderCell";
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)outlineView:(NSOutlineView *)outlineView isGroupItem:(id)item {
|
- (BOOL)outlineView:(NSOutlineView *)outlineView isGroupItem:(id)item {
|
||||||
NSTreeNode *treeNode = item;
|
return [self _itemIsRootNodeAdapter:item];
|
||||||
KdbGroup *group = [treeNode representedObject];
|
|
||||||
//KdbGroup *group = item;
|
|
||||||
if(!group.parent) {
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
return NO;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldSelectItem:(id)item {
|
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldSelectItem:(id)item {
|
||||||
NSTreeNode *treeNode = item;
|
return ![self _itemIsRootNodeAdapter:item];
|
||||||
KdbGroup *group = [treeNode representedObject];
|
|
||||||
//KdbGroup *group = item;
|
|
||||||
return (nil != [group parent]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)outlineViewSelectionDidChange:(NSNotification *)notification {
|
- (void)outlineViewSelectionDidChange:(NSNotification *)notification {
|
||||||
@@ -199,9 +189,7 @@ NSString *const _MPOutlinveViewHeaderViewIdentifier = @"HeaderCell";
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldShowOutlineCellForItem:(id)item {
|
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldShowOutlineCellForItem:(id)item {
|
||||||
return YES;
|
return ![self _itemIsRootNodeAdapter:item];
|
||||||
// KdbGroup *group = [item representedObject];
|
|
||||||
// return (nil != group.parent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
@@ -224,4 +212,9 @@ NSString *const _MPOutlinveViewHeaderViewIdentifier = @"HeaderCell";
|
|||||||
return [menu autorelease];
|
return [menu autorelease];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)_itemIsRootNodeAdapter:(id)item {
|
||||||
|
id node = [item representedObject];
|
||||||
|
return [node isKindOfClass:[MPRootAdapter class]];
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
18
MacPass/MPRootAdapter.h
Normal file
18
MacPass/MPRootAdapter.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
//
|
||||||
|
// MPRootAdapter.h
|
||||||
|
// MacPass
|
||||||
|
//
|
||||||
|
// Created by Michael Starke on 26.06.13.
|
||||||
|
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
@class KdbTree;
|
||||||
|
|
||||||
|
@interface MPRootAdapter : NSObject
|
||||||
|
|
||||||
|
@property (readonly, retain) NSArray *groups;
|
||||||
|
@property (nonatomic, retain) KdbTree *tree;
|
||||||
|
|
||||||
|
@end
|
||||||
33
MacPass/MPRootAdapter.m
Normal file
33
MacPass/MPRootAdapter.m
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
//
|
||||||
|
// MPRootAdapter.m
|
||||||
|
// MacPass
|
||||||
|
//
|
||||||
|
// Created by Michael Starke on 26.06.13.
|
||||||
|
// Copyright (c) 2013 HicknHack Software GmbH. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "MPRootAdapter.h"
|
||||||
|
#import "Kdb.h"
|
||||||
|
|
||||||
|
@interface MPRootAdapter ()
|
||||||
|
|
||||||
|
@property (retain) NSArray *groups;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation MPRootAdapter
|
||||||
|
|
||||||
|
- (void)dealloc {
|
||||||
|
[_groups release];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setTree:(KdbTree *)tree {
|
||||||
|
if(_tree != tree) {
|
||||||
|
[_tree release];
|
||||||
|
_tree = [tree retain];
|
||||||
|
self.groups = @[_tree.root];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -48,7 +48,7 @@
|
|||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1175</string>
|
<string>1224</string>
|
||||||
<key>LSMinimumSystemVersion</key>
|
<key>LSMinimumSystemVersion</key>
|
||||||
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
|
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
|
||||||
<key>NSHumanReadableCopyright</key>
|
<key>NSHumanReadableCopyright</key>
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user