Ejemplo n.º 1
0
    def upload_file(cls, source_file_path, s3_object_name):
        """Upload a file to a S3 bucket

        :param source_file_path: File to upload
        :param bucket: Bucket to upload to
        :param s3_object_name: S3 object name
        :return: True if file was uploaded, else False
        """
        if cls.s3_client is None:
            raise ApplicationError("S3 client not configured!", 500)

        # If S3 object_name was not specified, raise error
        if s3_object_name is None:
            raise ApplicationError("Invalid object name for uploading file!",
                                   500)

        # Upload the file
        try:
            print(cls.bucket_name)
            print(source_file_path)
            print(s3_object_name)
            # Cloudcube requires that we add <cubename> before objectname as a path else ops will fail
            response = cls.s3_client.upload_file(
                source_file_path, cls.bucket_name,
                f"{cls.cube_name}/{s3_object_name}")
            print(f"Upload response {response}")
        except ClientError as e:
            print(e)
            raise ApplicationError("Unable to upload file. Please try again!")
        except S3UploadFailedError as se3:
            print(se3)
            raise ApplicationError("Unable to upload file. Please try again!")
        return True
Ejemplo n.º 2
0
 def reset_password_using_token(cls, user_id, token, new_password):
     """Given a password reset token, will reset password if all criteria match"""
     # match criteria = userId, token, !isConsumed & validTill > currentTime
     password_reset_doc = DM.db[
         PasswordResetTokens.COLLECTION_NAME].find_one({
             PasswordResetTokens.USERID:
             user_id,
             PasswordResetTokens.TOKEN:
             token,
             PasswordResetTokens.IS_CONSUMED:
             False,
             PasswordResetTokens.VALID_TILL: {
                 "$gte": datetime.utcnow()
             }
         })
     if password_reset_doc is None:
         raise ApplicationError(
             "Invalid password reset token. Please try again!")
     # TODO: use transactions (bit complicated but the recommended way)
     new_password_hash = password_context.hash(new_password)
     DM.db[User.COLLECTION_NAME].update_one(
         filter={"_id": ObjectId(user_id)},
         update={
             "$set": {
                 User.PASSWORD_HASH: new_password_hash,
                 User.LAST_MODIFIED_AT: datetime.utcnow()
             }
         })
     DM.db[PasswordResetTokens.COLLECTION_NAME].update_one(
         filter={"_id": ObjectId(password_reset_doc["_id"])},
         update={"$set": {
             PasswordResetTokens.IS_CONSUMED: True
         }})
Ejemplo n.º 3
0
    def create_local_user(cls, email, password):
        if cls.is_email_used(email):
            # email already exists
            raise ApplicationError(
                message="Email address already used by another account!")

        # user does not exist, create
        password_hash = password_context.hash(password)
        current_timestamp = datetime.utcnow()
        email_verification_token = str(uuid.uuid4())
        user_id = DM.db[User.COLLECTION_NAME].insert_one({
            User.EMAIL:
            email,
            User.PASSWORD_HASH:
            password_hash,
            User.CREATED_AT:
            current_timestamp,
            User.LAST_MODIFIED_AT:
            current_timestamp,
            User.EMAIL_VERIFIED:
            False,
            User.VERIFICATION_TOKEN:
            email_verification_token
        }).inserted_id

        cls.__send_email_address_verification_mail__(email,
                                                     email_verification_token)
        return user_id
 def upsert_user_profile(cls,
                         user_id,
                         full_name=None,
                         city=None,
                         country=None,
                         gender=None,
                         age=None,
                         occupation=None,
                         mobile_number=0) -> bool:
     if user_id is None or len(user_id) == 0:
         return False
     if full_name is None:
         raise ApplicationError("Please provide your name!")
     if gender is None:
         gender = "undecided"
     data = {
         UserProfile.USERID: user_id,
         UserProfile.FULL_NAME: full_name,
         UserProfile.CITY: city,
         UserProfile.COUNTRY: country,
         UserProfile.GENDER: gender,
         UserProfile.AGE: age,
         UserProfile.OCCUPATION: occupation,
         UserProfile.MOBILE_NUMBER: mobile_number,
         UserProfile.LAST_MODIFIED_AT: datetime.utcnow()
     }
     DM.db[UserProfile.COLLECTION_NAME].update_one(
         filter={UserProfile.USERID: user_id},
         update={"$set": data},
         upsert=True)
Ejemplo n.º 5
0
 def wrapper(*args, **kwargs):
     verify_jwt_in_request()
     claims = get_jwt_claims()
     is_super_admin = claims.get(JwtClaims.IS_SUPER_ADMIN, False)
     if not is_super_admin:
         raise ApplicationError("Super-Admin only endpoint!", 403)
     else:
         return fn(*args, **kwargs)
Ejemplo n.º 6
0
 def resend_email_address_verification_email(cls, user_id):
     existing_user_doc = DM.db[User.COLLECTION_NAME].find_one(
         {"_id": ObjectId(user_id)})
     if existing_user_doc is None:
         raise ApplicationError("Invalid user!")
     email_address = existing_user_doc.get(User.EMAIL, None)
     if email_address is not None and existing_user_doc.get(
             User.EMAIL_VERIFIED, False) is False:
         UserRegistrationService.__send_email_address_verification_mail__(
             email_address, existing_user_doc[User.VERIFICATION_TOKEN])
