def logout(session_token: str): """ logout user. Even if session is not found, no errors will be raised. :param session_token: required """ with new_session() as session: session.query(LoginSession).filter(LoginSession.session_token == session_token).delete()
def login(username_or_email: str, password_sha256: bytes, expire_day_len: int = 30) -> str: """ make an existing user login. Return a new session id which has an expiration date. Should raise errors when user not exists or username and password doesn't match :param username_or_email: required :param password_sha256: required :param expire_day_len: optional, days before returned login token expires :return: session token for user which user should carry around for logged-in operations """ with new_session() as session: result = session.query(User) # figure out if input is username or email col_to_match = User.email if ('@' in username_or_email and '.' in username_or_email) else User.username result = result.filter(col_to_match == username_or_email, User.password == password_sha256) user = result.one_or_none() if user: # generate session token raw = ''.join(choices(ascii_letters, k=LoginSession.session_token.property.columns[0].type.length)) exp_date = datetime.now() + timedelta(days=expire_day_len) session.add(LoginSession(session_token=raw, username=user.username, expiration_time=exp_date)) session.commit() return raw else: # when query returns 0 users, see if user password is incorrect or user doesn't exists for _ in session.query(User).filter(col_to_match == username_or_email): raise UserPasswordNoMatchError() raise EmailDoNotExistsError if col_to_match is User.email else UsernameDoNotExistsError
def get_session_username(session_token: str) -> str: """ :param session_token: required :return: username for that session provided """ with new_session() as session: login_session = get_login_session(session, session_token) return login_session.username
def get_latest_news() -> OilNews: """ fetch latest news :return: OilNews object """ with new_session() as session: return __wrap_oil_news( session.query(OilNews).order_by( OilNews.publish_date.desc()).limit(1).one_or_none())
def get_oil_indices() -> List[OilIndexDenormalized]: """ get all de-normalized oil indices :return: list of oil indices objects """ with new_session() as session: result = session.query(OilIndex, OilCategory).filter(OilIndex.category_id == OilCategory.category_id).order_by( OilIndex.index_id) return [OilIndexDenormalized(iid=i.index_id, iname=i.index_name, cid=c.category_id, cname=c.category_name) for i, c in result]
def get_one_oil_news(news_id: int) -> OilNews: """ fetch a single oil news :param news_id: required, id for news :return: OilNews object """ with new_session() as session: return __wrap_oil_news( session.query(OilNews).filter( OilNews.news_id == news_id).one_or_none())
def register(username: str, password_sha256: bytes, email: str): """ new account registration. Should raise different errors if username/email already exists. :param username: required :param password_sha256: required, SHA3-256 of the password :param email: required """ with new_session() as session: for _ in session.query(User).filter(User.username == username): raise UserAlreadyExistsError() for _ in session.query(User).filter(User.email == email): raise EmailAlreadyExistsError() user = User(username=username, email=email, password=password_sha256) session.add(user) session.commit()
def pd_get_oil_prices(oil_index: int, start_time: datetime = None, end_time: datetime = None): """ get oil price within certain range (not required) and return as a pandas dataframe :param oil_index: id of certain index name for oil, required :param start_time: optional :param end_time: optional :return: pandas dataframe """ with new_session() as session: result = session.query(OilPrice).filter(OilPrice.index_id == oil_index) if start_time: result = result.filter(OilPrice.price_time > start_time) if end_time: result = result.filter(OilPrice.price_time < end_time) result = result.order_by(OilPrice.price_time) df = pd.read_sql(result.statement, session.bind) return df
def change_password(username_or_email: str, current_pass_sha256: bytes, new_pass_sha256: bytes): """ Change password of of a user. Should raise error if password doesn't match or user/email doesn't exists :param username_or_email: required :param current_pass_sha256: required :param new_pass_sha256: required """ with new_session() as session: result=session.query(User) #figure out username or email col_to_match = User.email if ('@' in username_or_email and '.' in username_or_email) else User.username result = result.filter(col_to_match == username_or_email, User.password == current_pass_sha256) user = result.one_or_none() if not user: for _ in session.query(User).filter(col_to_match == username_or_email): raise UserPasswordNoMatchError() raise EmailDoNotExistsError if col_to_match is User.email else UsernameDoNotExistsError else: result.update({User.password:new_pass_sha256})
def get_oil_prices(oil_index: int, start_time: datetime = None, end_time: datetime = None) -> List[OilPrice]: """ get oil price within certain range (not required) for certain type :param oil_index: id of certain index name for oil, required :param start_time: optional :param end_time: optional :return: list of oil price objects """ with new_session() as session: result = session.query(OilPrice).filter(OilPrice.index_id == oil_index) if start_time: result = result.filter(OilPrice.price_time > start_time) if end_time: result = result.filter(OilPrice.price_time < end_time) result = result.order_by(OilPrice.price_time).all() return [ OilPrice(price_id=price.price_id, index_id=price.index_id, price=price.price, price_time=price.price_time) for price in result]
def get_oil_news_list(start_time: datetime = None, end_time: datetime = None, news_num: int = -1) -> list: """ get oil news within certain range of time. (not required) :param start_time: optional :param end_time: optional :param news_num: required, number of news to grab each time, anything < 0 means grab all :return: list of oil news objects """ with new_session() as session: result = session.query(OilNews).order_by(OilNews.publish_date.desc()) if start_time: result = result.filter(OilNews.publish_date > start_time) if end_time: result = result.filter(OilNews.publish_date < end_time) if news_num > 0: result = result.limit(news_num) result = result.all() return [__wrap_oil_news(news) for news in result]