Added delete option to database storage.
This commit is contained in:
		
							parent
							
								
									308604a33c
								
							
						
					
					
						commit
						963b5bc68b
					
				
					 1868 changed files with 192402 additions and 13278 deletions
				
			
		
							
								
								
									
										520
									
								
								venv/Lib/site-packages/firebase_admin/_user_import.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										520
									
								
								venv/Lib/site-packages/firebase_admin/_user_import.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,520 @@ | |||
| # Copyright 2018 Google Inc. | ||||
| # | ||||
| # 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. | ||||
| 
 | ||||
| """Firebase user import sub module.""" | ||||
| 
 | ||||
| import base64 | ||||
| import json | ||||
| 
 | ||||
| from firebase_admin import _auth_utils | ||||
| 
 | ||||
| 
 | ||||
| def b64_encode(bytes_value): | ||||
|     return base64.urlsafe_b64encode(bytes_value).decode() | ||||
| 
 | ||||
| 
 | ||||
| class UserProvider: | ||||
|     """Represents a user identity provider that can be associated with a Firebase user. | ||||
| 
 | ||||
|     One or more providers can be specified in an ``ImportUserRecord`` when importing users via | ||||
|     ``auth.import_users()``. | ||||
| 
 | ||||
|     Args: | ||||
|         uid: User's unique ID assigned by the identity provider. | ||||
|         provider_id: ID of the identity provider. This can be a short domain name or the identifier | ||||
|             of an OpenID identity provider. | ||||
|         email: User's email address (optional). | ||||
|         display_name: User's display name (optional). | ||||
|         photo_url: User's photo URL (optional). | ||||
|     """ | ||||
| 
 | ||||
|     def __init__(self, uid, provider_id, email=None, display_name=None, photo_url=None): | ||||
|         self.uid = uid | ||||
|         self.provider_id = provider_id | ||||
|         self.email = email | ||||
|         self.display_name = display_name | ||||
|         self.photo_url = photo_url | ||||
| 
 | ||||
|     @property | ||||
|     def uid(self): | ||||
|         return self._uid | ||||
| 
 | ||||
|     @uid.setter | ||||
|     def uid(self, uid): | ||||
|         self._uid = _auth_utils.validate_uid(uid, required=True) | ||||
| 
 | ||||
|     @property | ||||
|     def provider_id(self): | ||||
|         return self._provider_id | ||||
| 
 | ||||
|     @provider_id.setter | ||||
|     def provider_id(self, provider_id): | ||||
|         self._provider_id = _auth_utils.validate_provider_id(provider_id, required=True) | ||||
| 
 | ||||
|     @property | ||||
|     def email(self): | ||||
|         return self._email | ||||
| 
 | ||||
|     @email.setter | ||||
|     def email(self, email): | ||||
|         self._email = _auth_utils.validate_email(email) | ||||
| 
 | ||||
|     @property | ||||
|     def display_name(self): | ||||
|         return self._display_name | ||||
| 
 | ||||
|     @display_name.setter | ||||
|     def display_name(self, display_name): | ||||
|         self._display_name = _auth_utils.validate_display_name(display_name) | ||||
| 
 | ||||
|     @property | ||||
|     def photo_url(self): | ||||
|         return self._photo_url | ||||
| 
 | ||||
|     @photo_url.setter | ||||
|     def photo_url(self, photo_url): | ||||
|         self._photo_url = _auth_utils.validate_photo_url(photo_url) | ||||
| 
 | ||||
|     def to_dict(self): | ||||
|         payload = { | ||||
|             'rawId': self.uid, | ||||
|             'providerId': self.provider_id, | ||||
|             'displayName': self.display_name, | ||||
|             'email': self.email, | ||||
|             'photoUrl': self.photo_url, | ||||
|         } | ||||
|         return {k: v for k, v in payload.items() if v is not None} | ||||
| 
 | ||||