Ejemplo n.º 7
0
 def change_password(cls, user_id, existing_password, new_password):
     print(user_id)
     existing_user_doc = DM.db[User.COLLECTION_NAME].find_one(
         {"_id": ObjectId(user_id)})
     if existing_user_doc is None:
         raise ApplicationError("Invalid user!")
     if not password_context.verify(existing_password,
                                    existing_user_doc[User.PASSWORD_HASH]):
         raise ApplicationError("Existing password incorrect!")
     # now we update the document with new password
     new_password_hash = password_context.hash(new_password)
     DM.db[User.COLLECTION_NAME].update_one(
         filter={"_id": ObjectId(user_id)},
         update={
             "$set": {
                 User.PASSWORD_HASH: new_password_hash,
                 User.LAST_MODIFIED_AT: datetime.utcnow()
             }
         })
Ejemplo n.º 8
0
def __resize_picture__(full_file_path, resized_image_path, max_w=400, max_h=400):
    try:
        image = Image.open(full_file_path)
        image.thumbnail((max_w, max_h))
        # remove the alpha channel, otherwise we cannot save as jpg
        if image.mode in ("RGBA", "P"):
            image = image.convert("RGB")
        image.save(resized_image_path, quality=95)
    except UnidentifiedImageError as e:
        raise ApplicationError("Invalid image file!")
Ejemplo n.º 9
0
    def get_login_tokens(cls, email, supplied_password):
        """Gets the user matching email and password"""
        userDoc = DM.db[User.COLLECTION_NAME].find_one({User.EMAIL: email})
        if userDoc is None:
            raise ApplicationError("Invalid credentials!", 403)

        # now we match the password hash
        if password_context.verify(supplied_password,
                                   userDoc[User.PASSWORD_HASH]):
            # correct user
            # generate jwt and return
            # We use the _id as the identity value in the access token
            # mark the access token as fresh since we just verified the user's login email and password
            user_id = str(userDoc["_id"])  # convert to str from ObjectId
            return {
                "accessToken": create_access_token(user_id, fresh=True),
                "refreshToken": create_refresh_token(user_id)
            }
        else:
            raise ApplicationError("Invalid credentials!", status_code=403)
Ejemplo n.º 10
0
def __upload_image__(file, s3_object_name, max_w, max_h):
    if file is None:
        raise ApplicationError("Invalid file!")
    if file.filename == '':
        raise ApplicationError("Invalid filename!")
    if __allowed_file__(file.filename) is False:
        raise ApplicationError("Invalid file type!")

    # Save to temp directory and then upload to s3
    with tempfile.TemporaryDirectory() as tmpdirname:
        print('created temporary directory', tmpdirname)
        # Since user provided file names are inherently insecure, use the secure_filename() method
        filename = secure_filename(file.filename)
        full_file_path = os.path.join(tmpdirname, filename)
        # save to location
        file.save(full_file_path)
        # resize image
        resized_image_path = os.path.join(tmpdirname, f"{uuid.uuid4()}.jpg")
        __resize_picture__(full_file_path, resized_image_path, max_w, max_h)
        # upload to s3
        AwsS3.upload_file(resized_image_path, s3_object_name)
Ejemplo n.º 11
0
 def validate_email_address_verification_token(cls, email,
                                               verification_token):
     user = cls.__get_existing_user_by_email__(email)
     if user is None:
         raise ApplicationError(message="Invalid email id!")
     if user[User.VERIFICATION_TOKEN] == verification_token:
         # token matches, update entry
         DM.db[User.COLLECTION_NAME].update_one({User.EMAIL: email}, {
             "$set": {
                 User.EMAIL_VERIFIED: True,
                 User.LAST_MODIFIED_AT: datetime.utcnow()
             }
         })
         return True
     return False
Ejemplo n.º 12
0
 def get(self, other_user_id):
     profile_doc = UserProfileService.get_user_profile(other_user_id)
     if profile_doc is None:
         raise ApplicationError("User profile unavailable", 404)
     else:
         # return selected fields when another user requests this id
         response_dict = {
             "userId": profile_doc.get(UserProfileConstants.USERID, ""),
             "fullName": profile_doc.get(UserProfileConstants.FULL_NAME,
                                         ""),
             "country": profile_doc.get(UserProfileConstants.COUNTRY, ""),
             "city": profile_doc.get(UserProfileConstants.CITY, "")
         }
         # Add display pic field
         picture_object_name = profile_doc.get(
             UserProfileConstants.PICTURE_OBJECT_NAME)
         if picture_object_name is not None:
             response_dict["displayPicUrl"] = AwsS3.get_object_url(
                 picture_object_name)
         else:
             response_dict["displayPicUrl"] = ""
         return response_dict
Ejemplo n.º 13
0
 def post(self):
     """
     All pictures are resized & uploaded to public directory
     """
     user_id = get_jwt_identity()
     # check if the post request has the file part
     if 'file' not in request.files:
         raise ApplicationError("Key 'file' not a part of request!")
     file = request.files['file']
     # generate profile pic name with timestamp
     current_timestamp = datetime.timestamp(datetime.now())
     # NOTE: the object name is based on convention :
     # Any object name starting with "public" is publicly visible via S3
     s3_object_name = f"public/profile/{user_id}-{current_timestamp}.jpg"
     __upload_image__(file, s3_object_name, __PROFILE_PIC_MAX_WIDTH__, __PROFILE_PIC_MAX_HEIGHT__)
     # Make entry
     UserProfileService.update_profile_picture(user_id, new_pic_object_name=s3_object_name)
     return {
         "filename": s3_object_name,
         "userId": user_id,
         "url": AwsS3.get_object_url(s3_object_name)
     }