| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370 |
- // Copyright 2020 Google LLC
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- import UIKit
- /// Firebase Auth supported identity providers and other methods of authentication
- enum AuthMenu: String {
- case settings = "Settings"
- case google = "google.com"
- case apple = "apple.com"
- case twitter = "twitter.com"
- case microsoft = "microsoft.com"
- case gitHub = "github.com"
- case yahoo = "yahoo.com"
- case linkedIn = "linkedin.com"
- case facebook = "facebook.com"
- case gameCenter = "gc.apple.com"
- case emailPassword = "password"
- case passwordless = "emailLink"
- case phoneNumber = "phone"
- case anonymous
- case custom
- case initRecaptcha
- case customAuthDomain
- case getToken
- case getTokenForceRefresh
- case addAuthStateChangeListener
- case removeLastAuthStateChangeListener
- case addIdTokenChangeListener
- case removeLastIdTokenChangeListener
- case verifyClient
- case deleteApp
- case actionType
- case continueURL
- case linkDomain
- case requestVerifyEmail
- case requestPasswordReset
- case resetPassword
- case checkActionCode
- case applyActionCode
- case verifyPasswordResetCode
- case phoneEnroll
- case totpEnroll
- case multifactorUnenroll
- // More intuitively named getter for `rawValue`.
- var id: String { rawValue }
- // The UI friendly name of the `AuthMenu`. Used for display.
- var name: String {
- switch self {
- case .settings:
- return "Settings"
- case .google:
- return "Google"
- case .apple:
- return "Apple"
- case .twitter:
- return "Twitter"
- case .microsoft:
- return "Microsoft"
- case .gitHub:
- return "GitHub"
- case .yahoo:
- return "Yahoo"
- case .linkedIn:
- return "LinkedIn"
- case .facebook:
- return "Facebook"
- case .gameCenter:
- return "Game Center"
- case .emailPassword:
- return "Email & Password Login"
- case .passwordless:
- return "Email Link/Passwordless"
- case .phoneNumber:
- return "Phone Number"
- case .anonymous:
- return "Anonymous Authentication"
- case .custom:
- return "Custom Auth System"
- // Recpatcha
- case .initRecaptcha:
- return "Initialize reCAPTCHA Enterprise"
- // Custom Auth Domain
- case .customAuthDomain:
- return "Set Custom Auth Domain"
- // App Section
- case .getToken:
- return "Get Token"
- case .getTokenForceRefresh:
- return "Get Token Force Refresh"
- case .addAuthStateChangeListener:
- return "Add Auth State Change Listener"
- case .removeLastAuthStateChangeListener:
- return "Remove Last Auth State Change Listener"
- case .addIdTokenChangeListener:
- return "Add ID Token Change Listener"
- case .removeLastIdTokenChangeListener:
- return "Remove Last ID Token Change Listener"
- case .verifyClient:
- return "Verify Client"
- case .deleteApp:
- return "Delete App"
- // OOB
- case .actionType:
- return "Action Type"
- case .continueURL:
- return "Continue URL"
- case .linkDomain:
- return "Link Domain"
- case .requestVerifyEmail:
- return "Request Verify Email"
- case .requestPasswordReset:
- return "Request Password Reset"
- case .resetPassword:
- return "Reset Password"
- case .checkActionCode:
- return "Check Action Code"
- case .applyActionCode:
- return "Apply Action Code"
- case .verifyPasswordResetCode:
- return "Verify Password Reset Code"
- // Multi factor
- case .phoneEnroll:
- return "Phone Enroll"
- case .totpEnroll:
- return "TOTP Enroll"
- case .multifactorUnenroll:
- return "Multifactor unenroll"
- }
- }
- // Failable initializer to create an `AuthMenu` from its corresponding `name` value.
- // - Parameter rawValue: String value representing `AuthMenu`'s name or type.
- init?(rawValue: String) {
- switch rawValue {
- case "Settings":
- self = .settings
- case "Google":
- self = .google
- case "Apple":
- self = .apple
- case "Twitter":
- self = .twitter
- case "Microsoft":
- self = .microsoft
- case "GitHub":
- self = .gitHub
- case "Yahoo":
- self = .yahoo
- case "LinkedIn":
- self = .linkedIn
- case "Facebook":
- self = .facebook
- case "Game Center":
- self = .gameCenter
- case "Email & Password Login":
- self = .emailPassword
- case "Email Link/Passwordless":
- self = .passwordless
- case "Phone Number":
- self = .phoneNumber
- case "Anonymous Authentication":
- self = .anonymous
- case "Custom Auth System":
- self = .custom
- case "Initialize reCAPTCHA Enterprise":
- self = .initRecaptcha
- case "Set Custom Auth Domain":
- self = .customAuthDomain
- case "Get Token":
- self = .getToken
- case "Get Token Force Refresh":
- self = .getTokenForceRefresh
- case "Add Auth State Change Listener":
- self = .addAuthStateChangeListener
- case "Remove Last Auth State Change Listener":
- self = .removeLastAuthStateChangeListener
- case "Add ID Token Change Listener":
- self = .addIdTokenChangeListener
- case "Remove Last ID Token Change Listener":
- self = .removeLastIdTokenChangeListener
- case "Verify Client":
- self = .verifyClient
- case "Delete App":
- self = .deleteApp
- case "Action Type":
- self = .actionType
- case "Continue URL":
- self = .continueURL
- case "Link Domain":
- self = .linkDomain
- case "Request Verify Email":
- self = .requestVerifyEmail
- case "Request Password Reset":
- self = .requestPasswordReset
- case "Reset Password":
- self = .resetPassword
- case "Check Action Code":
- self = .checkActionCode
- case "Apply Action Code":
- self = .applyActionCode
- case "Verify Password Reset Code":
- self = .verifyPasswordResetCode
- case "Phone Enroll":
- self = .phoneEnroll
- case "TOTP Enroll":
- self = .totpEnroll
- case "Multifactor unenroll":
- self = .multifactorUnenroll
- default:
- return nil
- }
- }
- }
- enum ActionCodeRequestType: String {
- case email
- case `continue`
- case inApp
- var name: String {
- switch self {
- case .email:
- return "Email Only"
- case .inApp:
- return "In-App + Continue URL"
- case .continue:
- return "Continue URL"
- }
- }
- init?(rawValue: String) {
- switch rawValue {
- case "Email Only":
- self = .email
- case "In-App + Continue URL":
- self = .inApp
- case "Continue URL":
- self = .continue
- default:
- return nil
- }
- }
- }
- // MARK: DataSourceProvidable
- class AuthMenuData: DataSourceProvidable {
- private static var providers: [AuthMenu] {
- [.google, .apple, .twitter, .microsoft, .gitHub, .yahoo, .linkedIn, .facebook, .gameCenter]
- }
- static var settingsSection: Section {
- let header = "Auth Settings"
- let item = Item(title: AuthMenu.settings.name, hasNestedContent: true)
- return Section(headerDescription: header, items: [item])
- }
- static var providerSection: Section {
- let providers = self.providers.map { Item(title: $0.name) }
- let header = "Identity Providers"
- let footer = "Choose a login flow from one of the identity providers above."
- return Section(headerDescription: header, footerDescription: footer, items: providers)
- }
- static var emailPasswordSection: Section {
- let image = UIImage(named: "firebaseIcon")
- let header = "Email and Password Login"
- let item = Item(title: AuthMenu.emailPassword.name, hasNestedContent: true, image: image)
- return Section(headerDescription: header, items: [item])
- }
- static var otherSection: Section {
- let lockSymbol = UIImage.systemImage("lock.slash.fill", tintColor: .systemOrange)
- let phoneSymbol = UIImage.systemImage("phone.fill", tintColor: .systemOrange)
- let anonSymbol = UIImage.systemImage("questionmark.circle.fill", tintColor: .systemOrange)
- let shieldSymbol = UIImage.systemImage("lock.shield.fill", tintColor: .systemOrange)
- let otherOptions = [
- Item(title: AuthMenu.passwordless.name, image: lockSymbol),
- Item(title: AuthMenu.phoneNumber.name, image: phoneSymbol),
- Item(title: AuthMenu.anonymous.name, image: anonSymbol),
- Item(title: AuthMenu.custom.name, image: shieldSymbol),
- ]
- let header = "Other Authentication Methods"
- return Section(headerDescription: header, items: otherOptions)
- }
- static var recaptchaSection: Section {
- let image = UIImage(named: "firebaseIcon")
- let header = "Initialize reCAPTCHA Enterprise"
- let item = Item(title: AuthMenu.initRecaptcha.name, hasNestedContent: false, image: image)
- return Section(headerDescription: header, items: [item])
- }
- static var customAuthDomainSection: Section {
- let image = UIImage(named: "firebaseIcon")
- let header = "Custom Auth Domain"
- let item = Item(title: AuthMenu.customAuthDomain.name, hasNestedContent: false, image: image)
- return Section(headerDescription: header, items: [item])
- }
- static var appSection: Section {
- let header = "APP"
- let items: [Item] = [
- Item(title: AuthMenu.getToken.name),
- Item(title: AuthMenu.getTokenForceRefresh.name),
- Item(title: AuthMenu.addAuthStateChangeListener.name),
- Item(title: AuthMenu.removeLastAuthStateChangeListener.name),
- Item(title: AuthMenu.addIdTokenChangeListener.name),
- Item(title: AuthMenu.removeLastIdTokenChangeListener.name),
- Item(title: AuthMenu.verifyClient.name),
- Item(title: AuthMenu.deleteApp.name),
- ]
- return Section(headerDescription: header, items: items)
- }
- static var oobSection: Section {
- let header = "OOB"
- let items: [Item] = [
- Item(title: AuthMenu.actionType.name, detailTitle: ActionCodeRequestType.inApp.name),
- Item(title: AuthMenu.continueURL.name, detailTitle: "--", isEditable: true),
- Item(title: AuthMenu.linkDomain.name, detailTitle: "--", isEditable: true),
- Item(title: AuthMenu.requestVerifyEmail.name),
- Item(title: AuthMenu.requestPasswordReset.name),
- Item(title: AuthMenu.resetPassword.name),
- Item(title: AuthMenu.checkActionCode.name),
- Item(title: AuthMenu.applyActionCode.name),
- Item(title: AuthMenu.verifyPasswordResetCode.name),
- ]
- return Section(headerDescription: header, items: items)
- }
- static var multifactorSection: Section {
- let header = "Multi Factor"
- let items: [Item] = [
- Item(title: AuthMenu.phoneEnroll.name),
- Item(title: AuthMenu.totpEnroll.name),
- Item(title: AuthMenu.multifactorUnenroll.name),
- ]
- return Section(headerDescription: header, items: items)
- }
- static let sections: [Section] =
- [settingsSection, providerSection, emailPasswordSection, otherSection, recaptchaSection,
- customAuthDomainSection, appSection, oobSection, multifactorSection]
- static var authLinkSections: [Section] {
- let allItems = [providerSection, emailPasswordSection, otherSection].flatMap { $0.items }
- let header = "Manage linking between providers"
- let footer =
- "Select an unchecked row to link the currently signed in user to that auth provider. To unlink the user from a linked provider, select its corresponding row marked with a checkmark."
- return [Section(headerDescription: header, footerDescription: footer, items: allItems)]
- }
- var sections: [Section] = AuthMenuData.sections
- }
|