| 
 | ||||
| class ImportUserRecord: | ||||
|     """Represents a user account to be imported to Firebase Auth. | ||||
| 
 | ||||
|     Must specify the ``uid`` field at a minimum. A sequence of ``ImportUserRecord`` objects can be | ||||
|     passed to the ``auth.import_users()`` function, in order to import those users into Firebase | ||||
|     Auth in bulk. If the ``password_hash`` is set on a user, a hash configuration must be | ||||
|     specified when calling ``import_users()``. | ||||
| 
 | ||||
|     Args: | ||||
|         uid: User's unique ID. Must be a non-empty string not longer than 128 characters. | ||||
|         email: User's email address (optional). | ||||
|         email_verified: A boolean indicating whether the user's email has been verified (optional). | ||||
|         display_name: User's display name (optional). | ||||
|         phone_number: User's phone number (optional). | ||||
|         photo_url: User's photo URL (optional). | ||||
|         disabled: A boolean indicating whether this user account has been disabled (optional). | ||||
|         user_metadata: An ``auth.UserMetadata`` instance with additional user metadata (optional). | ||||
|         provider_data: A list of ``auth.UserProvider`` instances (optional). | ||||
|         custom_claims: A ``dict`` of custom claims to be set on the user account (optional). | ||||
|         password_hash: User's password hash as a ``bytes`` sequence (optional). | ||||
|         password_salt: User's password salt as a ``bytes`` sequence (optional). | ||||
| 
 | ||||
|     Raises: | ||||
|         ValueError: If provided arguments are invalid. | ||||
|     """ | ||||
| 
 | ||||
|     def __init__(self, uid, email=None, email_verified=None, display_name=None, phone_number=None, | ||||
|                  photo_url=None, disabled=None, user_metadata=None, provider_data=None, | ||||
|                  custom_claims=None, password_hash=None, password_salt=None): | ||||
|         self.uid = uid | ||||
|         self.email = email | ||||
|         self.display_name = display_name | ||||
|         self.phone_number = phone_number | ||||
|         self.photo_url = photo_url | ||||
|         self.password_hash = password_hash | ||||
|         self.password_salt = password_salt | ||||
|         self.email_verified = email_verified | ||||
|         self.disabled = disabled | ||||
|         self.user_metadata = user_metadata | ||||
|         self.provider_data = provider_data | ||||
|         self.custom_claims = custom_claims | ||||
| 
 | ||||
|     @property | ||||
|     def uid(self): | ||||
|         return self._uid | ||||
| 
 | ||||
|     @uid.setter | ||||
|     def uid(self, uid): | ||||
|         self._uid = _auth_utils.validate_uid(uid, required=True) | ||||
| 
 | ||||
|     @property | ||||
|     def email(self): | ||||
|         return self._email | ||||
| 
 | ||||
|     @email.setter | ||||
|     def email(self, email): | ||||
|         self._email = _auth_utils.validate_email(email) | ||||
| 
 | ||||
|     @property | ||||
|     def display_name(self): | ||||
|         return self._display_name | ||||
| 
 | ||||
|     @display_name.setter | ||||
|     def display_name(self, display_name): | ||||
|         self._display_name = _auth_utils.validate_display_name(display_name) | ||||
| 
 | ||||
|     @property | ||||
|     def phone_number(self): | ||||
|         return self._phone_number | ||||
| 
 | ||||
|     @phone_number.setter | ||||
|     def phone_number(self, phone_number): | ||||
|         self._phone_number = _auth_utils.validate_phone(phone_number) | ||||
| 
 | ||||
|     @property | ||||
|     def photo_url(self): | ||||
|         return self._photo_url | ||||
| 
 | ||||
|     @photo_url.setter | ||||
|     def photo_url(self, photo_url): | ||||
|         self._photo_url = _auth_utils.validate_photo_url(photo_url) | ||||
| 
 | ||||
