You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
213 lines
6.4 KiB
213 lines
6.4 KiB
//
|
|
// FLEXKeychainTableViewController.m
|
|
// FLEX
|
|
//
|
|
// Created by ray on 2019/8/17.
|
|
// Copyright © 2019 Flipboard. All rights reserved.
|
|
//
|
|
|
|
#import "FLEXKeychain.h"
|
|
#import "FLEXKeychainQuery.h"
|
|
#import "FLEXKeychainTableViewController.h"
|
|
#import "FLEXUtility.h"
|
|
#import "UIPasteboard+FLEX.h"
|
|
|
|
@interface FLEXKeychainTableViewController ()
|
|
|
|
@property (nonatomic) NSMutableArray<NSDictionary *> *keychainItems;
|
|
@property (nonatomic) NSString *headerTitle;
|
|
|
|
@end
|
|
|
|
@implementation FLEXKeychainTableViewController
|
|
|
|
- (void)viewDidLoad
|
|
{
|
|
[super viewDidLoad];
|
|
|
|
self.navigationItem.rightBarButtonItems = @[
|
|
[[UIBarButtonItem alloc]
|
|
initWithBarButtonSystemItem:UIBarButtonSystemItemTrash target:self action:@selector(trashPressed)
|
|
],
|
|
[[UIBarButtonItem alloc]
|
|
initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addPressed)
|
|
],
|
|
];
|
|
|
|
[self refreshkeychainItems];
|
|
[self updateHeaderTitle];
|
|
}
|
|
|
|
- (void)refreshkeychainItems
|
|
{
|
|
self.keychainItems = [FLEXKeychain allAccounts].mutableCopy;
|
|
}
|
|
|
|
- (void)updateHeaderTitle
|
|
{
|
|
self.headerTitle = [NSString stringWithFormat:@"%@ items", @(self.keychainItems.count)];
|
|
}
|
|
|
|
- (FLEXKeychainQuery *)queryForItemAtIndex:(NSInteger)idx
|
|
{
|
|
NSDictionary *item = self.keychainItems[idx];
|
|
|
|
FLEXKeychainQuery *query = [FLEXKeychainQuery new];
|
|
query.service = item[kFLEXKeychainWhereKey];
|
|
query.account = item[kFLEXKeychainAccountKey];
|
|
[query fetch:nil];
|
|
|
|
return query;
|
|
}
|
|
|
|
- (void)deleteItem:(NSDictionary *)item
|
|
{
|
|
NSError *error = nil;
|
|
BOOL success = [FLEXKeychain
|
|
deletePasswordForService:item[kFLEXKeychainWhereKey]
|
|
account:item[kFLEXKeychainAccountKey]
|
|
error:&error
|
|
];
|
|
|
|
if (!success) {
|
|
[FLEXAlert makeAlert:^(FLEXAlert *make) {
|
|
make.title(@"Error Deleting Item");
|
|
make.message(error.localizedDescription);
|
|
} showFrom:self];
|
|
}
|
|
}
|
|
|
|
|
|
#pragma mark Buttons
|
|
|
|
- (void)trashPressed
|
|
{
|
|
[FLEXAlert makeSheet:^(FLEXAlert *make) {
|
|
make.title(@"Clear Keychain");
|
|
make.message(@"This will remove all keychain items for this app.\n");
|
|
make.message(@"This action cannot be undone. Are you sure?");
|
|
make.button(@"Yes, clear the keychain").destructiveStyle().handler(^(NSArray *strings) {
|
|
for (id account in self.keychainItems) {
|
|
[self deleteItem:account];
|
|
}
|
|
|
|
[self refreshkeychainItems];
|
|
[self.tableView reloadData];
|
|
});
|
|
make.button(@"Cancel").cancelStyle();
|
|
} showFrom:self];
|
|
}
|
|
|
|
- (void)addPressed
|
|
{
|
|
[FLEXAlert makeAlert:^(FLEXAlert *make) {
|
|
make.title(@"Add Keychain Item");
|
|
make.textField(@"Service name, i.e. Instagram");
|
|
make.textField(@"Account, i.e. username@example.com");
|
|
make.textField(@"Password");
|
|
make.button(@"Cancel").cancelStyle();
|
|
make.button(@"Save").handler(^(NSArray<NSString *> *strings) {
|
|
// Display errors
|
|
NSError *error = nil;
|
|
if (![FLEXKeychain setPassword:strings[2] forService:strings[0] account:strings[1] error:&error]) {
|
|
[FLEXAlert showAlert:@"Error" message:error.localizedDescription from:self];
|
|
}
|
|
|
|
[self refreshkeychainItems];
|
|
[self.tableView reloadData];
|
|
});
|
|
} showFrom:self];
|
|
}
|
|
|
|
|
|
#pragma mark - FLEXGlobalsEntry
|
|
|
|
+ (NSString *)globalsEntryTitle:(FLEXGlobalsRow)row
|
|
{
|
|
return @"🔑 Keychain";
|
|
}
|
|
|
|
+ (UIViewController *)globalsEntryViewController:(FLEXGlobalsRow)row {
|
|
FLEXKeychainTableViewController *viewController = [self new];
|
|
viewController.title = [self globalsEntryTitle:row];
|
|
|
|
return viewController;
|
|
}
|
|
|
|
|
|
#pragma mark - Table View Data Source
|
|
|
|
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
|
|
{
|
|
return self.keychainItems.count;
|
|
}
|
|
|
|
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
|
|
{
|
|
static NSString *CellIdentifier = @"Cell";
|
|
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
|
|
if (!cell) {
|
|
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
|
|
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
|
|
cell.textLabel.font = [FLEXUtility defaultTableViewCellLabelFont];
|
|
}
|
|
|
|
NSDictionary *item = self.keychainItems[indexPath.row];
|
|
id account = item[kFLEXKeychainAccountKey];
|
|
if ([account isKindOfClass:[NSString class]]) {
|
|
cell.textLabel.text = account;
|
|
} else {
|
|
cell.textLabel.text = [NSString stringWithFormat:
|
|
@"[%@]\n\n%@",
|
|
NSStringFromClass([account class]),
|
|
[account description]
|
|
];
|
|
}
|
|
|
|
return cell;
|
|
}
|
|
|
|
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
|
|
{
|
|
return self.headerTitle;
|
|
}
|
|
|
|
- (void)tableView:(UITableView *)tv commitEditingStyle:(UITableViewCellEditingStyle)style forRowAtIndexPath:(NSIndexPath *)ip
|
|
{
|
|
if (style == UITableViewCellEditingStyleDelete) {
|
|
[self deleteItem:self.keychainItems[ip.row]];
|
|
[self.keychainItems removeObjectAtIndex:ip.row];
|
|
[tv deleteRowsAtIndexPaths:@[ip] withRowAnimation:UITableViewRowAnimationAutomatic];
|
|
}
|
|
}
|
|
|
|
|
|
#pragma mark - Table View Delegate
|
|
|
|
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
|
|
{
|
|
FLEXKeychainQuery *query = [self queryForItemAtIndex:indexPath.row];
|
|
|
|
[FLEXAlert makeAlert:^(FLEXAlert *make) {
|
|
make.title(query.service);
|
|
make.message(@"Service: ").message(query.service);
|
|
make.message(@"\nAccount: ").message(query.account);
|
|
make.message(@"\nPassword: ").message(query.password);
|
|
|
|
make.button(@"Copy Service").handler(^(NSArray<NSString *> *strings) {
|
|
[UIPasteboard.generalPasteboard flex_copy:query.service];
|
|
});
|
|
make.button(@"Copy Account").handler(^(NSArray<NSString *> *strings) {
|
|
[UIPasteboard.generalPasteboard flex_copy:query.account];
|
|
});
|
|
make.button(@"Copy Password").handler(^(NSArray<NSString *> *strings) {
|
|
[UIPasteboard.generalPasteboard flex_copy:query.password];
|
|
});
|
|
make.button(@"Dismiss").cancelStyle();
|
|
|
|
} showFrom:self];
|
|
|
|
[tableView deselectRowAtIndexPath:indexPath animated:YES];
|
|
}
|
|
|
|
@end
|