def create_comment(self, comment: Comment) -> Result[Comment, str]: if self.get_comment(comment.comment_id): return Err(f"Comment {comment} already exists") elif not self.get_meeting(comment.meeting_id): return Err(f"Meeting {comment.meeting_id} does not exist") else: c = self.connection.cursor() if isinstance(comment.author, Instructor): term = ( str(comment.comment_id), str(comment.meeting_id), comment.author.user_name, None, comment.time_stamp, comment.content_text, ) else: term = ( str(comment.comment_id), str(comment.meeting_id), None, comment.author.student_number, comment.time_stamp, comment.content_text, ) c.execute( "INSERT INTO comments(comment_id, meeting_id, author_if_instructor," " author_if_student, time_stamp, content_text) " "VALUES (%s, %s, %s, %s, %s, %s)", term, ) self.connection.commit() return Ok(comment)
def test_create_note(schema, success): note = next(fake_note()) error = Err(fake.pystr()) context = MagicMock() context.api.meeting_api.create_note.return_value = Ok( note) if success else error query = """ mutation createNote($meetingId: UUID!, $contentText: String!) { createNote(meetingId: $meetingId, contentText: $contentText) { noteId meetingId timeStamp contentText } } """ variables = { "meetingId": str(note.meeting_id), "contentText": note.content_text } result = schema.execute(query, context=context, variables=variables) if success: assert not result.errors for attr, val in result.data["createNote"].items(): expected = getattr(note, to_snake_case(attr)) if isinstance(expected, UUID): expected = str(expected) assert expected == val else: assert error.unwrap_err() in str(result.errors) context.api.meeting_api.create_note.assert_called_once_with( note.meeting_id, context.user, note.content_text)
def test_delete_note(schema, success): context = MagicMock() note_id = uuid4() error = Err(fake.pystr()) context.user = fake_instructor() context.api.meeting_api.delete_note.return_value = Ok( note_id) if success else error query = """ mutation deleteNote($noteId: UUID!) { deleteNote(noteId: $noteId) { noteId } } """ result = schema.execute(query, context=context, variables={"noteId": str(note_id)}) if success: assert not result.errors assert result.data["deleteNote"] == {"noteId": str(note_id)} else: assert error.unwrap_err() in str(result.errors) context.api.meeting_api.delete_note.assert_called_once_with( note_id, context.user)
def _check_meeting_user(self, meeting_id: UUID, user: User, error_msg: str) -> Result[None, str]: meeting_result = self.meeting_persistence.get_meeting(meeting_id) if not meeting_result: return Err(f"Meeting with ID: '{meeting_id}' does not exist") meeting = meeting_result.unwrap() if user not in (meeting.instructor, meeting.student): return Err(error_msg) return Ok(None)
def verify_student_by_token(self, token: str) -> Result[Student, str]: payload_result = self.jwt_authenticator.verify_token(token) if payload_result.is_err: return payload_result payload = payload_result.unwrap() student_number = payload.get("id") if not student_number: return Err("Invalid token") return self.get_student(student_number).map_or( Ok, (Err("Could not get student")))
def verify_instructor_by_token(self, token: str) -> Result[Instructor, str]: payload_result = self.jwt_authenticator.verify_token(token) if payload_result.is_err: return payload_result payload = payload_result.unwrap() user_name = payload.get("id") if not user_name: return Err("Invalid token") return self.get_instructor(user_name).map_or( Ok, (Err("Could not get instructor")))
def get_profile(user_id) -> Result[User, HttpError]: parsed_id = validate_int(user_id) if not parsed_id: return Err(HttpError(400, f'{user_id} is not a valid user ID')) user_id = parsed_id.value try: found_user = User.objects.get(id=user_id) except (User.DoesNotExist, OverflowError): return Err(HttpError(404, f'User with ID {user_id} does not exist')) return Ok(found_user)
def delete_request(request_id, user): parsed_id = validate_int(request_id) if not parsed_id: return Err(HttpError(400, f'{parsed_id} is not a valid request ID')) try: request_to_del = Request.objects.get(id=parsed_id.unwrap()) except (Request.DoesNotExist, OverflowError): return Err(HttpError(404, f'Request with ID {request_id} does not exist')) if request_to_del.customer != user: return Err(HttpError(403, 'Cannot delete someone else\'s request')) Request.objects.delete_request(request_to_del) return Ok({})
def create_response(valid_data: Dict, user: User): request_id = valid_data['request_id'] try: request = Request.objects.get(id=request_id) except (Request.DoesNotExist, OverflowError): return Err(HttpError(404, f'Request with ID {request_id} does not exist')) if user == request.customer: return Err(HttpError(400, 'You cannot respond to your own request')) if request.response_set.filter(worker=user).exists(): return Err(HttpError(400, f'You already responded to request with ID {request_id}')) response = Response(request=request, worker=user, comment=valid_data['comment']) response.save() return Ok(request)
def test_create_comment(schema, author, success): context = MagicMock() comment = next(fake_comment()) error = Err(fake.pystr()) query = """ mutation createComment($meetingId: UUID!, $contentText: String!) { createComment(meetingId: $meetingId, contentText: $contentText) { commentId meetingId author { ... on Instructor { userName } ... on Student { studentNumber } } timeStamp contentText } } """ context.api.meeting_api.create_comment.return_value = (Ok(comment) if success else error) variables = { "meetingId": str(comment.meeting_id), "contentText": comment.content_text, } result = schema.execute(query, context=context, variables=variables) if success: assert not result.errors for key, val in result.data["createComment"].items(): if key == "author": if isinstance(comment.author, Instructor): assert val["userName"] == comment.author.user_name else: assert val[ "studentNumber"] == comment.author.student_number else: expected = getattr(comment, to_snake_case(key)) if isinstance(expected, UUID): expected = str(expected) assert expected == val else: assert result.errors assert error.unwrap_err() in str(result.errors) context.api.meeting_api.create_comment.assert_called_once_with( comment.meeting_id, context.user, comment.content_text)
def create_request(valid_data: Dict, user: User): try: request = Request.objects.create_request(user, **valid_data) except ValidationError as e: return Err(HttpError(400, '\n'.join(e.messages))) else: return Ok(request)
def test_create_meeting(meeting_api, success): meeting = next(fake_meeting()) error = Err(fake.pystr()) def assert_called_correctly(_meeting): assert meeting.meeting_id != _meeting.meeting_id for attr in ( "office_hour_id", "index", "instructor", "student", "notes", "comments", "start_time", ): assert getattr(meeting, attr) == getattr(_meeting, attr) return Ok(meeting) if success else error meeting_api.meeting_persistence.create_meeting.side_effect = assert_called_correctly result = meeting_api.create_meeting( meeting.instructor, meeting.student, meeting.office_hour_id, meeting.index, meeting.start_time, ) if success: assert result.unwrap() == meeting else: assert result == error meeting_api.meeting_persistence.create_meeting.assert_called_once()
def find_worker(request_id, user: User): parsed_id = validate_int(request_id) if not parsed_id: return Err(HttpError(400, f'{request_id} is not a valid request ID')) request_id = parsed_id.value try: request = Request.objects.get(id=request_id) except (OverflowError, Request.DoesNotExist): return Err(HttpError(404, f'Request with {request_id} does not exist')) if request.customer != user: return Err(HttpError(403, 'You cannot find a worker for another customer\'s request')) worker = Request.objects.find_worker(request) if worker: return Ok(user_converter.to_dict(worker.value)) return Ok(None)
def delete_meeting(self, meeting_id: uuid.UUID) -> Result[uuid.UUID, str]: if not self.get_meeting(meeting_id): return Err(f"Meeting {meeting_id} does not exist") c = self.connection.cursor() c.execute("DELETE FROM meetings WHERE meeting_id=%s", (str(meeting_id),)) self.connection.commit() return Ok(meeting_id)
def delete_course(self, course_code: str) -> Result[str, str]: if not self.get_course(course_code): return Err(f"Course {course_code} does not exist") c = self.connection.cursor() c.execute("DELETE FROM courses WHERE course_code=%s", (course_code,)) self.connection.commit() return Ok(course_code)
def parse_auth_token(request: Request) -> Result[str, str]: """ Parse a Bearer token from a request header Args: request: The HTTP request Returns: The parsed token """ auth_header = request.headers.get("Authorization") if not auth_header: return Err("No 'Authorization' header") token_list = auth_header.split(" ") if len(token_list) != 2 or token_list[0] != "Bearer": return Err("Wrong Authorization header format (Bearer TOKEN)") return Ok(token_list[1])
def test(host="1.1.1.1", port=53, timeout=3) -> Result[None, str]: try: socket.setdefaulttimeout(timeout) socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((host, port)) return Ok(None) except OSError err: return Err(f'No internet connection availiable. {err.strerror} ({err.errno})')
def test_fail(self, mock_course_presistence): course_api = CourseApi(mock_course_presistence) course = fake_course() err = Err(fake.pystr()) mock_course_presistence.create_course = MagicMock(return_value=err) assert course_api.create_course(course.course_code) == err mock_course_presistence.create_course.assert_called_once_with(course)
def delete_note(self, note_id: uuid.UUID) -> Result[uuid.UUID, str]: if not self.get_note(note_id): return Err(f"Note {note_id} does not exist") c = self.connection.cursor() c.execute("DELETE FROM notes WHERE note_id=%s", (str(note_id),)) self.connection.commit() return Ok(note_id)
def validate_json_string(string: AnyStr, schema: Dict, *args, **kwargs) -> Result[Json, str]: """Parse a JSON string and validate it""" parsed_json = load_json(string) if not parsed_json: return Err(f'{string} is not a valid json string') return validate_json(parsed_json.value, schema, *args, **kwargs)
def delete_comment(self, comment_id: uuid.UUID) -> Result[uuid.UUID, str]: if not self.get_comment(comment_id): return Err(f"Comment {comment_id} does not exist") c = self.connection.cursor() c.execute("DELETE FROM comments WHERE comment_id=%s", (str(comment_id),)) self.connection.commit() return Ok(comment_id)
def validate_json(json_data: Json, schema: Dict, *args, **kwargs) -> Result[Json, str]: """Validate a JSON value""" try: validate(json_data, schema, *args, **kwargs) except ValidationError as e: return Err(e.message) return Ok(json_data)
def create_course(self, course: Course) -> Result[Course, str]: if self.get_course(course.course_code): return Err(f"Course {course} already exists") c = self.connection.cursor() term = (course.course_code,) c.execute("INSERT INTO courses VALUES (%s)", term) self.connection.commit() return Ok(course)
def delete_student(self, student: Student) -> Result[Student, str]: if not self.get_student(student.student_number): return Err(f"Student {student} does not exist") c = self.connection.cursor() term = (student.student_number, ) c.execute("DELETE FROM students WHERE student_number=%s", term) self.connection.commit() return Ok(student)
def delete_note(self, note_id: UUID, author: Instructor) -> Result[UUID, str]: """ Deletes note of <note_id>. Returns: note_id on success """ note_result = self.meeting_persistence.get_note(note_id) if not note_result: return Err(f"Note with ID: '{note_id}' does not exist") meeting_id = note_result.unwrap().meeting_id meeting_result = self.meeting_persistence.get_meeting(meeting_id) if not meeting_result: return Err(f"Meeting with ID: '{meeting_id}' does not exist") if author != meeting_result.unwrap().instructor: return Err("Cannot delete a note that does not belong to you") return self.meeting_persistence.delete_note(note_id)
def test_verify_password_fail_at_persistence(password_authenticator): user_id, password = fake.pystr(), fake.pystr() error = Err(fake.pystr()) password_authenticator.authentication_persistence.get_password_hash = MagicMock( return_value=error) assert password_authenticator.verify_password(user_id, password) == error password_authenticator.crypto_context.verify_and_update.assert_not_called() password_authenticator.authentication_persistence.update_password_hash.assert_not_called( )
def delete_instructor(self, instructor: Instructor) -> Result[Instructor, str]: if not self.get_instructor(instructor.user_name): return Err(f"Instructor {instructor} does not exist") c = self.connection.cursor() term = (instructor.user_name, ) c.execute("DELETE FROM instructors WHERE user_name=%s", term) self.connection.commit() return Ok(instructor)
def test_delete_meeting_fail_user_check(meeting_api, user): meeting = next(fake_meeting()) error = Err(fake.pystr()) meeting_api._check_meeting_user = MagicMock(return_value=error) assert meeting_api.delete_meeting(meeting.meeting_id, user) == error meeting_api.meeting_persistence.delete_meeting.assert_not_called() meeting_api._check_meeting_user.assert_called_once_with( meeting.meeting_id, user, "Cannot delete meeting that you are not a part of")
def delete_officehour(self, office_hour_id: UUID, mp: MeetingPersistence) -> Result[UUID, str]: if not self.get_officehour(office_hour_id, mp): return Err(f"OfficeHour {office_hour_id} does not exist") c = self.connection.cursor() c.execute("DELETE FROM officehours WHERE office_hour_id=%s", (office_hour_id, )) self.connection.commit() return Ok(office_hour_id)
def get_password_hash(self, user_identity: str) -> Result[str, str]: c = self.connection.cursor() term = (user_identity, ) c.execute("SELECT * FROM instructors WHERE user_name=%s", term) res = c.fetchone() if res: pass_hash = res[2] return Ok(pass_hash) else: return Err(f"Instructor {user_identity} does not exist")