class AppIdsImporter(object):
    def __init__(self):
        self.market = None
        self.category_ids = None
        self.database_service = DatabaseService()
        self.redis_service = RedisService()

    def imported(self, date_str, **kargs):
        print 'Started to import ids'
        logger.info('Started to import ids')
        for category_id in self.category_ids:
            import_ids_set = set()
            for letter in string.uppercase:
                for content in self._load(date_str, category_id, letter):
                    import_ids_set.update(self._parser(content))
                
            print len(import_ids_set)
            self._save(import_ids_set)
            garbage_number = gc.collect()
            print 'Garbage number:', garbage_number
        
        self.database_service.close()

    def _load(self, date_str, category_id, letter):
        category_page_key = CATEGORY_PAGE_KEY.format(date=date_str, category_id=category_id, market=self.market, letter=letter)
        print category_page_key
        category_pages = self.redis_service.members_set(category_page_key)
        for category_page in category_pages:
            yield zlib.decompress(category_page)

    @abstractmethod
    def _parser(self, content):
        """

        :param content:
        :return: ids set
        """
        raise NotImplementedError()

    def _save(self, ids_set):
        if not ids_set:
            return
        try:
            self.database_service.import_ids(self.market, ids_set)
            print 'Succeed import ids: {}'.format(len(ids_set))
            logger.info('Succeed import ids: {}'.format(len(ids_set)))

        except Exception as ex:
            logger.exception(ex)
            print ex
            logger.error('Failed import ids {}'.format(len(ids_set)))
            print 'Failed import ids.'
Example #2
0
    def test_jwt_token_contains_subject_and_user_type(self):
        email = "*****@*****.**"
        password = "******"
        db = DatabaseService()
        api_config = APIConfig()
        db.save_user(email=email, password=password)
        data = json.dumps({
            "email": "*****@*****.**",
            "password": "******"
        })

        result = self.app.post("/api/v1/login", data=data)
        try:
            data = json.loads(result.data)
            token = data["token"]
            decoded = jwt.decode(token,
                                 api_config.SECRET_KEY,
                                 algorithms=["HS256"])
            subject = decoded["subject"]
            userType = decoded["userType"]
        except:
            decoded = None
        self.assertIsNotNone(decoded)
Example #3
0
def get_profile():

    auth_header = request.headers.get("Authorization")
    if auth_header is None:
        return make_response("Valid token required", 401)

    try:
        encoded = auth_header.split(" ")[1]
        decoded = jwt.decode(encoded,
                             app.config["SECRET_KEY"],
                             algorithms=["HS256"])
        email = decoded["subject"]
    except:
        return make_response("Invalid token", 401)

    db = DatabaseService()
    user = db.get_user(email)
    formattedUser = {
        "email": user["email"],
        "firstName": user["firstName"],
        "lastName": user["lastName"],
        "userType": user["userType"],
    }
    return jsonify(formattedUser)
Example #4
0
def login():
    try:
        data = get_request_data(request, ["email", "password"])
    except (ValueError, TypeError) as e:
        return handle_error(
            message="Invalid parameters: %s" % str(e),
            logger=logger,
            status_code=422
        )

    db = DatabaseService()
    userType = db.authenticate_user(
        email=data["email"], 
        password=data["password"],
    )
    if not userType:
        return make_response("Error: invalid credentials", 401)

    token = jwt.encode(
        {"subject": data["email"], "userType": userType},
        app.config["SECRET_KEY"],
        algorithm="HS256",
    )
    return jsonify({"token": token})
Example #5
0
def create_validation_token():
    try:
        data = get_request_data(
            request,
            required_params=["email"],
        )
    except (ValueError, TypeError) as e:
        return handle_error(
            message="%s: %s" % (request.url, str(e)),
            logger=logger,
            status_code=422,
        )

    token = DatabaseService().create_validation_token(email=data["email"])
    if token is None:
        return make_response("Could not generate unique token", 500)

    return jsonify({"token": token})