|     @property | ||||
|     def password_hash(self): | ||||
|         return self._password_hash | ||||
| 
 | ||||
|     @password_hash.setter | ||||
|     def password_hash(self, password_hash): | ||||
|         self._password_hash = _auth_utils.validate_bytes(password_hash, 'password_hash') | ||||
| 
 | ||||
|     @property | ||||
|     def password_salt(self): | ||||
|         return self._password_salt | ||||
| 
 | ||||
|     @password_salt.setter | ||||
|     def password_salt(self, password_salt): | ||||
|         self._password_salt = _auth_utils.validate_bytes(password_salt, 'password_salt') | ||||
| 
 | ||||
|     @property | ||||
|     def user_metadata(self): | ||||
|         return self._user_metadata | ||||
| 
 | ||||
|     @user_metadata.setter | ||||
|     def user_metadata(self, user_metadata): | ||||
|         created_at = user_metadata.creation_timestamp if user_metadata is not None else None | ||||
|         last_login_at = user_metadata.last_sign_in_timestamp if user_metadata is not None else None | ||||
|         self._created_at = _auth_utils.validate_timestamp(created_at, 'creation_timestamp') | ||||
|         self._last_login_at = _auth_utils.validate_timestamp( | ||||
|             last_login_at, 'last_sign_in_timestamp') | ||||
|         self._user_metadata = user_metadata | ||||
| 
 | ||||
|     @property | ||||
|     def provider_data(self): | ||||
|         return self._provider_data | ||||
| 
 | ||||
|     @provider_data.setter | ||||
|     def provider_data(self, provider_data): | ||||
|         if provider_data is not None: | ||||
|             try: | ||||
|                 if any([not isinstance(p, UserProvider) for p in provider_data]): | ||||
|                     raise ValueError('One or more provider data instances are invalid.') | ||||
|             except TypeError: | ||||
|                 raise ValueError('provider_data must be iterable.') | ||||
|         self._provider_data = provider_data | ||||
| 
 | ||||
|     @property | ||||
|     def custom_claims(self): | ||||
|         return self._custom_claims | ||||
| 
 | ||||
|     @custom_claims.setter | ||||
|     def custom_claims(self, custom_claims): | ||||
|         json_claims = json.dumps(custom_claims) if isinstance( | ||||
|             custom_claims, dict) else custom_claims | ||||
|         self._custom_claims_str = _auth_utils.validate_custom_claims(json_claims) | ||||
|         self._custom_claims = custom_claims | ||||
| 
 | ||||
|     def to_dict(self): | ||||
|         """Returns a dict representation of the user. For internal use only.""" | ||||
|         payload = { | ||||
|             'localId': self.uid, | ||||
|             'email': self.email, | ||||
|             'displayName': self.display_name, | ||||
|             'phoneNumber': self.phone_number, | ||||
|             'photoUrl': self.photo_url, | ||||
|             'emailVerified': (bool(self.email_verified) | ||||
|                               if self.email_verified is not None else None), | ||||
|             'disabled': bool(self.disabled) if self.disabled is not None else None, | ||||
|             'customAttributes': self._custom_claims_str, | ||||
|             'createdAt': self._created_at, | ||||
|             'lastLoginAt': self._last_login_at, | ||||
|             'passwordHash': b64_encode(self.password_hash) if self.password_hash else None, | ||||
|             'salt': b64_encode(self.password_salt) if self.password_salt else None, | ||||
|         } | ||||
|         if self.provider_data: | ||||
|             payload['providerUserInfo'] = [p.to_dict() for p in self.provider_data] | ||||
|         return {k: v for k, v in payload.items() if v is not None} | ||||
| 
 | ||||
| 
 | ||||
