DEV Community

Rahul Khan
Rahul Khan

Posted on • Edited on

User Create in Drupal 10 using REST API

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).
Image description

Step 2: Download and install HAL & REST UI module.
Image description

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'
Image description

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());
        }
    }
}


Enter fullscreen mode Exit fullscreen mode

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);
    }
}


Enter fullscreen mode Exit fullscreen mode

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());
        }
    }
}


Enter fullscreen mode Exit fullscreen mode

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());
        }
    }
}


Enter fullscreen mode Exit fullscreen mode

Step 5: Enable the 'restapi' custom module and then enable the APIs from REST UI interface.
Image description

Step 6: Set the permissions for each individual APIs.

Image description

Step 7: Now we can test these APIs in postman.

  • Registration
    Image description

  • Login

Image description

  • User Details

Image description

  • Edit Details

Image description

  • Logout

Image description

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.

Top comments (1)

Collapse
 
jeetpatel_32 profile image
JEET

Hi,
This is very helpful articles.
Can you please share the "Authentication providers" screenshot of the User Details API?