def handle_oauth(network: Type[SocialNetwork], access_token: str): if not access_token: raise RouteError("No token received.") network_user_id = network.token_metadata(access_token) oauth = create_or_get_oauth(network.network_name, network_user_id, access_token) user = oauth.user if not user: profile = network.profile(network_user_id, access_token) logger.debug(f"profile of user is {profile}") if not profile.get("email"): raise RouteError("Can not get email from user.") try: image_url = profile["picture"]["data"].get("url") logger.info(f"Uploading {image_url} to Cloudinary...") image = upload(image_url)["public_id"] except Exception: image = "" # Create a new local user account for this user user = User(email=profile.get("email"), name=profile.get("name"), image=image).save() oauth.user = user oauth.save() logger.debug(f"creating new user {user}") exchange_token = user.encode_exchange_token().decode() logger.debug("Logging out of session") logout_user() return {"token": exchange_token}
def test_refresh_token_payload(auth, user: User): """check that refresh token after login has a scope and a user_id""" resp = auth.login() assert resp.json["refresh_token"] payload = User.decode_token(resp.json["refresh_token"]) assert payload["scope"] assert User.from_payload(payload) == user
def test_exchange_token(requester, user: User): resp = requester.post( "/login/exchange_token", json={"exchange_token": user.encode_exchange_token().decode()}, ) assert "user" in resp.json assert "auth_token" in resp.json assert user == User.from_login_token(resp.json["auth_token"])
def refresh_token(): args = flask.request.get_json() if not args.get("refresh_token"): raise RouteError("INAVLID_REFRESH_TOKEN") payload = User.decode_token(args["refresh_token"]) if payload["scope"] != TokenScope.REFRESH.value: raise TokenError("INAVLID_REFRESH_TOKEN") user = User.from_payload(payload) return {"auth_token": user.encode_auth_token().decode()}
def exchange_token(): args = flask.request.get_json() payload = User.decode_token(args["exchange_token"]) if payload["scope"] != TokenScope.EXCHANGE.value: raise TokenError("INVALID_EXCHANGE_TOKEN") user = User.from_payload(payload) logger.debug(f"{user} exchanged auth token") BlacklistToken.create( token=args["exchange_token"]) # blacklist exchange token tokens = user.generate_tokens() return dict(**tokens, **{"user": user.to_dict()})
def token_tuple(request): auth_header = request.headers.get("Authorization") try: auth_token = auth_header.split(" ")[1] except IndexError: raise TokenError("INVALID_TOKEN") return auth_token, User.from_login_token(auth_token)
def test_login(user, auth): resp = auth.login() assert "auth_token" in resp.json assert "refresh_token" in resp.json assert user.to_dict()["id"] == resp.json["user"]["id"] payload = User.decode_token(resp.json["auth_token"]) assert "email" in payload
def test_handle_extra_filters(teacher): new_user = User.create(email="[email protected]", password="******", name="absolutely", area="nope") student = Student.create(teacher=teacher, creator=teacher.user, user=new_user) def custom_filter(model, key, value): return getattr(model, key) == value extra_filters = {User: {"area": custom_filter}} new_student = Student._handle_extra_filters( query=Student.query, args={ "area": "npe" }, extra_filters=extra_filters).first() assert not new_student new_student = Student._handle_extra_filters( query=Student.query, args={ "area": "nope" }, extra_filters=extra_filters).first() assert new_student == student
def search(): try: query = User.query.filter( and_(User.teacher == None, User.student == None)) return User.filter_and_sort(flask.request.args, query=query, with_pagination=True) except ValueError: raise RouteError("Wrong parameters passed.")
def test_invalid_login_to_ezcount(auth, requester): new_user = User.create( email="[email protected]", password="******", name="absolutely", area="nope" ) new_teacher = Teacher.create( user=new_user, is_approved=True, price=100, lesson_duration=40, crn=999999999 ) auth.login(email=new_user.email, password="******") resp = requester.get("/teacher/ezcount?redirect=backoffice/expenses") assert "does not have an invoice account" in resp.json["message"]
def create_user_from_data(data, required=None): (name, area, email, password, phone) = validate_inputs(data, required=required) image = flask.request.files.get("image") # Query to see if the user already exists user = User.query.filter_by(email=email).first() if user: raise RouteError("Email is already registered.") # Register the user user = User(email=email, password=password, name=name, area=area, phone=phone) if image: try: user.image = upload(image)["public_id"] except Exception: raise RouteError("Image could not be uploaded.") user.save() return user
def test_delete_student(auth, requester, student, teacher): auth.login(email=teacher.user.email) resp = requester.delete(f"/student/{student.id}") assert "Can't delete" in resp.json["message"] student_user = User.create(email="*****@*****.**", password="******", name="student", area="test") new_student = Student.create(user=student_user, teacher=teacher, creator=teacher.user, is_approved=True) resp = requester.delete(f"/student/{new_student.id}") assert "deleted" in resp.json["message"]
def test_students(auth, teacher, requester): new_user = User.create( email="[email protected]", password="******", name="absolutely", area="nope" ) new_student = Student.create(teacher=teacher, creator=teacher.user, user=new_user) auth.login(email=teacher.user.email) resp = requester.get("/teacher/students?order_by=balance desc") assert resp.json["data"][1]["student_id"] == new_student.id resp = requester.get("/teacher/students?name=solut") assert resp.json["data"][0]["student_id"] == new_student.id resp = requester.get("/teacher/students?name=le:no way") assert not resp.json["data"] resp = requester.get("/teacher/students?limit=1") assert len(resp.json["data"]) == 1
def test_ezcount_create_user(auth, requester, teacher): auth.login(email=teacher.user.email) resp = requester.get("/teacher/ezcount_user") assert "already has" in resp.json["message"] auth.logout() new_user = User.create( email="[email protected]", password="******", name="absolutely", area="nope" ) new_teacher = Teacher.create( user=new_user, is_approved=True, price=100, lesson_duration=40, crn=999999999 ) auth.login(email=new_teacher.user.email, password="******") resp = requester.get("/teacher/ezcount_user") assert "successfully" in resp.json["message"]
def oauth_facebook(): """setup Facebook API, redirect to facebook login & permissions when redirected back, check auth code and setup a server session with credentials """ # If authenticated from JWT, login using a session # and blacklist token auth_token = flask.request.values.get("token") if auth_token: user = User.from_login_token(auth_token) BlacklistToken.create(token=auth_token) logger.debug("logged wih token, creating session...") login_user(user, remember=True) # Store the state so the callback can verify the auth server response. state = "".join(random.choices(string.ascii_uppercase + string.digits, k=6)) flask.session["state"] = state return flask.redirect(Facebook.auth_url(state))
def test_filter_and_sort(user, teacher, student, meetup, dropoff): """test that limit is maxed to 100, base query, custom date, non allowed filters""" date = datetime.utcnow() + timedelta(days=100) for x in range(101): user = User.create(email=f"{x}@test.com", password="******", name="teacher", area="test") teacher = Teacher.create(user=user, price=100, lesson_duration=40, is_approved=True, crn=9) Appointment.create( teacher=teacher, student=student, creator=student.user, duration=40, date=date, meetup_place=meetup, dropoff_place=dropoff, ) args = MultiDict([("teacher_id", teacher.id)]) # not allowed query = None lessons_from_db = Appointment.filter_and_sort(args, query=query) assert len(lessons_from_db) == 102 args = MultiDict([("date", date.strftime(WORKDAY_DATE_FORMAT))]) lessons_from_db = Appointment.filter_and_sort( args, query=query, custom_date=lambda x: datetime.strptime(x, WORKDAY_DATE_FORMAT), ) assert not lessons_from_db query = Appointment.query.filter_by(teacher_id=3) args = MultiDict() lessons_from_db = Appointment.filter_and_sort(args, query=query) assert len(lessons_from_db) == 1 query = None args = MultiDict([("limit", 100_000_000_000_000)]) lessons_from_db = Appointment.filter_and_sort(args, query=query, with_pagination=True) assert len(lessons_from_db.items) == 100
def make_student(): data = flask.request.args user = current_user teacher = Teacher.get_by_id(data.get("teacher_id")) if current_user.teacher: user = User.get_by_id(data.get("user_id")) teacher = current_user.teacher if not user: raise RouteError("User was not found.", 401) if user.teacher or user.student: raise RouteError("User is already a student or a teacher.") if not teacher: raise RouteError("Teacher was not found.") try: price = int(data.get("price", "")) except ValueError: price = None student = Student.create(user=user, teacher=teacher, creator=current_user, price=price) # send notification user_to_send_to = student.user body_text = gettext("%(teacher)s added you as a student!", teacher=teacher.user.name) if student.creator == user_to_send_to: user_to_send_to = teacher.user body_text = gettext("%(student)s added you as a teacher!", student=student.user.name) if user_to_send_to.firebase_token: logger.debug(f"sending fcm to {user_to_send_to}") try: FCM.notify( token=user_to_send_to.firebase_token, title=gettext("Join Request"), body=body_text, ) except: pass return {"data": student.to_dict()}, 201
def test_invalid_add_receipt(auth, requester, student, teacher): auth.login(email=teacher.user.email) resp = requester.get("/teacher/payments/1000/receipt") assert resp.status_code == 404 auth.logout() new_user = User.create( email="[email protected]", password="******", name="absolutely", area="nope" ) new_teacher = Teacher.create( user=new_user, is_approved=True, price=100, lesson_duration=40, crn=999999999 ) auth.login(email=new_user.email, password="******") payment = Payment.create( teacher=new_teacher, amount=new_teacher.price, student=student, payment_type=PaymentType.cash, details="test", crn=1101, ) resp = requester.get(f"/teacher/payments/{payment.id}/receipt") assert "does not have an invoice account" in resp.json["message"]
def test_teachers(auth, teacher, requester): new_user = User.create( email="[email protected]", password="******", name="absolutely", area="nope" ) new_teacher = Teacher.create( user=new_user, is_approved=True, price=100, lesson_duration=40, crn=1 ) auth.login() resp = requester.get("/teacher/") first_length = len(resp.json["data"]) assert resp.json["data"][1]["teacher_id"] == new_teacher.id resp = requester.get("/teacher/?order_by=created_at desc") assert resp.json["data"][0]["teacher_id"] == new_teacher.id resp = requester.get("/teacher/?name=solut") assert resp.json["data"][0]["teacher_id"] == new_teacher.id resp = requester.get("/teacher/?name=le:no way") assert not resp.json["data"] resp = requester.get("/teacher/?limit=1") assert len(resp.json["data"]) == 1 new_teacher.is_approved = False resp = requester.get("/teacher/") assert len(resp.json["data"]) == first_length - 1
def setup_db(app): User.create(email="*****@*****.**", password="******", name="test", area="test", phone="044444444") User.create( email="*****@*****.**", password="******", name="admin", area="test", is_admin=True, phone="055555555", ) teacher_user = User.create(email="*****@*****.**", password="******", name="teacher", area="test") teacher = Teacher.create( user=teacher_user, price=100, lesson_duration=40, is_approved=True, crn=999999999, invoice_api_key=DEMO_API_KEY, ) Car.create(teacher=teacher, number=1111111111) student_user = User.create(email="*****@*****.**", password="******", name="student", area="test") student = Student.create(user=student_user, teacher=teacher, creator=teacher.user, is_approved=True) meetup = Place.create( description="test", used_as=PlaceType.meetup.value, student=student, google_id="ID1", ) dropoff = Place.create( description="test", used_as=PlaceType.dropoff.value, student=student, google_id="ID2", ) WorkDay.create( teacher=teacher, day=1, from_hour=0, to_hour=23, to_minutes=59, on_date=(datetime.utcnow() + timedelta(days=2)).date(), ) # 2 days from now Topic.create(title="topic test", min_lesson_number=1, max_lesson_number=5) Appointment.create( teacher=teacher, student=student, # schedule to 5 days from now to it won't bother with no test creator=teacher.user, duration=40, date=(datetime.utcnow() + timedelta(days=5)), meetup_place=meetup, dropoff_place=dropoff, )
def test_decode_auth_token(user): auth_token = user.encode_auth_token() assert isinstance(auth_token, bytes) assert User.from_login_token(auth_token.decode("utf-8")) == user