| class UserImportHash: | ||||
|     """Represents a hash algorithm used to hash user passwords. | ||||
| 
 | ||||
|     An instance of this class must be specified when importing users with passwords via the | ||||
|     ``auth.import_users()`` API. Use one of the provided class methods to obtain new | ||||
|     instances when required. Refer to `documentation`_ for more details. | ||||
| 
 | ||||
|     .. _documentation: https://firebase.google.com/docs/auth/admin/import-users | ||||
|     """ | ||||
| 
 | ||||
|     def __init__(self, name, data=None): | ||||
|         self._name = name | ||||
|         self._data = data | ||||
| 
 | ||||
|     def to_dict(self): | ||||
|         payload = {'hashAlgorithm': self._name} | ||||
|         if self._data: | ||||
|             payload.update(self._data) | ||||
|         return payload | ||||
| 
 | ||||
|     @classmethod | ||||
|     def _hmac(cls, name, key): | ||||
|         data = { | ||||
|             'signerKey': b64_encode(_auth_utils.validate_bytes(key, 'key', required=True)) | ||||
|         } | ||||
|         return UserImportHash(name, data) | ||||
| 
 | ||||
|     @classmethod | ||||
|     def hmac_sha512(cls, key): | ||||
|         """Creates a new HMAC SHA512 algorithm instance. | ||||
| 
 | ||||
|         Args: | ||||
|             key: Signer key as a byte sequence. | ||||
| 
 | ||||
|         Returns: | ||||
|             UserImportHash: A new ``UserImportHash``. | ||||
|         """ | ||||
|         return cls._hmac('HMAC_SHA512', key) | ||||
| 
 | ||||
|     @classmethod | ||||
|     def hmac_sha256(cls, key): | ||||
|         """Creates a new HMAC SHA256 algorithm instance. | ||||
| 
 | ||||
|         Args: | ||||
|             key: Signer key as a byte sequence. | ||||
| 
 | ||||
|         Returns: | ||||
|             UserImportHash: A new ``UserImportHash``. | ||||
|         """ | ||||
|         return cls._hmac('HMAC_SHA256', key) | ||||
| 
 | ||||
|     @classmethod | ||||
|     def hmac_sha1(cls, key): | ||||
|         """Creates a new HMAC SHA1 algorithm instance. | ||||
| 
 | ||||
|         Args: | ||||
|             key: Signer key as a byte sequence. | ||||
| 
 | ||||
|         Returns: | ||||
|             UserImportHash: A new ``UserImportHash``. | ||||
|         """ | ||||
|         return cls._hmac('HMAC_SHA1', key) | ||||
| 
 | ||||
|     @classmethod | ||||
|     def hmac_md5(cls, key): | ||||
|         """Creates a new HMAC MD5 algorithm instance. | ||||
| 
 | ||||
|         Args: | ||||
|             key: Signer key as a byte sequence. | ||||
| 
 | ||||
|         Returns: | ||||
|             UserImportHash: A new ``UserImportHash``. | ||||
|         """ | ||||
|         return cls._hmac('HMAC_MD5', key) | ||||
| 
 | ||||
|     @classmethod | ||||
|     def md5(cls, rounds): | ||||
|         """Creates a new MD5 algorithm instance. | ||||
| 
 | ||||
|         Args: | ||||
|             rounds: Number of rounds. Must be an integer between 0 and 8192. | ||||
| 
 | ||||
|         Returns: | ||||
|             UserImportHash: A new ``UserImportHash``. | ||||
|         """ | ||||
|         return UserImportHash( | ||||
|             'MD5', | ||||
|             {'rounds': _auth_utils.validate_int(rounds, 'rounds', 0, 8192)}) | ||||
| 
 | ||||
|     @classmethod | ||||
|     def sha1(cls, rounds): | ||||
|         """Creates a new SHA1 algorithm instance. | ||||
| 
 | ||||
|         Args: | ||||
|             rounds: Number of rounds. Must be an integer between 1 and 8192. | ||||
| 
 | ||||
|         Returns: | ||||
|             UserImportHash: A new ``UserImportHash``. | ||||
|         """ | ||||
|         return UserImportHash( | ||||
|             'SHA1', | ||||
|             {'rounds': _auth_utils.validate_int(rounds, 'rounds', 1, 8192)}) | ||||
| 
 | ||||