Example #6
0
    def test_reset_password_updates_password(self):
        email = "*****@*****.**"
        token = "testtoken"
        password1 = "testpassword1"
        password2 = "testpassword2"

        db = DatabaseService()
        db.save_user(email=email, password=password1)
        db.save_reset_token(email=email, token=token)
        data = json.dumps({
            "token": token,
            "password": password2,
            "passwordCheck": password2,
        })

        self.app.post("/api/v1/reset-password", data=data)
        result = db.authenticate_user(email=email, password=password2)
        self.assertIsNotNone(result)
Example #7
0
def confirm_validation_token():
    try:
        data = get_request_data(
            request,
            required_params=["token"],
        )
    except (ValueError, TypeError) as e:
        return handle_error(
            message="%s: %s" % (request.url, str(e)),
            logger=logger,
            status_code=422,
        )

    try:
        email = DatabaseService().confirm_validation_token(data["token"])
        if email is not None:
            return jsonify({"email": email})
    except TypeError:
        logger.error("Could not get email for token %s" % data["token"])

    return make_response("Invalid token", 401)
Example #8
0
    def test_user_can_login_with_new_password_after_reset_password(self):
        email = "*****@*****.**"
        token = "testtoken"
        password1 = "testpassword1"
        password2 = "testpassword2"

        db = DatabaseService()
        db.save_user(email=email, password=password1)
        db.save_reset_token(email=email, token=token)
        data = json.dumps({
            "token": token,
            "password": password2,
            "passwordCheck": password2,
        })

        self.app.post("/api/v1/reset-password", data=data)

        login_data = json.dumps({"email": email, "password": password2})
        result = self.app.post("/api/v1/login", data=login_data)
        self.assertEqual(result.status_code, 200)
 def __init__(self):
     self.market = None
     self.category_ids = None
     self.database_service = DatabaseService()
     self.redis_service = RedisService()
 def setUp(self):
     super(TestDatabaseService, self).setUp()
     self.db = DatabaseService()
