«phpClub» — архив тем ("тредов"), посвящённых изучению PHP и веб-технологий.
Аноним 2019/08/08 17:38:54  №1450056 1
>>1447890

>>- зачем нужна таблица participant, если есть conference_reference? Я не понимаю, чем таблица participant отличается от conference_reference.
> Это денормализация чтобы получить конференцию по собеседнику, в случае приватных конференций

Тут мне кажется, непонимание. Я вижу, что в таблице conference_reference есть поля-ссылки:

- "user" -> на таблицу users
- "participant" -> на таблицу users
- conference -> на таблицу conference

А еще есть таблица participant с такими полями:

- user -> на таблицу users
- conference -> на таблицу conference

Соответственно вопрос, чем таблица participant отличается от conference_reference? Они обе содержат поля user и conference, и не хранят ли они одно и то же?

В моем понимании диалог выглядит так: есть conference, есть 2 ссылающихся на него conference_reference (вид на диалог со стороны каждого собеседника). Что тут делает таблица participant? На нее нет внешних ключей, то есть никто на нее не ссылается.

Вот определение этой таблицы: https://github.com/someApprentice/Crypter/blob/master/schema.sql#L152

Что касается денормализации для поиска существующего диалога, то поля user + participant в таблице conference_reference вполне решают эту проблему, как я понимаю.

> Да, id не как не используются для этих сущностный и не нужны. Вроде есть такой шаблон проектирования, когда создаются вспомогательные таблицы, которые ссылаются на основные, как бы соединяя их, и там нету поля id. Как он называется? Чтобы быть уверенным что я делаю.

Может быть, связь многие-ко-многим? Составной первичный ключ?

>> И еще, не отдаем ли мы тут детали ошибки на сервере пользователю
> Об этом нужно выдать ошибку пользователю. А вот ниже там действительно обрабатывается любая ошибка, но это только потому что я не знаю как обработать отдельные ошибки

По идее должно быть так: если происходит неожиданная ошибка, то это баг в программе. И мы логгируем ее в лог + отдаем пользователю общее сообщение об ошибке в программе без подробностей (в режиме отладки, если такой режим есть, можно с подробностями). В идеале, мы вообще не должны их ловить, а вебсокет-сервер должен их корректно обрабатывать сам. Но если он вместо этого падает, закрывая все соединения, то тогда ради стабильности можно их ловить самим.

Логгировать можно выводом в stderr, или попробовать разобраться с модулем logging: https://docs.python.org/3/library/logging.html

У тебя в коде есть комментарий:

> builtins.TypeError: catching classes that do not inherit from BaseException is not allowed
> except (InvalidSignatureError, UserNotFoundError, WrongTokenError, Exception) as e:

Это скорее всего из-за того, что классы не импортированы или импортированы неправильно и Питон путает их с какими-то другими классами. Для надежности можно отркыть исходный код, где они определены, и проверить, что они действительно наследуются от базового класса исключений.

> Тогда пришлось бы генерировать токен так как он генерируется в функции регистрации/логина. Не будет ли это положением теста на знание о том как генерируется токен?

Здесь вопрос в том, что именно мы хотим протестировать? Как звучат требования к модулю authenticator.py?

- "аутентификатор принимает валидный JWT токен, имеющий такую структуру: ...."
- или же "аутентификатор принимает токен неизвестного типа и структуры, выданный данной командой/функцией/методом API в PHP-приложении"

В первом случае, очевидно, мы должны получить этот токен с помощью функции генерации JWT токена или же сгенерировать его вручную какой-то командой и в комментариях описать эту команду. Чтобы другой разработчик мог сгенерировать токен сам и убедиться, что все верно.

Во втором - нам нужен интеграционный тест, который вызовет метод регистрации или логина в PHP-приложении, получит токен и передаст Питоновскому коду для проверки. Либо опять же, сгенерировать токен вручную и описать процедуру его получения в комментарии. Заметим, что в этом случае тест свалится при изменении структуры токена или приватного ключа.

Еще один вариант - попробовать "мокнуть" для тестов функцию декодирования токена (jwt.decode), заменив ее на свою функцию, возвращающую заранее известный результат для данного токена, вроде такого:

def mock_jwt_decode(token):
if token == 'token_for_alice':
return {"name": "Alice", "email": "alice@example.com"}
...

То есть убрать из теста JWT. Но в этом случае мы полагаемся на знание того, что токен является JWT токеном, знаем его структуру и знаем, что тестируемый код использует jwt.decode.

Проблема с вписанным вручную токеном в том, что непонятно, откуда он взят. Как мне проверить вручную, что он корректен? Как поменять что-то в нем? Код теста должен быть читабелен, и проверяем, а тут я не могу разобраться в нем. Та же проблема, кстати, с прописанными хешами паролей пользователей вот тут: https://github.com/someApprentice/Crypter/blob/57b4ce3025053507a6b65aeac81fdd07149445fc/wamp/tests/conftest.py#L19 - непонятно, как они получены. Такой тест трудно будет отлаживать другому разработчику. Может, в тестируемом коде ошибка, а может ты просто опечатался при копировании токена - как понять?

Какой из вариантов лучше - надо выбирать, взвесив плюсы и минусы. Намекну, что вариант с комментарием самый простой в реализации.

>>Что касается исключений при авторизации, мне кажется, их правильнее ловить в обработчике авторизации, а не тут:
> Делать блок try/catch?

Да. Чем мне нравится этот вариант - тем, что мы ловим исключение только в определенном месте кода. И код обработки исключения находится рядом с остальным кодом авторизации. ExceptionListener же ловит исключения со всего кода, плюс, нелегко догадаться о его существовании и о том, что в нем есть код, относящийся к авторизации.

Вот, например, у тебя есть код в ExceptionListener:

> if ($exception instanceof UniqueConstraintViolationException) {
> $response = new Response('Bad Request', Response::HTTP_BAD_REQUEST);

Как я должен понять, к какому контроллеру относится этот код? Наверно можно попробовать поискать по коду, где используется ограничение на уникальность, но это какой-то очень странный подход. Также, этот код ловит исключения отовсюду. Ты писал его для какого-то своего контроллера, но исключения ловятся и со всех других контроллеров, что может быть неожиданно для их авторов, которые этого не хотели.