|     @classmethod | ||||
|     def sha256(cls, rounds): | ||||
|         """Creates a new SHA256 algorithm instance. | ||||
| 
 | ||||
|         Args: | ||||
|             rounds: Number of rounds. Must be an integer between 1 and 8192. | ||||
| 
 | ||||
|         Returns: | ||||
|             UserImportHash: A new ``UserImportHash``. | ||||
|         """ | ||||
|         return UserImportHash( | ||||
|             'SHA256', | ||||
|             {'rounds': _auth_utils.validate_int(rounds, 'rounds', 1, 8192)}) | ||||
| 
 | ||||
|     @classmethod | ||||
|     def sha512(cls, rounds): | ||||
|         """Creates a new SHA512 algorithm instance. | ||||
| 
 | ||||
|         Args: | ||||
|             rounds: Number of rounds. Must be an integer between 1 and 8192. | ||||
| 
 | ||||
|         Returns: | ||||
|             UserImportHash: A new ``UserImportHash``. | ||||
|         """ | ||||
|         return UserImportHash( | ||||
|             'SHA512', | ||||
|             {'rounds': _auth_utils.validate_int(rounds, 'rounds', 1, 8192)}) | ||||
| 
 | ||||
|     @classmethod | ||||
|     def pbkdf_sha1(cls, rounds): | ||||
|         """Creates a new PBKDF SHA1 algorithm instance. | ||||
| 
 | ||||
|         Args: | ||||
|             rounds: Number of rounds. Must be an integer between 0 and 120000. | ||||
| 
 | ||||
|         Returns: | ||||
|             UserImportHash: A new ``UserImportHash``. | ||||
|         """ | ||||
|         return UserImportHash( | ||||
|             'PBKDF_SHA1', | ||||
|             {'rounds': _auth_utils.validate_int(rounds, 'rounds', 0, 120000)}) | ||||
| 
 | ||||
|     @classmethod | ||||
|     def pbkdf2_sha256(cls, rounds): | ||||
|         """Creates a new PBKDF2 SHA256 algorithm instance. | ||||
| 
 | ||||
|         Args: | ||||
|             rounds: Number of rounds. Must be an integer between 0 and 120000. | ||||
| 
 | ||||
|         Returns: | ||||
|             UserImportHash: A new ``UserImportHash``. | ||||
|         """ | ||||
|         return UserImportHash( | ||||
|             'PBKDF2_SHA256', | ||||
|             {'rounds': _auth_utils.validate_int(rounds, 'rounds', 0, 120000)}) | ||||
| 
 | ||||
|     @classmethod | ||||
|     def scrypt(cls, key, rounds, memory_cost, salt_separator=None): | ||||
|         """Creates a new Scrypt algorithm instance. | ||||
| 
 | ||||
|         This is the modified Scrypt algorithm used by Firebase Auth. See ``standard_scrypt()`` | ||||
|         function for the standard Scrypt algorith, | ||||
| 
 | ||||
|         Args: | ||||
|             key: Signer key as a byte sequence. | ||||
|             rounds: Number of rounds. Must be an integer between 1 and 8. | ||||
|             memory_cost: Memory cost as an integer between 1 and 14. | ||||
|             salt_separator: Salt separator as a byte sequence (optional). | ||||
| 
 | ||||
|         Returns: | ||||
|             UserImportHash: A new ``UserImportHash``. | ||||
|         """ | ||||
|         data = { | ||||
|             'signerKey': b64_encode(_auth_utils.validate_bytes(key, 'key', required=True)), | ||||
|             'rounds': _auth_utils.validate_int(rounds, 'rounds', 1, 8), | ||||
|             'memoryCost': _auth_utils.validate_int(memory_cost, 'memory_cost', 1, 14), | ||||
|         } | ||||
|         if salt_separator: | ||||
|             data['saltSeparator'] = b64_encode(_auth_utils.validate_bytes( | ||||
|                 salt_separator, 'salt_separator')) | ||||
|         return UserImportHash('SCRYPT', data) | ||||
| 
 | ||||
