FLEXKeychainTableViewController.m 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. //
  2. // FLEXKeychainTableViewController.m
  3. // FLEX
  4. //
  5. // Created by ray on 2019/8/17.
  6. // Copyright © 2019 Flipboard. All rights reserved.
  7. //
  8. #import "FLEXKeychain.h"
  9. #import "FLEXKeychainQuery.h"
  10. #import "FLEXKeychainTableViewController.h"
  11. #import "FLEXUtility.h"
  12. @interface FLEXKeychainTableViewController ()
  13. @property (nonatomic) NSArray<NSDictionary *> *keyChainItems;
  14. @end
  15. @implementation FLEXKeychainTableViewController
  16. - (void)viewDidLoad
  17. {
  18. [super viewDidLoad];
  19. self.navigationItem.rightBarButtonItems = @[
  20. [[UIBarButtonItem alloc]
  21. initWithBarButtonSystemItem:UIBarButtonSystemItemTrash target:self action:@selector(trashPressed)
  22. ],
  23. [[UIBarButtonItem alloc]
  24. initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addPressed)
  25. ],
  26. ];
  27. [self refreshKeychainItems];
  28. }
  29. - (void)refreshKeychainItems
  30. {
  31. self.keyChainItems = [FLEXKeychain allAccounts];
  32. self.title = [NSString stringWithFormat:@"🔑 Keychain Items (%lu)", (unsigned long)self.keyChainItems.count];
  33. }
  34. #pragma mark Buttons
  35. - (void)trashPressed
  36. {
  37. [FLEXAlert makeSheet:^(FLEXAlert *make) {
  38. make.title(@"Clear Keychain");
  39. make.message(@"This will remove all keychain items for this app.\n");
  40. make.message(@"This action cannot be undone. Are you sure?");
  41. make.button(@"Yes, clear the keychain").destructiveStyle().handler(^(NSArray *strings) {
  42. for (id account in self.keyChainItems) {
  43. FLEXKeychainQuery *query = [FLEXKeychainQuery new];
  44. query.service = account[kFLEXKeychainWhereKey];
  45. query.account = account[kFLEXKeychainAccountKey];
  46. // Delete item or display error
  47. NSError *error = nil;
  48. if (![query deleteItem:&error]) {
  49. [FLEXAlert makeAlert:^(FLEXAlert *make) {
  50. make.title(@"Error Deleting Item");
  51. make.message(error.localizedDescription);
  52. } showFrom:self];
  53. }
  54. }
  55. [self refreshKeychainItems];
  56. [self.tableView reloadData];
  57. });
  58. make.button(@"Cancel").cancelStyle();
  59. } showFrom:self];
  60. }
  61. - (void)addPressed
  62. {
  63. [FLEXAlert makeAlert:^(FLEXAlert *make) {
  64. make.title(@"Add Keychain Item");
  65. make.textField(@"Service name, i.e. Instagram");
  66. make.textField(@"Account, i.e. username@example.com");
  67. make.textField(@"Password");
  68. make.button(@"Cancel").cancelStyle();
  69. make.button(@"Save").handler(^(NSArray<NSString *> *strings) {
  70. // Display errors
  71. NSError *error = nil;
  72. if (![FLEXKeychain setPassword:strings[2] forService:strings[0] account:strings[1] error:&error]) {
  73. [FLEXAlert showAlert:@"Error" message:error.localizedDescription from:self];
  74. }
  75. [self refreshKeychainItems];
  76. [self.tableView reloadData];
  77. });
  78. } showFrom:self];
  79. }
  80. #pragma mark - FLEXGlobalsEntry
  81. + (NSString *)globalsEntryTitle:(FLEXGlobalsRow)row
  82. {
  83. return @"🔑 Keychain";
  84. }
  85. + (UIViewController *)globalsEntryViewController:(FLEXGlobalsRow)row
  86. {
  87. return [self new];
  88. }
  89. #pragma mark - Table View Data Source
  90. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
  91. {
  92. return self.keyChainItems.count;
  93. }
  94. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
  95. {
  96. static NSString *CellIdentifier = @"Cell";
  97. UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
  98. if (!cell) {
  99. cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
  100. cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
  101. cell.textLabel.font = [FLEXUtility defaultTableViewCellLabelFont];
  102. }
  103. NSDictionary *item = self.keyChainItems[indexPath.row];
  104. cell.textLabel.text = item[kFLEXKeychainAccountKey];
  105. return cell;
  106. }
  107. #pragma mark - Table View Delegate
  108. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
  109. {
  110. NSDictionary *item = self.keyChainItems[indexPath.row];
  111. FLEXKeychainQuery *query = [FLEXKeychainQuery new];
  112. query.service = item[kFLEXKeychainWhereKey];
  113. query.account = item[kFLEXKeychainAccountKey];
  114. [query fetch:nil];
  115. [FLEXAlert makeAlert:^(FLEXAlert *make) {
  116. make.title(query.service);
  117. make.message(@"Service: ").message(query.service);
  118. make.message(@"\nAccount: ").message(query.account);
  119. make.message(@"\nPassword: ").message(query.password);
  120. make.button(@"Copy Service").handler(^(NSArray<NSString *> *strings) {
  121. UIPasteboard.generalPasteboard.string = query.service;
  122. });
  123. make.button(@"Copy Account").handler(^(NSArray<NSString *> *strings) {
  124. UIPasteboard.generalPasteboard.string = query.account;
  125. });
  126. make.button(@"Copy Password").handler(^(NSArray<NSString *> *strings) {
  127. UIPasteboard.generalPasteboard.string = query.password;
  128. });
  129. make.button(@"Dismiss").cancelStyle();
  130. } showFrom:self];
  131. }
  132. @end