Rahul Khan
Posted on September 9, 2023
Hello. Today we will be creating a custom module to create users using REST API in Drupal 10. We will be doing basic operations namely, user-registration, user-login, read and edit user details and user-logout.
Step 1: Addition three new text fields for the user (First Name, Last Name, City).
Step 2: Download and install HAL & REST UI module.
Step 3: Create a custom module named 'restapi' and add the info.yml file and create a folder structure in the 'restapi' module folder as 'src\Plugin\rest\resource'
Step 4: Create the php files for different operations.
UserRegistrationRest.php - For user registration
<?php
namespace Drupal\restapi\Plugin\rest\resource;
use Drupal\rest\Plugin\ResourceBase;
use Psr\Log\LoggerInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Drupal\user\Entity\User;
/**
* Provides a resource to get view modes by entity and bundle.
* @RestResource(
* id = "user_registration_rest",
* label = @Translation("User Registration API"),
* uri_paths = {
* "create" = "/api/user-registration",
* }
* )
*/
class UserRegistrationRest extends ResourceBase {
/**
* A current user instance which is logged in the session.
* @var \Drupal\Core\Session\AccountProxyInterface
*/
protected $loggedUser;
/**
* Constructs a Drupal\rest\Plugin\ResourceBase object.
*
* @param array $config
* A configuration array which contains the information about the plugin instance.
* @param string $module_id
* The module_id for the plugin instance.
* @param mixed $module_definition
* The plugin implementation definition.
* @param array $serializer_formats
* The available serialization formats.
* @param \Psr\Log\LoggerInterface $logger
* A logger instance.
* @param \Drupal\Core\Session\AccountProxyInterface $current_user
* A currently logged user instance.
*/
public function __construct(array $config, $module_id, $module_definition, array $serializer_formats, LoggerInterface $logger, AccountProxyInterface $current_user) {
parent::__construct($config, $module_id, $module_definition, $serializer_formats, $logger);
$this->loggedUser = $current_user;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $config, $module_id, $module_definition) {
return new static(
$config,
$module_id,
$module_definition,
$container->getParameter('serializer.formats'),
$container->get('logger.factory')->get('user_registration_api'),
$container->get('current_user')
);
}
/*
* User Registration API
*/
public function post(Request $data) {
global $base_url;
try {
$content = $data->getContent();
$params = json_decode($content, TRUE);
$message_string = "";
$message_string .= empty($params['email']) ? "Email ID. " : "";
$message_string .= empty($params['password']) ? "Password. " : "";
$message_string .= empty($params['first_name']) ? "First Name. " : "";
$message_string .= empty($params['last_name']) ? "Last Name. " : "";
$message_string .= empty($params['city']) ? "City. " : "";
if($message_string) {
$final_api_reponse = array(
"status" => "Error",
"message" => "Mandatory Fields Missing",
"result" => "Required fields: ".$message_string
);
}
else {
$user_name = strtolower($params['first_name'].'.'.$params['last_name']);
$user_full_name = ucfirst($params['first_name']).' '.ucfirst($params['last_name']);
$user_email = $params['email'];
// Checking for duplicate user entries
$email_check = \Drupal::entityQuery('user')->accessCheck(TRUE)->condition('mail', $user_email)->execute();
$username_check = \Drupal::entityQuery('user')->accessCheck(TRUE)->condition('name', $user_name)->execute();
if (!empty($email_check) || !empty($username_check)) {
$final_api_reponse = array(
"status" => "Error",
"message" => "Registration Failed",
"result" => "User details already exists. Please try with different Name or Email-ID."
);
}
else {
// Create new user
$new_user = User::create([
'name' => $user_name,
'pass' => $params['password'],
'mail' => $user_email,
'roles' => array('general', 'authenticated'),
'field_first_name' => ucfirst($params['first_name']),
'field_last_name' => ucfirst($params['last_name']),
'field_city' => $params['city'],
'status' => 1,
])->save();
$final_api_reponse = array(
"status" => "Success",
"message" => "Registration Successful",
"result" => "Thank You. Account for ".$user_full_name." has been created."
);
}
}
return new JsonResponse($final_api_reponse);
}
catch(Exception $exception) {
$this->exception_error_msg($exception->getMessage());
}
}
}
UserLoginRest.php - For user login
<?php
namespace Drupal\restapi\Plugin\rest\resource;
use Drupal\rest\Plugin\ResourceBase;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\Core\Access\CsrfTokenGenerator;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Routing\RouteProviderInterface;
use Drupal\user\UserAuthInterface;
use Drupal\user\UserFloodControlInterface;
use Drupal\user\UserInterface;
use Drupal\user\UserStorageInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Serializer;
use Drupal\user\Entity\User;
/**
* Provides a resource to get view modes by entity and bundle.
* @RestResource(
* id = "user_login_rest",
* label = @Translation("User Login API"),
* uri_paths = {
* "create" = "/api/user-login",
* }
* )
*/
class UserLoginRest extends ResourceBase {
/**
* String sent in responses, to describe the user as being logged in.
* @var string
*/
const LOGGED_IN = 1;
/**
* String sent in responses, to describe the user as being logged out.
* @var string
*/
const LOGGED_OUT = 0;
/**
* The user flood control service.
* @var \Drupal\user\UserFloodControl
*/
protected $userFloodControl;
/**
* The user storage.
* @var \Drupal\user\UserStorageInterface
*/
protected $userStorage;
/**
* The CSRF token generator.
* @var \Drupal\Core\Access\CsrfTokenGenerator
*/
protected $csrfToken;
/**
* The user authentication.
* @var \Drupal\user\UserAuthInterface
*/
protected $userAuth;
/**
* The route provider.
* @var \Drupal\Core\Routing\RouteProviderInterface
*/
protected $routeProvider;
/**
* The serializer.
* @var \Symfony\Component\Serializer\Serializer
*/
protected $serializer;
/**
* The available serialization formats.
* @var array
*/
protected $serializerFormats = [];
/**
* A logger instance.
* @var \Psr\Log\LoggerInterface
*/
protected $logger;
/**
* Constructs a new UserAuthenticationController object.
*
* @param \Drupal\user\UserFloodControlInterface $user_flood_control
* The user flood control service.
* @param \Drupal\user\UserStorageInterface $user_storage
* The user storage.
* @param \Drupal\Core\Access\CsrfTokenGenerator $csrf_token
* The CSRF token generator.
* @param \Drupal\user\UserAuthInterface $user_auth
* The user authentication.
* @param \Drupal\Core\Routing\RouteProviderInterface $route_provider
* The route provider.
* @param \Symfony\Component\Serializer\Serializer $serializer
* The serializer.
* @param array $serializer_formats
* The available serialization formats.
* @param \Psr\Log\LoggerInterface $logger
* A logger instance.
*/
public function __construct(array $config, $module_id, $module_definition, array $serializer_formats, UserStorageInterface $user_storage, CsrfTokenGenerator $csrf_token, UserAuthInterface $user_auth, RouteProviderInterface $route_provider, LoggerInterface $logger, AccountProxyInterface $current_user) {
parent::__construct($config, $module_id, $module_definition, $serializer_formats, $logger);
$this->loggedUser = $current_user;
$this->userStorage = $user_storage;
$this->csrfToken = $csrf_token;
$this->userAuth = $user_auth;
$this->routeProvider = $route_provider;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $config, $module_id, $module_definition) {
return new static(
$config,
$module_id,
$module_definition,
$container->getParameter('serializer.formats'),
$container->get('entity_type.manager')->getStorage('user'),
$container->get('csrf_token'),
$container->get('user.auth'),
$container->get('router.route_provider'),
$container->get('logger.factory')->get('user_login_api'),
$container->get('current_user')
);
}
/**
* Logs in a user.
* @param \Symfony\Component\HttpFoundation\Request $request
* The request.
* @return \Symfony\Component\HttpFoundation\Response
* A response which contains the ID and CSRF token.
*/
public function post(Request $data) {
global $base_url;
try {
$content = $data->getContent();
$params = json_decode($content, TRUE);
$email = $params['email'];
$password = $params['pass'];
if (empty($email) || empty($password)) {
$final_api_reponse = array(
"status" => "Error",
"message" => "Missing Credentials"
);
}
else {
$user = user_load_by_mail($email);
if(empty($user)) {
$final_api_reponse = array(
"status" => "Error",
"message" => "User Not Found",
"result" => "No user registered with ".$email
);
}
else {
$user_name = $user->get('name')->value;
if ($uid = $this->userAuth->authenticate($user_name, $password)) {
$user = $this->userStorage->load($uid);
$this->userLoginFinalize($user);
$response_data = array();
if ($user->get('uid')->access('view', $user)) {
$response_data['current_user']['uid'] = $user->id();
}
if ($user->get('name')->access('view', $user)) {
$response_data['current_user']['name'] = $user->getAccountName();
}
$response_data['csrf_token'] = $this->csrfToken->get('rest');
$logout_route = $this->routeProvider->getRouteByName('user.logout.http');
$logout_path = ltrim($logout_route->getPath(), '/');
$response_data['logout_token'] = $this->csrfToken->get($logout_path);
$final_api_reponse = array(
"status" => "Success",
"message" => "Login Success",
"result" => $response_data
);
}
else {
$final_api_reponse = array(
"status" => "Error",
"message" => "Invalid Credentials"
);
}
}
}
return new JsonResponse($final_api_reponse);
}
catch(Exception $exception) {
$this->exception_error_msg($exception->getMessage());
}
}
/**
* Finalizes the user login.
* @param \Drupal\user\UserInterface $user
* The user.
*/
protected function userLoginFinalize(UserInterface $user) {
user_login_finalize($user);
}
}
UserAccountRest.php - For fetching and editing user details
<?php
namespace Drupal\restapi\Plugin\rest\resource;
use Drupal\rest\Plugin\ResourceBase;
use Psr\Log\LoggerInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Drupal\user\Entity\User;
/**
* Provides a resource to get view modes by entity and bundle.
* @RestResource(
* id = "user_account_rest",
* label = @Translation("User Account API"),
* uri_paths = {
* "canonical" = "/api/user-account",
* "create" = "/api/edit-account",
* }
* )
*/
class UserAccountRest extends ResourceBase {
/**
* A current user instance which is logged in the session.
* @var \Drupal\Core\Session\AccountProxyInterface
*/
protected $loggedUser;
/**
* Constructs a Drupal\rest\Plugin\ResourceBase object.
*
* @param array $config
* A configuration array which contains the information about the plugin instance.
* @param string $module_id
* The module_id for the plugin instance.
* @param mixed $module_definition
* The plugin implementation definition.
* @param array $serializer_formats
* The available serialization formats.
* @param \Psr\Log\LoggerInterface $logger
* A logger instance.
* @param \Drupal\Core\Session\AccountProxyInterface $current_user
* A currently logged user instance.
*/
public function __construct(array $config, $module_id, $module_definition, array $serializer_formats, LoggerInterface $logger, AccountProxyInterface $current_user) {
parent::__construct($config, $module_id, $module_definition, $serializer_formats, $logger);
$this->loggedUser = $current_user;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $config, $module_id, $module_definition) {
return new static(
$config,
$module_id,
$module_definition,
$container->getParameter('serializer.formats'),
$container->get('logger.factory')->get('user_account_api'),
$container->get('current_user')
);
}
/*
* Fetch User Account Details API
*/
public function get() {
global $base_url;
try {
$logged_user = User::load(\Drupal::currentUser()->id());
$user_id = $logged_user->get('uid')->value;
$role = $logged_user->get('roles')->getValue();
$user_role = $role[0]['target_id'];
$user_data['user_id'] = $user_id;
$user_data['role'] = ucfirst($user_role);
$user_data['first_name'] = $logged_user->get('field_first_name')->value;
$user_data['last_name'] = $logged_user->get('field_last_name')->value;
$user_data['email'] = $logged_user->get('mail')->value;
$user_data['city'] = $logged_user->get('field_city')->value;
$final_api_reponse = array(
"status" => "Success",
"message" => "User Account",
"result" => $user_data
);
return new JsonResponse($final_api_reponse);
}
catch(Exception $exception) {
$this->exception_error_msg($exception->getMessage());
}
}
/*
* Edit User Details API
*/
public function post(Request $data) {
global $base_url;
try {
$logged_user = User::load(\Drupal::currentUser()->id());
$user_id = $logged_user->get('uid')->value;
$content = $data->getContent();
$params = json_decode($content, TRUE);
if($params['first_name'] != "") {
$logged_user->set('field_first_name', $params['first_name']);
}
if($params['last_name'] != "") {
$logged_user->set('field_last_name', $params['last_name']);
}
if($params['city'] != "") {
$logged_user->set('field_city', $params['city']);
}
$logged_user->save();
$final_api_reponse = array(
"status" => "Success",
"message" => "User Details Updated",
"result" => "Your details have been updated."
);
return new JsonResponse($final_api_reponse);
}
catch(Exception $exception) {
$this->exception_error_msg($exception->getMessage());
}
}
}
UserLogoutRest.php - For user logout
<?php
namespace Drupal\restapi\Plugin\rest\resource;
use Drupal\rest\Plugin\ResourceBase;
use Psr\Log\LoggerInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Drupal\user\Entity\User;
/**
* Provides a resource to get view modes by entity and bundle.
* @RestResource(
* id = "user_logout_rest",
* label = @Translation("User Logout API"),
* uri_paths = {
* "create" = "/api/user-logout",
* }
* )
*/
class UserLogoutRest extends ResourceBase {
/**
* A current user instance which is logged in the session.
* @var \Drupal\Core\Session\AccountProxyInterface
*/
protected $loggedUser;
/**
* Constructs a Drupal\rest\Plugin\ResourceBase object.
*
* @param array $config
* A configuration array which contains the information about the plugin instance.
* @param string $module_id
* The module_id for the plugin instance.
* @param mixed $module_definition
* The plugin implementation definition.
* @param array $serializer_formats
* The available serialization formats.
* @param \Psr\Log\LoggerInterface $logger
* A logger instance.
* @param \Drupal\Core\Session\AccountProxyInterface $current_user
* A currently logged user instance.
*/
public function __construct(array $config, $module_id, $module_definition, array $serializer_formats, LoggerInterface $logger, AccountProxyInterface $current_user) {
parent::__construct($config, $module_id, $module_definition, $serializer_formats, $logger);
$this->loggedUser = $current_user;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $config, $module_id, $module_definition) {
return new static(
$config,
$module_id,
$module_definition,
$container->getParameter('serializer.formats'),
$container->get('logger.factory')->get('user_logout_api'),
$container->get('current_user')
);
}
/*
* User Logout API
*/
public function post(Request $data) {
global $base_url;
try {
$content = $data->getContent();
$params = json_decode($content, TRUE);
$user_id = $params['user_id'];
$logged_user = User::load(\Drupal::currentUser()->id());
$current_id = $logged_user->get('uid')->value;
if(empty($user_id) || ($current_id != $user_id)) {
$final_api_reponse = array(
"status" => "Error",
"message" => "Logout Error",
"result" => "Please provide valid User-ID"
);
}
else {
user_logout();
$final_api_reponse = array(
"status" => "Success",
"message" => "Logout Success",
"result" => "You have successfully logged out from your account."
);
}
return new JsonResponse($final_api_reponse);
}
catch(Exception $exception) {
$this->exception_error_msg($exception->getMessage());
}
}
}
Step 5: Enable the 'restapi' custom module and then enable the APIs from REST UI interface.
Step 6: Set the permissions for each individual APIs.
Step 7: Now we can test these APIs in postman.
- User Details
- Edit Details
- Logout
So, in this way we can do basic operations using REST API in Drupal. I hope you find this simple use of REST API helpful.
Posted on September 9, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.