|     @classmethod | ||||
|     def bcrypt(cls): | ||||
|         """Creates a new Bcrypt algorithm instance. | ||||
| 
 | ||||
|         Returns: | ||||
|             UserImportHash: A new ``UserImportHash``. | ||||
|         """ | ||||
|         return UserImportHash('BCRYPT') | ||||
| 
 | ||||
|     @classmethod | ||||
|     def standard_scrypt(cls, memory_cost, parallelization, block_size, derived_key_length): | ||||
|         """Creates a new standard Scrypt algorithm instance. | ||||
| 
 | ||||
|         Args: | ||||
|             memory_cost: Memory cost as a non-negaive integer. | ||||
|             parallelization: Parallelization as a non-negative integer. | ||||
|             block_size: Block size as a non-negative integer. | ||||
|             derived_key_length: Derived key length as a non-negative integer. | ||||
| 
 | ||||
|         Returns: | ||||
|             UserImportHash: A new ``UserImportHash``. | ||||
|         """ | ||||
|         data = { | ||||
|             'memoryCost': _auth_utils.validate_int(memory_cost, 'memory_cost', low=0), | ||||
|             'parallelization': _auth_utils.validate_int(parallelization, 'parallelization', low=0), | ||||
|             'blockSize': _auth_utils.validate_int(block_size, 'block_size', low=0), | ||||
|             'dkLen': _auth_utils.validate_int(derived_key_length, 'derived_key_length', low=0), | ||||
|         } | ||||
|         return UserImportHash('STANDARD_SCRYPT', data) | ||||
| 
 | ||||
| 
 | ||||
| class ErrorInfo: | ||||
|     """Represents an error encountered while performing a batch operation such | ||||
|     as importing users or deleting multiple user accounts. | ||||
|     """ | ||||
|     # TODO(rsgowman): This class used to be specific to importing users (hence | ||||
|     # it's home in _user_import.py). It's now also used by bulk deletion of | ||||
|     # users. Move this to a more common location. | ||||
| 
 | ||||
|     def __init__(self, error): | ||||
|         self._index = error['index'] | ||||
|         self._reason = error['message'] | ||||
| 
 | ||||
|     @property | ||||
|     def index(self): | ||||
|         return self._index | ||||
| 
 | ||||
|     @property | ||||
|     def reason(self): | ||||
|         return self._reason | ||||
| 
 | ||||
| 
 | ||||
| class UserImportResult: | ||||
|     """Represents the result of a bulk user import operation. | ||||
| 
 | ||||
|     See ``auth.import_users()`` API for more details. | ||||
|     """ | ||||
| 
 | ||||
|     def __init__(self, result, total): | ||||
|         errors = result.get('error', []) | ||||
|         self._success_count = total - len(errors) | ||||
|         self._failure_count = len(errors) | ||||
|         self._errors = [ErrorInfo(err) for err in errors] | ||||
| 
 | ||||
|     @property | ||||
|     def success_count(self): | ||||
|         """Returns the number of users successfully imported.""" | ||||
|         return self._success_count | ||||
| 
 | ||||
|     @property | ||||
|     def failure_count(self): | ||||
|         """Returns the number of users that failed to be imported.""" | ||||
|         return self._failure_count | ||||
| 
 | ||||
|     @property | ||||
|     def errors(self): | ||||
|         """Returns a list of ``auth.ErrorInfo`` instances describing the errors encountered.""" | ||||
|         return self._errors | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue