Как правильно организовать регистрацию пользователя и подтверждение через почту в RESTful приложении?
Вот моё неправильное представление о том как это организовать:
Пользователь заполняет данные, например, в android приложении, затем нажимает кнопку "Register" и данные в формате json (что-то типа такого { firstName: 'Aleksey', email: 'some_email@mail.ru', ... }) отсылаются на сервер с помощью HTTP запроса с POST методом и с URI: "/users/".
Затем на основе этих данных на сервере создаётся UnverifiedUser и сохраняется в таблицу unverified_users, в этом объекте будет храниться токен, который также будет отправлен на почту пользователя. Затем сервер возвращает ответ "202 Accepted".
На почту пользователя придёт письмо с ссылкой, в которой будет находиться токен, а вот какой URI должен быть в этой ссылке я не знаю, знаю, что точно не /users/{token}.
Когда пользователь переходит по этой ссылке, то в базе данных ищется UnverifiedUser с таким же токеном, если такой в базе данных есть, то создаём полноценный объект User и сохраняем его в БД и возвращаем "201 Created".
Так вот, как по мне, то возвращение "202 Accepted" здесь - это неправильно, если я правильно понял, то этот ответ сигнализирует о том, что сервер позже самостоятельно завершит обработку запроса.
Также я не знаю какой URI должен быть в активационной ссылке с токеном, это точно не может быть /users/{token} из-за того, что такой URI уже занят для другого действия (запрос пользователя по ID: /users/{id}) и, вообще, токен в ссылке - это параметр, а значит переход по ссылке инициирует GET запрос, а такой запрос не должен менять состояние сервера, то есть не должен создавать User.
Единственным верным решением, по моему мнению, является создание UnverifiedUser, то есть в объекте User не будет свойства типа $isRegistered, которое, как мне кажется, доставит проблем в будущем. Ну может это и не так, может я не прав и это плохое решение. Я пока не знаю, нужно продвинуться чуть дальше чтобы узнать.
Возможно вообще не стоит подстраивать регистрацию под REST? Я хз, я не очень в этом шарю, просто стараюсь учиться и писать приложение одновременно.
Также подскажите, пожалуйста, кто должен отправлять письмо, клиент или сервер? Мне кажется, что сервер.
Спасибо. Я во время написания понял, что я дичь придумал. Но назрел другой вопрос. Если сразу создать User со свойством email_verified и поместить его в основную таблицу с пользователями, то получается если в UserRepository есть множество методов типа getById(), getByFirstName(), getByAge() и так далее, значит в каждом из них нужно добавить к запросу условие: "where email_verified = 'true'"? Я ведь не хочу чтобы незареганные пользователи отображались где-либо.
Алексей Потапенко, где в названии метода getByFirstName() указание на то, что он ищет по имени только тех, кто мыло подтвердил? Правильно, нигде. Если ты уж так сильно этого хочешь (как по мне, так это дичь №3), то это должен быть какой-то глобальный скоуп/критерий, накладываемый на репу. Гугли скоупы и критерии.
Если андроид, то забудь про подтверждение, либо смс либо ничего. И эти подтверждения они ничего не дают, ценность email'a с точки зрения лидогенерации околонулевая, а 90% защиту дает от спама дает смс(но по факту много сервисов навроде https://sms-activate.ru/ru/), плюс номера можно могут обрабатывать продажники.