class TestDatabaseService(BaseTest):
    def setUp(self):
        super(TestDatabaseService, self).setUp()
        self.db = DatabaseService()

    def tearDown(self):
        super(TestDatabaseService, self).tearDown()

    def test_database_service_can_connect(self):
        self.assertIsNotNone(self.db)

    def test_database_service_can_save_user(self):
        email = '*****@*****.**'
        password = '******'
        self.db.save_user(
            email=email,
            password=password,
        )

        query = "SELECT COUNT(*) FROM users"
        curr = self.conn.cursor()
        curr.execute(query)
        results = curr.fetchall()
        self.assertEqual(1, results[0][0])
        curr.close()

    def test_database_service_saves_user_with_correct_email(self):
        email = '*****@*****.**'
        password = '******'
        self.db.save_user(
            email=email,
            password=password,
        )

        query = "SELECT email FROM users"
        curr = self.conn.cursor()
        curr.execute(query)
        results = curr.fetchall()
        self.assertEqual(email, results[0][0])
        curr.close()

    def test_database_service_saves_email_as_lowercase(self):
        email = '*****@*****.**'
        lowercaseEmail = '*****@*****.**'
        password = '******'
        self.db.save_user(
            email=email,
            password=password,
        )

        query = "SELECT email FROM users"
        curr = self.conn.cursor()
        curr.execute(query)
        results = curr.fetchall()
        self.assertEqual(lowercaseEmail, results[0][0])
        curr.close()

    def test_database_service_saves_hashed_password(self):
        email = '*****@*****.**'
        password = '******'
        self.db.save_user(
            email=email,
            password=password,
        )

        query = "SELECT password FROM users"
        curr = self.conn.cursor()
        curr.execute(query)
        results = curr.fetchall()
        self.assertNotEqual(password, results[0][0])
        curr.close()

    def test_database_services_saves_correct_password(self):
        email = '*****@*****.**'
        password = '******'
        self.db.save_user(
            email=email,
            password=password,
        )

        query = "SELECT password FROM users"
        curr = self.conn.cursor()
        curr.execute(query)
        results = curr.fetchall()
        self.assertTrue(check_password_hash(results[0][0], password))
        curr.close()

    def test_database_service_saves_first_and_last_name(self):
        email = '*****@*****.**'
        password = '******'
        firstName = 'First'
        lastName = 'Last'
        self.db.save_user(
            email=email,
            password=password,
            firstName=firstName,
            lastName=lastName,
        )

        query = "SELECT first_name, last_name FROM users"
        curr = self.conn.cursor()
        curr.execute(query)
        results = curr.fetchall()
        self.assertEqual(firstName, results[0][0])
        self.assertEqual(lastName, results[0][1])
        curr.close()

    def test_database_service_handles_default_values_for_first_and_last_name(
            self):
        email = '*****@*****.**'
        password = '******'
        self.db.save_user(
            email=email,
            password=password,
        )

        query = "SELECT first_name, last_name FROM users"
        curr = self.conn.cursor()
        curr.execute(query)
        results = curr.fetchall()
        self.assertEqual(None, results[0][0])
        self.assertEqual(None, results[0][1])
        curr.close()

    def test_database_service_can_authorize_valid_user_credentials(self):
        email = '*****@*****.**'
        password = '******'
        self.db.save_user(
            email=email,
            password=password,
        )

        result = self.db.authenticate_user(email=email, password=password)
        self.assertIsNotNone(result)

    def test_database_service_returns_user_type_after_authorizing(self):
        email = '*****@*****.**'
        password = '******'
        userType = 'testtype'
        self.db.save_user(
            email=email,
            password=password,
            userType=userType,
        )

        result = self.db.authenticate_user(email=email, password=password)
        self.assertEqual(userType, result)

    def test_database_service_handles_nonexistent_user(self):
        email = '*****@*****.**'
        password = '******'
        result = self.db.authenticate_user(email=email, password=password)
        self.assertEqual(result, None)

    def test_database_service_creates_user_with_correct_user_type(self):
        email = '*****@*****.**'
        password = '******'
        userType = 'testtype'
        self.db.save_user(
            email=email,
            password=password,
            userType=userType,
        )

        query = "SELECT user_type FROM users"
        curr = self.conn.cursor()
        curr.execute(query)
        results = curr.fetchall()
        self.assertEqual(userType, results[0][0])
        curr.close()

    def test_database_service_can_return_user_data(self):
        email = '*****@*****.**'
        password = '******'
        userType = 'testtype'
        self.db.save_user(
            email=email,
            password=password,
            userType=userType,
        )

        user = self.db.get_user(email=email)
        self.assertIsNotNone(user)

    def test_database_service_returns_correct_user_data_on_get_user(self):
        email = '*****@*****.**'
        password = '******'
        userType = 'testtype'
        firstName = 'First'
        lastName = 'Last'
        self.db.save_user(
            email=email,
            password=password,
            userType=userType,
            firstName=firstName,
            lastName=lastName,
        )

        user = self.db.get_user(email=email)
        self.assertEqual(user['email'], email)
        self.assertEqual(user['firstName'], firstName)
        self.assertEqual(user['lastName'], lastName)
        self.assertEqual(user['userType'], userType)

    def test_database_service_can_save_reset_token(self):
        self.db.save_reset_token(
            email='*****@*****.**',
            token='thisisatesttoken',
        )

        query = "SELECT * FROM reset_tokens"
        curr = self.conn.cursor()
        curr.execute(query)
        results = curr.fetchall()
        curr.close()
        self.assertIsNotNone(results[0])

    def test_database_service_can_validate_saved_reset_token(self):
        email = '*****@*****.**'
        token = 'testtoken'

        curr = self.conn.cursor()
        data = (email, token)
        query = "INSERT INTO reset_tokens (email, token) VALUES (%s, %s)"
        curr.execute(query, data)
        self.conn.commit()

        user_email = self.db.validate_reset_token(token=token)
        self.assertIsNotNone(user_email)

    def test_database_service_can_update_password(self):
        email = '*****@*****.**'
        password1 = 'testpass1'
        password2 = 'testpass2'

        self.db.save_user(email=email, password=password1)
        query = "SELECT password FROM users"
        curr = self.conn.cursor()
        curr.execute(query)
        results = curr.fetchall()
        curr.close()
        first_password = results[0][0]

        self.db.update_password(email=email, password=password2)
        query = "SELECT password FROM users"
        curr = self.conn.cursor()
        curr.execute(query)
        results = curr.fetchall()
        curr.close()
        second_password = results[0][0]

        self.assertNotEqual(first_password, second_password)
