MainViewController+Email.m 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. /*
  2. * Copyright 2019 Google
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #import "MainViewController+Email.h"
  17. #import "AppManager.h"
  18. #import <FirebaseAuth/FIRPhoneMultiFactorInfo.h>
  19. #import "MainViewController+Internal.h"
  20. NS_ASSUME_NONNULL_BEGIN
  21. extern NSString *const FIRAuthErrorUserInfoMultiFactorResolverKey;
  22. typedef void (^ShowEmailDialogCompletion)(FIRAuthCredential *credential);
  23. @implementation MainViewController (Email)
  24. - (StaticContentTableViewSection *)emailAuthSection {
  25. __weak typeof(self) weakSelf = self;
  26. return [StaticContentTableViewSection sectionWithTitle:@"Email Auth" cells:@[
  27. [StaticContentTableViewCell cellWithTitle:@"Create User"
  28. action:^{ [weakSelf createUser]; }],
  29. [StaticContentTableViewCell cellWithTitle:@"Sign in with Email Password"
  30. action:^{ [weakSelf signInEmailPassword]; }],
  31. [StaticContentTableViewCell cellWithTitle:@"Link with Email Password"
  32. action:^{ [weakSelf linkWithEmailPassword]; }],
  33. [StaticContentTableViewCell cellWithTitle:@"Reauthenticate Email Password"
  34. action:^{ [weakSelf reauthenticateEmailPassword]; }],
  35. [StaticContentTableViewCell cellWithTitle:@"Send Email Sign in Link"
  36. action:^{ [weakSelf sendEmailSignInLink]; }],
  37. [StaticContentTableViewCell cellWithTitle:@"Sign in with Email Link"
  38. action:^{ [weakSelf signInWithEmailLink]; }],
  39. [StaticContentTableViewCell cellWithTitle:@"Link with Email Link"
  40. action:^{ [weakSelf linkWithEmailLink]; }],
  41. [StaticContentTableViewCell cellWithTitle:@"Unlink from Email"
  42. action:^{ [weakSelf unlinkFromProvider:FIREmailAuthProviderID
  43. completion:nil]; }],
  44. ]];
  45. }
  46. - (void)createUser {
  47. [self showTextInputPromptWithMessage:@"Email:"
  48. keyboardType:UIKeyboardTypeEmailAddress
  49. completionBlock:^(BOOL userPressedOK, NSString *_Nullable email) {
  50. if (!userPressedOK || !email.length) {
  51. return;
  52. }
  53. [self showTextInputPromptWithMessage:@"Password:"
  54. completionBlock:^(BOOL userPressedOK, NSString *_Nullable password) {
  55. if (!userPressedOK) {
  56. return;
  57. }
  58. [self showSpinner:^{
  59. [[AppManager auth] createUserWithEmail:email
  60. password:password
  61. completion:^(FIRAuthDataResult *_Nullable result,
  62. NSError *_Nullable error) {
  63. if (error) {
  64. [self logFailure:@"create user failed" error:error];
  65. } else {
  66. [self logSuccess:@"create user succeeded."];
  67. [self log:result.user.uid];
  68. }
  69. [self hideSpinner:^{
  70. [self showTypicalUIForUserUpdateResultsWithTitle:@"Create User" error:error];
  71. }];
  72. }];
  73. }];
  74. }];
  75. }];
  76. }
  77. - (void)signUpNewEmail:(NSString *)email
  78. password:(NSString *)password
  79. callback:(nullable FIRAuthResultCallback)callback {
  80. [[AppManager auth] createUserWithEmail:email
  81. password:password
  82. completion:^(FIRAuthDataResult *_Nullable result,
  83. NSError *_Nullable error) {
  84. if (error) {
  85. [self logFailure:@"sign-up with Email/Password failed" error:error];
  86. if (callback) {
  87. callback(nil, error);
  88. }
  89. } else {
  90. [self logSuccess:@"sign-up with Email/Password succeeded."];
  91. if (callback) {
  92. callback(result.user, nil);
  93. }
  94. }
  95. [self showTypicalUIForUserUpdateResultsWithTitle:@"Sign-In" error:error];
  96. }];
  97. }
  98. - (void)signInEmailPassword {
  99. [self showTextInputPromptWithMessage:@"Email Address"
  100. keyboardType:UIKeyboardTypeEmailAddress
  101. completionBlock:^(BOOL userPressedOK, NSString *_Nullable email) {
  102. if (!userPressedOK || !email.length) {
  103. return;
  104. }
  105. [self showTextInputPromptWithMessage:@"Password"
  106. completionBlock:^(BOOL userPressedOK, NSString *_Nullable password) {
  107. if (!userPressedOK) {
  108. return;
  109. }
  110. [self showSpinner:^{
  111. [[AppManager auth] signInWithEmail:email
  112. password:password
  113. completion:^(FIRAuthDataResult *_Nullable authResult,
  114. NSError *_Nullable error) {
  115. [self hideSpinner:^{
  116. if (error) {
  117. if (error.code == FIRAuthErrorCodeSecondFactorRequired) {
  118. [self authenticateWithSecondFactorError:error workflow:@"sign in"];
  119. } else {
  120. [self logFailure:@"sign-in with Email/Password failed" error:error];
  121. }
  122. } else {
  123. [self logSuccess:@"sign-in with Email/Password succeeded."];
  124. [self log:[NSString stringWithFormat:@"UID: %@",authResult.user.uid]];
  125. }
  126. }];
  127. }];
  128. }];
  129. }];
  130. }];
  131. }
  132. - (void)linkWithEmailPassword {
  133. [self showEmailPasswordDialogWithCompletion:^(FIRAuthCredential *credential) {
  134. [self showSpinner:^{
  135. [[self user] linkWithCredential:credential
  136. completion:^(FIRAuthDataResult *result, NSError *error) {
  137. if (error) {
  138. [self logFailure:@"link Email Password failed." error:error];
  139. } else {
  140. [self logSuccess:@"link Email Password succeeded."];
  141. }
  142. [self hideSpinner:^{
  143. [self showTypicalUIForUserUpdateResultsWithTitle:@"Link with Email Password" error:error];
  144. }];
  145. }];
  146. }];
  147. }];
  148. }
  149. - (void)reauthenticateEmailPassword {
  150. FIRUser *user = [self user];
  151. if (!user) {
  152. NSString *title = @"Missing User";
  153. NSString *message = @"There is no signed-in email/password user.";
  154. [self showMessagePromptWithTitle:title message:message showCancelButton:NO completion:nil];
  155. return;
  156. }
  157. [self showEmailPasswordDialogWithCompletion:^(FIRAuthCredential *credential) {
  158. [self showSpinner:^{
  159. [[self user] reauthenticateWithCredential:credential
  160. completion:^(FIRAuthDataResult *_Nullable result,
  161. NSError *_Nullable error) {
  162. if (error) {
  163. if (error.code == FIRAuthErrorCodeSecondFactorRequired) {
  164. [self authenticateWithSecondFactorError:error workflow:@"reauthicate"];
  165. } else {
  166. [self logFailure:@"reauthicate failed" error:error];
  167. }
  168. } else {
  169. [self logSuccess:@"reauthicate with email password succeeded."];
  170. }
  171. [self hideSpinner:^{
  172. [self showTypicalUIForUserUpdateResultsWithTitle:@"Reauthenticate Email Password" error:error];
  173. }];
  174. }];
  175. }];
  176. }];
  177. }
  178. - (void)signInWithEmailLink {
  179. [self showTextInputPromptWithMessage:@"Email Address:"
  180. keyboardType:UIKeyboardTypeEmailAddress
  181. completionBlock:^(BOOL userPressedOK, NSString *_Nullable email) {
  182. if (!userPressedOK || !email.length) {
  183. return;
  184. }
  185. [self showTextInputPromptWithMessage:@"Email Sign-In Link:"
  186. completionBlock:^(BOOL userPressedOK, NSString *_Nullable link) {
  187. if (!userPressedOK) {
  188. return;
  189. }
  190. if ([[FIRAuth auth] isSignInWithEmailLink:link]) {
  191. [self showSpinner:^{
  192. [[AppManager auth] signInWithEmail:email
  193. link:link
  194. completion:^(FIRAuthDataResult *_Nullable authResult,
  195. NSError *_Nullable error) {
  196. [self hideSpinner:^{
  197. if (error) {
  198. if (error.code == FIRAuthErrorCodeSecondFactorRequired) {
  199. [self authenticateWithSecondFactorError:error workflow:@"sign in"];
  200. } else {
  201. [self logFailure:@"sign-in with Email/Sign-In link failed" error:error];
  202. }
  203. } else {
  204. [self logSuccess:@"sign-in with Email/Sign-In link succeeded."];
  205. [self log:[NSString stringWithFormat:@"UID: %@",authResult.user.uid]];
  206. }
  207. [self showTypicalUIForUserUpdateResultsWithTitle:@"Sign-In Error" error:error];
  208. }];
  209. }];
  210. }];
  211. } else {
  212. [self log:@"The sign-in link is invalid"];
  213. }
  214. }];
  215. }];
  216. }
  217. - (void)sendEmailSignInLink {
  218. [self showTextInputPromptWithMessage:@"Email:"
  219. completionBlock:^(BOOL userPressedOK, NSString *_Nullable userInput) {
  220. if (!userPressedOK) {
  221. return;
  222. }
  223. [self showSpinner:^{
  224. void (^requestEmailSignInLink)(void (^)(NSError *)) = ^(void (^completion)(NSError *)) {
  225. [[AppManager auth] sendSignInLinkToEmail:userInput
  226. actionCodeSettings:[self actionCodeSettings]
  227. completion:completion];
  228. };
  229. requestEmailSignInLink(^(NSError *_Nullable error) {
  230. [self hideSpinner:^{
  231. if (error) {
  232. [self logFailure:@"Email Link request failed" error:error];
  233. [self showMessagePrompt:error.localizedDescription];
  234. return;
  235. }
  236. [self logSuccess:@"Email Link request succeeded."];
  237. [self showMessagePrompt:@"Sent"];
  238. }];
  239. });
  240. }];
  241. }];
  242. }
  243. - (void)linkWithEmailLink {
  244. [self showEmailLinkDialogWithCompletion:^(FIRAuthCredential *credential) {
  245. [self showSpinner:^{
  246. [[self user] linkWithCredential:credential
  247. completion:^(FIRAuthDataResult *result, NSError *error) {
  248. if (error) {
  249. [self logFailure:@"link Email Link failed." error:error];
  250. } else {
  251. [self logSuccess:@"link Email Link succeeded."];
  252. }
  253. [self hideSpinner:^{
  254. [self showTypicalUIForUserUpdateResultsWithTitle:@"Link with Email Link" error:error];
  255. }];
  256. }];
  257. }];
  258. }];
  259. }
  260. - (void)showEmailPasswordDialogWithCompletion:(ShowEmailDialogCompletion)completion {
  261. [self showTextInputPromptWithMessage:@"Email Address:"
  262. completionBlock:^(BOOL userPressedOK, NSString *_Nullable email) {
  263. if (!userPressedOK || !email.length) {
  264. return;
  265. }
  266. [self showTextInputPromptWithMessage:@"Password:"
  267. completionBlock:^(BOOL userPressedOK, NSString *_Nullable password) {
  268. if (!userPressedOK || !password.length) {
  269. return;
  270. }
  271. FIRAuthCredential *credential = [FIREmailAuthProvider credentialWithEmail:email
  272. password:password];
  273. completion(credential);
  274. }];
  275. }];
  276. }
  277. - (void)showEmailLinkDialogWithCompletion:(ShowEmailDialogCompletion)completion {
  278. [self showTextInputPromptWithMessage:@"Email Address:"
  279. completionBlock:^(BOOL userPressedOK, NSString *_Nullable email) {
  280. if (!userPressedOK || !email.length) {
  281. return;
  282. }
  283. [self showTextInputPromptWithMessage:@"Link:"
  284. completionBlock:^(BOOL userPressedOK, NSString *_Nullable link) {
  285. if (!userPressedOK || !link.length) {
  286. return;
  287. }
  288. FIRAuthCredential *credential = [FIREmailAuthProvider credentialWithEmail:email
  289. link:link];
  290. completion(credential);
  291. }];
  292. }];
  293. }
  294. @end
  295. NS_ASSUME_NONNULL_END