def update_profile_props(self, id=None, email=None, username=None, profile_dict={}): """Update the user profile properties. """ if id and utils.validate_id(id): user_props_dict = self.__get_all_user_props(id=id) elif email and utils.validate_email(email): user_props_dict = self.__get_all_user_props(email=email) elif username and utils.validate_username(username): user_props_dict = self.__get_all_user_props(username=username) else: return None # this fields will not be updated by this method. protected_fields = ('id', 'email', 'username', 'password',) for k,v in user_props_dict.items(): if k in protected_fields: continue elif k in profile_dict: user_props_dict[k] = profile_dict[k] table = self._nosql_table nosql = FotogalNosql() nosql_result = nosql.update(table, user_props_dict) return nosql_result
def create(self, user_id): """Create and return cookie properties to create a cookie for authentication purposes. """ fotogal_user = FotogalUser() if utils.validate_id(user_id) and fotogal_user.exists(id=user_id): random_token = self.__gen_random_token() random_token = str(user_id) + ':' + random_token # truncate to 64 chars because of the primary key limit. if len(random_token) > 64: random_token = random_token[:64] datetime_now = datetime.datetime.now() expire_timedelta = datetime_now + datetime.timedelta(days=7) created_ts = int(datetime_now.strftime('%s')) expire_ts = int(expire_timedelta.strftime('%s')) enc_base64_value = self.__encrypt(random_token) auth_session_dict = {'random_token': random_token, 'created_ts': created_ts, 'expire_ts': expire_ts, 'user_id': user_id} nosql = FotogalNosql() nosql_result = nosql.add(self._nosql_table, auth_session_dict) if nosql_result: return (self._cookie_name, enc_base64_value, expire_ts,) return None
def is_private(self, id=None, email=None, username=None): """Check if the user is a private user. """ if id and utils.validate_id(id): conditions = 'id = %d LIMIT 1' % (id,) elif email and utils.validate_email(email): conditions = 'email = "%s" LIMIT 1' % (email,) elif username and utils.validate_username(username): conditions = 'username = "******" LIMIT 1' % (username,) else: return False fields = 'is_private' table = self._nosql_table query = f'SELECT {fields} FROM {table} WHERE {conditions}' nosql = FotogalNosql() nosql_result = nosql.exec_query(table, query) if len(nosql_result) > 0: return nosql_result[0]['is_private'] else: return None
def get_user_imgs_list(self, user_id=None, limit=None, offset=None): """Return a list that contains the images posted by "user_id". """ if utils.validate_id(user_id): my_imgs_list = [] if limit and offset: conditions = '(user_id = %d AND is_profile = FALSE) ORDER BY created_ts DESC LIMIT %d OFFSET %d' % ( user_id, limit, offset, ) else: conditions = '(user_id = %d AND is_profile = FALSE) ORDER BY created_ts DESC' % ( user_id, ) fields = 'id, image_filename, image_type' table = self._img_nosql_table query = f'SELECT {fields} FROM {table} WHERE {conditions}' nosql = FotogalNosql() query_result = nosql.exec_query_loop(table, query) for dict_result in query_result: my_imgs_list.append(dict_result) return my_imgs_list
def check_passwd(self, id=None, email=None, username=None, passwd=''): """Checks the user password. """ if id and utils.validate_id(id): conditions = 'id = %d LIMIT 1' % (id,) elif email and utils.validate_email(email): conditions = 'email = "%s" LIMIT 1' % (email,) elif username and utils.validate_username(username): conditions = 'username = "******" LIMIT 1' % (username,) else: return False fields = 'password' table = self._nosql_table query = f'SELECT {fields} FROM {table} WHERE {conditions}' nosql = FotogalNosql() nosql_result = nosql.exec_query(table, query) if len(nosql_result) > 0: passwd_db_hash = nosql_result[0]['password'] try: passwd_check_status = check_password_hash(passwd_db_hash, passwd) except: return False else: if passwd_check_status: return True else: return False else: return False
def update_passwd(self, id=None, email=None, username=None, passwd=''): """Generate a new password hash and update the user. """ if id and utils.validate_id(id): user_pkey_dict = self.get_pkey_values(id=id) elif email and utils.validate_email(email): user_pkey_dict = self.get_pkey_values(email=email) elif username and utils.validate_username(username): user_pkey_dict = self.get_pkey_values(username=username) else: return None new_passwd_hash = generate_password_hash(passwd) fields = 'SET password = "******"' % (new_passwd_hash,) table = self._nosql_table conditions = 'id = %d AND email = "%s" AND username = "******"' % (user_pkey_dict['id'], user_pkey_dict['email'], user_pkey_dict['username'],) query = f'UPDATE {table} {fields} WHERE {conditions}' nosql = FotogalNosql() nosql_result = nosql.exec_query(table, query) if len(nosql_result) > 0: if nosql_result[0]['NumRowsUpdated'] == 1: return True else: return False else: return False
def get_pkey_values(self, id=None, email=None, username=None): """Returns the user's primary key values. Some operations in Oracle NoSQL (like UPDATE) requires all primary key values to be informed. """ if id and utils.validate_id(id): conditions = 'id = %d LIMIT 1' % (id,) elif email and utils.validate_email(email): conditions = 'email = "%s" LIMIT 1' % (email,) elif username and utils.validate_username(username): conditions = 'username = "******" LIMIT 1' % (username,) else: return None fields = 'id, email, username' table = self._nosql_table query = f'SELECT {fields} FROM {table} WHERE {conditions}' nosql = FotogalNosql() nosql_result = nosql.exec_query(table, query) user_dict = {'id': '', 'username': '', 'email': ''} if len(nosql_result) > 0: user_dict['id'] = nosql_result[0]['id'] user_dict['username'] = nosql_result[0]['username'] user_dict['email'] = nosql_result[0]['email'] return user_dict else: return user_dict
def remove(self, user_id, img_filename): """Remove an image by filename. """ if utils.validate_id(user_id): table = self._img_nosql_table conditions = 'user_id = %d AND image_filename = "%s"' % ( user_id, img_filename, ) query = f'DELETE FROM {table} WHERE {conditions}' nosql = FotogalNosql() nosql_result = nosql.exec_query(table, query) if len(nosql_result ) > 0 and nosql_result[0]['numRowsDeleted'] == 1: self.__del_img_data(img_filename) return True else: return False return None
def get_profile_img_url(self, id=None, email=None, username=None): """Return the image profile URL. """ if id and utils.validate_id(id): conditions = 'id = %d LIMIT 1' % (id,) elif email and utils.validate_email(email): conditions = 'email = "%s" LIMIT 1' % (email,) elif username and utils.validate_username(username): conditions = 'username = "******" LIMIT 1' % (username,) else: return None fields = 'profile_image_url' table = self._nosql_table query = f'SELECT {fields} FROM {table} WHERE {conditions}' nosql = FotogalNosql() nosql_result = nosql.exec_query(table, query) if len(nosql_result) > 0: return nosql_result[0]['profile_image_url'] else: return None
def get_posted_imgs_list(self, user_id=None, follow_user_id=None, limit=None, offset=None): """Returns a list of a user's posted images """ if utils.validate_id(user_id): posted_imgs_list = [] if limit and offset: conditions = '(user_id = %d AND is_profile = FALSE) ORDER BY created_ts DESC LIMIT %d OFFSET %d' % ( follow_user_id, limit, offset, ) else: conditions = '(user_id = %d AND is_profile = FALSE) ORDER BY created_ts DESC' % ( follow_user_id, ) fields = 'id, user_id, image_filename, main_comment, created_ts,' \ + 'liked_list[$element = %d] AS liked_by_me, disliked_list[$element = %d] AS disliked_by_me' % (user_id, user_id,) table = self._img_nosql_table query = f'SELECT {fields} FROM {table} WHERE {conditions}' nosql = FotogalNosql() query_result = nosql.exec_query_loop(table, query) fotogal_user = FotogalUser() for dict_result in query_result: img_username = fotogal_user.get_username( id=dict_result['user_id']) profile_img_url = fotogal_user.get_profile_img_url( id=dict_result['user_id']) if dict_result['liked_by_me'] is not None: dict_result['liked_by_me'] = True else: dict_result['liked_by_me'] = False if dict_result['disliked_by_me'] is not None: dict_result['disliked_by_me'] = True else: dict_result['disliked_by_me'] = False dict_result.update({'username': img_username}) dict_result.update({'profile_image_url': profile_img_url}) dict_result.pop('user_id') posted_imgs_list.append(dict_result) return posted_imgs_list
def add_new_user(self, new_user_dict={}): """Add a new user and return the new generated ID from NoSQL. """ if 'password' in new_user_dict: passwd_hash = generate_password_hash(new_user_dict['password']) new_user_dict['password'] = passwd_hash table = self._nosql_table nosql = FotogalNosql() nosql_result = nosql.add(table, new_user_dict) return nosql_result else: return None
def get_suggestions(self): """Return some users as suggestions to follow. """ MAX_USERS_TO_RETURN = 30 fields = 'id, full_name, username, profile_image_url, is_private' conditions = 'is_professional_account = TRUE LIMIT %d' % ( MAX_USERS_TO_RETURN, ) table = self._nosql_table query = f'SELECT {fields} FROM {table} WHERE {conditions}' nosql = FotogalNosql() nosql_result = nosql.exec_query(table, query) return nosql_result
def get_posted_imgs_total(self, user_id): """Return the total count of images posted by a "user_id". """ if utils.validate_id(user_id): fields = 'count(image_filename) AS total' table = self._img_nosql_table conditions = 'user_id = %d AND is_profile = FALSE' % (user_id, ) query = f'SELECT {fields} FROM {table} WHERE {conditions}' nosql = FotogalNosql() nosql_result = nosql.exec_query(table, query) if len(nosql_result) > 0: return nosql_result[0]['total'] else: return 0
def get_img_props(self, id): """Return image properties. """ if utils.validate_id(id): fields = 'id, image_filename, image_original_filename, user_id, created_ts, is_profile' table = self._img_nosql_table conditions = 'id = %d LIMIT 1' % (id, ) query = f'SELECT {fields} FROM {table} WHERE {conditions}' nosql = FotogalNosql() nosql_result = nosql.exec_query(table, query) if len(nosql_result) > 0: return nosql_result[0] return None
def get_following_total(self, user_id): """Returns the total from "follow_list". """ if utils.validate_id(user_id): fields = 'count(follow_list[]) AS total' table = self._nosql_table conditions = 'id = %d' % (user_id, ) query = f'SELECT {fields} FROM {table} WHERE {conditions}' nosql = FotogalNosql() nosql_result = nosql.exec_query(table, query) if len(nosql_result) > 0: return nosql_result[0]['total'] else: return 0
def get_data(self, request_user_id, img_owner_username, img_filename): """Return the image headers and content if the user requesting the image has following authorization. """ if utils.validate_id(request_user_id) and utils.validate_username( img_owner_username): fotogal_user = FotogalUser() img_owner_user_id = fotogal_user.get_id( username=img_owner_username) fotogal_follow = FotogalFollow() if request_user_id == img_owner_user_id or fotogal_follow.is_following( request_user_id, img_owner_user_id): fields = 'image_filename, image_type' table = self._img_nosql_table conditions = 'user_id = %d AND image_filename = "%s" LIMIT 1' % ( img_owner_user_id, img_filename, ) query = f'SELECT {fields} FROM {table} WHERE {conditions}' nosql = FotogalNosql() nosql_result = nosql.exec_query(table, query) if len(nosql_result) > 0: ( img_headers, img_content, ) = self.__get_img_data(img_filename) return ( img_headers, img_content, ) return ( None, None, )
def is_following(self, user_id, follow_user_id): """Return TRUE if the "user_id" is following the "follow_user_id". """ if utils.validate_id(user_id) and utils.validate_id(follow_user_id): fields = 'follow_list[$element = %d] AS follow_user_id' % ( follow_user_id, ) table = self._nosql_table conditions = 'id = %d' % (user_id, ) query = f'SELECT {fields} FROM {table} WHERE {conditions}' nosql = FotogalNosql() nosql_result = nosql.exec_query(table, query) if len(nosql_result) > 0: if nosql_result[0]['follow_user_id'] == follow_user_id: return True else: return False
def remove_dislike(self, id, user_id): """Remove the "user_id" from "disliked_list" array of the "img_id". """ if utils.validate_id(id) and utils.validate_id(user_id): table = self._img_nosql_table fields = 'disliked_list[$element = %d]' % (user_id, ) conditions = 'id = %d' % (id, ) query = f'UPDATE {table} REMOVE {fields} WHERE {conditions}' nosql = FotogalNosql() nosql_result = nosql.exec_query(table, query) if len(nosql_result ) > 0 and nosql_result[0]['NumRowsUpdated'] == 1: return True else: return False
def remove(self, enc_cookie_value, user_id): """Validate and remove the auth cookie values. """ if utils.validate_id(user_id): if self.validate(enc_cookie_value, user_id): random_token = self.__decrypt(enc_cookie_value) table = self._nosql_table conditions = 'random_token = "%s" AND user_id = %d' % (random_token, user_id,) query = f'DELETE FROM {table} WHERE {conditions}' nosql = FotogalNosql() nosql_result = nosql.exec_query(table, query) if len(nosql_result) > 0: return True return False
def __get_all_user_props(self, id=None, email=None, username=None): """Return all user's properties. """ if id and utils.validate_id(id): conditions = 'id = %d LIMIT 1' % (id,) elif email and utils.validate_email(email): conditions = 'email = "%s" LIMIT 1' % (email,) elif username and utils.validate_username(username): conditions = 'username = "******" LIMIT 1' % (username,) else: return None fields = '*' table = self._nosql_table query = f'SELECT {fields} FROM {table} WHERE {conditions}' nosql = FotogalNosql() nosql_result = nosql.exec_query(table, query) profile_dict = {'id': '', 'email': '', 'full_name': '', 'username': '', 'password': '', 'follow_list': [], 'follow_sent_list': [], 'follow_you_list': [], 'follow_received_list': [], 'created_ts': '', 'is_private': '', 'is_professional_account': '', 'profile_image_url': '', 'user_data': {'birthday_ts': '', 'website': '', 'bio': '', 'gender': '', 'phone_number': ''}} if len(nosql_result) > 0: for k,v in profile_dict.items(): if k == 'user_data': for k,v in nosql_result[0]['user_data'].items(): profile_dict['user_data'][k] = v else: profile_dict[k] = nosql_result[0][k] return profile_dict else: return None
def add_dislike(self, id, user_id): """Add the "user_id" into "disliked_list" array of the "img_id". """ if utils.validate_id(id) and utils.validate_id(user_id): table = self._img_nosql_table fields = 'disliked_list[$element = %d] AS disliked_result' % ( user_id, ) conditions = 'id = %d' % (id, ) query = f'SELECT {fields} FROM {table} WHERE {conditions}' nosql = FotogalNosql() nosql_result = nosql.exec_query(table, query) if len(nosql_result ) > 0 and nosql_result[0]['disliked_result'] is None: fields = 'disliked_list %d' % (user_id, ) conditions = 'id = %d' % (id, ) query = f'UPDATE {table} ADD {fields} WHERE {conditions}' nosql = FotogalNosql() nosql_result = nosql.exec_query(table, query) if len(nosql_result ) > 0 and nosql_result[0]['NumRowsUpdated'] == 1: self.remove_like(id, user_id) return True else: return False
def validate(self, enc_cookie_value, user_id): """Return TRUE if the encrypted cookie value is valid. """ if utils.validate_id(user_id): try: random_token = self.__decrypt(enc_cookie_value) except InvalidToken as e: return False cookie_user_id = int(random_token[:random_token.index(':')]) if utils.validate_id(cookie_user_id): fields = 'random_token, created_ts, expire_ts' table = self._nosql_table conditions = 'random_token = "%s" AND user_id = %d LIMIT 1' % (random_token, user_id,) query = f'SELECT {fields} FROM {table} WHERE {conditions}' nosql = FotogalNosql() nosql_result = nosql.exec_query(table, query) if len(nosql_result) > 0: if user_id == cookie_user_id: now_ts = int(datetime.datetime.now().strftime('%s')) expire_ts = int(nosql_result[0]['expire_ts']) if now_ts >= expire_ts: self.remove(enc_cookie_value, user_id) app.logger.debug('Removing cookie (%s)' % (enc_cookie_value,)) return False else: return True else: return False else: return False return False
def get_profile_img(self, username=None, img_filename=None): """Return the profile image headers and content. """ if username and utils.validate_username(username): profile_img_url = '/profile/%s/image/%s' % ( username, img_filename, ) conditions = 'username = "******" AND profile_image_url = "%s" LIMIT 1' % ( username, profile_img_url, ) else: return None fields = 'profile_image_url' table = self._usr_nosql_table query = f'SELECT {fields} FROM {table} WHERE {conditions}' nosql = FotogalNosql() nosql_result = nosql.exec_query(table, query) if len(nosql_result) > 0: ( img_headers, img_content, ) = self.__get_img_data(img_filename) return ( img_headers, img_content, ) return ( None, None, )
def get_follow_list(self, user_id=None, index_low=None, index_high=None): """Returns a sublist of user IDs from the "follow_list". """ if utils.validate_id(user_id): if index_low and index_high: fields = '[follow_list[%d:%d]] AS follow_list' % ( index_low, index_high, ) else: fields = 'follow_list AS follow_list' table = self._nosql_table conditions = 'id = %d LIMIT 1' % (user_id, ) query = f'SELECT {fields} FROM {table} WHERE {conditions}' nosql = FotogalNosql() nosql_result = nosql.exec_query(table, query) return nosql_result[0]['follow_list']
def get_id(self, email=None, username=None): """Return the user ID. """ if email and utils.validate_email(email): conditions = 'email = "%s" LIMIT 1' % (email,) elif username and utils.validate_username(username): conditions = 'username = "******" LIMIT 1' % (username,) else: return None fields = 'id' table = self._nosql_table query = f'SELECT {fields} FROM {table} WHERE {conditions}' nosql = FotogalNosql() nosql_result = nosql.exec_query(table, query) if len(nosql_result) > 0: return nosql_result[0]['id'] else: return None
def save(self, user_id, img_filename, img_content, is_profile): """Save the image content into Object Storage and register the properties in NoSQL. """ if utils.validate_id(user_id): new_img_filename = self.__get_new_filename(img_filename) img_data_dict = self.__add_img_data(new_img_filename, img_content) if img_data_dict: img_created_ts = datetime.datetime.now().strftime('%s') img_dict = { 'image_url': '', 'image_filename': new_img_filename, 'image_original_filename': img_filename, 'image_host_fqdn': '', 'image_uri': '', 'image_type': '', 'created_ts': img_created_ts, 'user_id': user_id, 'liked_list': [], 'disliked_list': [], 'main_comment': '', 'is_profile': is_profile } for k, v in img_data_dict.items(): img_dict[k] = img_data_dict[k] nosql = FotogalNosql() new_img_id = nosql.add(self._img_nosql_table, img_dict) return new_img_id return None
def create_app(config_name): app = Flask(__name__) app.config.from_object(config[config_name]) config[config_name].init_app(app) app.jinja_env.trim_blocks = True app.jinja_env.lstrip_blocks = True # Init OCI SDK oci_config_filepath = app.root_path + '/../' + app.config.get( 'OCI_CONFIG_FILE') oci_privkey_filepath = app.root_path + '/../' + app.config.get( 'OCI_PRIVKEY_FILE') oci_config = oci.config.from_file(oci_config_filepath) oci_config['key_file'] = oci_privkey_filepath app.config['oci_config'] = oci_config # App Log oci_loggroup_name = app.config.get('LOG_GROUP_NAME') oci_customlog_name = app.config.get('LOG_NAME') log_handler = FotogalLog.create_handler(oci_config, oci_loggroup_name, oci_customlog_name) app.logger.addHandler(log_handler) # CSRF Token csrf.init_app(app) # Init and get the OCI NoSQL handle. # A handle has memory and network resources associated with it. To minimize # network activity as well as resource allocation and deallocation overheads, # it’s best to avoid repeated creation and closing of handles. So we create # and globalize the handle here for the entire app. app._nosql_handle = FotogalNosql.create_handler(oci_config, app.logger) from .auth import auth as auth_blueprint from .main import main as main_blueprint from .api import api as api_blueprint app.register_blueprint(auth_blueprint) app.register_blueprint(main_blueprint) app.register_blueprint(api_blueprint, url_prefix='/api/v1') return app
def __add_list_item(self, list_name, list_owner_id, user_follow_id): """Add the "user_follow_id" into the "list_name" from "list_owner_id". """ fotogal_user = FotogalUser() owner_list_dict = fotogal_user.get_pkey_values(id=list_owner_id) nosql = FotogalNosql() table = self._nosql_table # Check if the ID doesn't exist in follow_list array. fields = 'id' conditions = 'id = %d AND %s[] =any %d' % ( owner_list_dict['id'], list_name, user_follow_id, ) query = f'SELECT {fields} FROM {table} WHERE {conditions}' nosql_result = nosql.exec_query(table, query) if len(nosql_result) > 0: return False else: fields = '%s %d' % ( list_name, user_follow_id, ) conditions = 'id = %d AND username = "******" AND email = "%s"' % ( owner_list_dict['id'], owner_list_dict['username'], owner_list_dict['email'], ) query = f'UPDATE {table} ADD {fields} WHERE {conditions}' nosql = FotogalNosql() nosql_result = nosql.exec_query(table, query) return True