class AppDetailImporter(object):
    def __init__(self):
        self.market = None
        self.database_service = DatabaseService()
        self.redis_service = RedisService()

    def imported(self, date_str, **kwargs):
        start_id = kwargs.get('start', 1)
        end_id = kwargs.get('end', -1)
        ids = self.database_service.load_ids(self.market, start_id, end_id)
        for batch_app_ids in chunks(ids, DEFAULT_BATCH_SIZE):
            print 'Started to import batch:', len(batch_app_ids)
            logger.info('Started to import batch: {}'.format(len(batch_app_ids)))
            for app_id in batch_app_ids:
                content = self._load(date_str, app_id)
                detail_dict = self._parser(content)
                self._save(app_id, detail_dict)

            garbage_number = gc.collect()
            print 'Garbage number:', garbage_number

        self.database_service.close()

    def _load(self, date_str, app_id):
        app_detail_key = DETAIL_SOURCE_KEY.format(date=date_str, market=self.market, app_id=app_id)
        detail = self.redis_service.get(app_detail_key)
        if detail:
            return zlib.decompress(detail)

    @abstractmethod
    def _parser(self, content):
        """

        :param content:
        :return: detail dict
        """
        raise NotImplementedError()

    def _save(self, app_id, current_detail):
        if not current_detail:
            return
        try:
            last_detail = self.database_service.get_app_detail(self.market, app_id)
            if self._need_to_update(last_detail, current_detail):
                self.database_service.update_app_detail(self.market, app_id, current_detail)
                logger.info('Succeed save detail for {} in {}'.format(app_id, self.market))
                print 'Succeed save detail for {} in {}'.format(app_id, self.market)
                
                if last_detail['name'] != 'NULL':
                    self.database_service.save_event(app_id, last_detail, current_detail)
                    logger.info('Succeed save event for {} in {}'.format(app_id, self.market))
                    print 'Succeed save event for {} in {}'.format(app_id, self.market)

           # elif self._need_to_update_icon(last_detail, current_detail):
           #     self.database_service.save_icon_event(app_id, last_detail, current_detail)
           #     logger.info('Succeed save icon event for {} in {}'.format(app_id, self.market))
           #     print 'Succeed save icon event for {} in {}'.format(app_id, self.market)

            else:
                logger.info('Not need to update for {} in {}'.format(app_id, self.market))
                print 'Not need to update for {} in {}'.format(app_id, self.market)

        except Exception as ex:
            print ex
            logger.exception(ex)
            logger.info('Failed update detail and event for {} in {}'.format(app_id, self.market))
            print 'Failed save detail and event for {} in {}'.format(app_id, self.market)

    @staticmethod
    def _need_to_update(last_detail_dict, current_detail_dict):
        if last_detail_dict['name'] != current_detail_dict['name']:
            return True
    
    @staticmethod
    def _need_to_update_icon(last_detail, current_detail_dict):
        if last_detail['icon_url'] != current_detail_dict['icon_url']:
            return True