Controllers & Libraries
In the controllers directory, create a new directory for your controller and libraries. In this example, we created the Controllers/Users directory. We created UsersController.php, UsersLib.php, and UsersLibAuth.php.
UsersController - Controller Example
Setting $resourceName = 'users', this is how you will reference this controller in your Api calls. For instance,
you would call https://api.yoursite.com/users/login to perform the login function. The directory you created, Users has
to match the $resourceName. The directory should be first letter upper case, the rest lower (Users). The $resourceName should
be all lower case (users). Using this naming convention, there is no need to setup anything else for this controller, SlenderApi
automatically wires it into the framework.
Note that this is all the code that should ever go into your controller. It should be permissions, references to your
libraries, and your endpoint methods. The endpoint methods should call your libraries, which is where all your code
will go. The idea is to keep your controller simple and clean, it basically serves as a list of all your Api endpoints.
namespace SlenderApi\Controllers\Users;
use SlenderApi\Controllers as Controllers;
use SlenderApi\Lib\Request\Request;
use SlenderApi\Lib\Response\Response;
class UsersController extends Controllers\Controller
{
public object $usersLib;
public object $usersLibAuth;
public object $router;
//As noted above, this is where you set how to reference this controller.
//example: https://api.yoursite.com/users/somemethod.
public string $resourceName = 'users';
public array $methodPermissions;
public function __construct(object $db, Request $request, Response $response)
{
parent::__construct($db, $request, $response);
//Setup reference to your libraries here.
$this->usersLib = new UsersLib($this);
$this->usersLibAuth = new UsersLibAuth($this);
$this->setMethodPermissions();
}
//Setup individual permissions for any methods that require them.
//CR = Create, UP = Update, RE = Read, DE = Delete
public function setMethodPermissions()
{
$this->methodPermissions = array(
'save' => array('CR','UP'),
'updatePassword' => array('UP'),
'select' => array('RE'),
'selectColumns' => array('RE'),
'archive' => array('UP'),
);
}
//All your Api endpoints go here.
//This endpoint would be https://api.yoursite.com/users/login.
public function login()
{
$this->usersLibAuth->login();
}
public function authenticate()
{
$this->usersLibAuth->authenticate();
}
public function logout()
{
$this->usersLibAuth->logout();
}
public function register()
{
$this->usersLib->register();
}
public function save()
{
$this->usersLib->save();
}
public function updatePassword()
{
$this->usersLib->updatePassword();
}
public function forgotPassword()
{
$this->usersLib->forgotPassword();
}
public function resetPassword()
{
$this->usersLib->resetPassword();
}
public function select()
{
$this->usersLib->select();
}
public function selectColumns()
{
$this->usersLib->selectColumns();
}
public function archive()
{
$this->usersLib->archive();
}
}
UsersLibAuth - Library Example
This example library is used to take care of all of the user authentication methods. All of the things you can do with your libraries are documented in the other sections on the left menu, such as responses, requests, validation, models, and vendor libraries.
namespace SlenderApi\Controllers\Users; //Pull in all of the helpers and libraries you need. use SlenderApi\Helpers\TimeHelper; use SlenderApi\Lib\Request\Request; use SlenderApi\Lib\Response\ErrorGenerator; use SlenderApi\Lib\Response\Response; use SlenderApi\Lib\Response\Validation; use SlenderApi\Models as Models; class UsersLibAuth { private object $db; private Request $request; private Response $response; private String $email; private String $password; private Bool $remember; private Object $blankUserModel; private Object $loginUser; private ?int $authenticatedUserId; public function __construct(object $controller) { $this->db = $controller->db; $this->request = $controller->request; $this->response = $controller->response; $this->authenticatedUserId = $controller->request->getAuthenticatedUserId(); } public function login(): void { $credentials = $this->request->getCredentialsFromAuthorization(); $this->email = strtolower($credentials->username); $this->password = $credentials->password; $this->remember = $this->request->getParameterValue('remember', true); $this->blankUserModel = new Models\UserModel($this->db, null); $this->validate(); $this->checkAccess(); $this->setLoginUser(); $this->userVerified(); $this->attemptsExceeded(); $this->passwordVerified(); $this->loginSuccess(); } private function validate(): void { $validationRules = Validation::getValidationRulesByFields(Models\UserModel::getValidationRules(), array('email_address', 'password')); $validationRules['email_address'] = Validation::addValidationRuleForField($validationRules['email_address'], 'required'); $data = array( 'email_address' => $this->email, 'password' => $this->password ); $errors = Validation::getErrors($data, $validationRules); if (!empty($errors)) { $this->response->outputResponse(400, null, $errors); } } private function checkAccess(): void { $globalPermissions = $this->blankUserModel->getGlobalPermissionValues(); if (!$globalPermissions[0]->allow_login) { $this->response->addError(ErrorGenerator::getError(545, 'users')); $this->response->dieWithCode(400); } } private function setLoginUser(): void { //Execute a custom query. $users = $this->blankUserModel->selectUserByLoginUsername($this->email); $this->userExists($users); $this->loginUser = $users[0]; } private function userExists(array $users): void { if (count($users) == 0) { $this->response->addError(ErrorGenerator::getError(28, 'users', 'data')); $this->response->dieWithCode(400); } } private function userVerified(): void { if (!$this->loginUser->verified) { $this->response->addError(ErrorGenerator::getError(543, 'users')); $this->response->dieWithCode(401); } } private function attemptsExceeded(): void { if (!$this->checkLoginAttempts()) { $this->response->addError(ErrorGenerator::getError(470, 'email_address', 'validation')); $this->response->dieWithCode(400); } } private function passwordVerified(): void { if (!password_verify($this->password, $this->loginUser->password)) { $this->updateLoginAttempt(); $this->response->clearCookiesWithCode(401); } } public function updateLoginAttempt(bool $successLogin = false): void { $userModal = new Models\UserModel($this->db, $this->loginUser->id); if ($successLogin) { $updateData = array( 'login_attempts' => 0 ); } else if ($this->loginUser->login_attempts == 4) { $updateData = array( 'lockout_time' => date('Y-m-d H:i:s', strtotime('+15 minute')), 'login_attempts' => 0 ); } else { $updateData = array( 'login_attempts' => $this->loginUser->login_attempts + 1 ); } //Save the login attempts to the user table. $userModal->save($updateData, $this->loginUser->id); } public function checkLoginAttempts(): bool { if (empty($this->loginUser->lockout_time) || strtotime($this->loginUser->lockout_time) <= strtotime(date('Y-m-d H:i:s'))) { return true; } return false; } private function loginSuccess(): void { unset($this->loginUser->password); $this->updateLoginAttempt(true); $this->loginUser->remember = $this->remember; $setCookie = $this->response->setCookies($this->loginUser->id, $this->loginUser->remember, true); if (!empty($this->request->getParameterValue('device_id'))) { $userModal = new Models\UserModel($this->db, $this->loginUser->id); $userModal->save(array('last_device_id' => $this->request->getParameterValue('device_id')), $this->loginUser->id); } //User is logged in, set the auth cookie, output the success. $this->response->addData('token', $setCookie); $this->response->addData('user', $this->loginUser); $this->response->outputResponse(); } public function authenticate(): void { if (!empty($this->request->authenticatedUser)) { $browserDate = $this->request->getParameterValue('browser_date'); if (!empty($browserDate)) { $timeHelper = new TimeHelper(); $offset = $timeHelper->getTimeOffset($browserDate); $userModel = new Models\UserModel($this->db, $this->authenticatedUserId); $userModel->save(array('time_offset' => $offset), $this->authenticatedUserId); } $this->response->addData('user', $this->request->authenticatedUser); $this->response->outputResponse(200); } else { $this->response->clearCookiesWithCode(401); } } public function logout(): void { //Clear the cookies to log them out. $this->response->clearCookiesWithCode(200); } }
Posting To Endpoints
To call your controller, if it requires authentication, call https://api.yoursite.com/users/login
passing the email/password form variables to it. Once you are authenticated, call the API call
you want, pass in the auth cookie and form variables and parse your response.
Examples for language specific calls, (php, jquery, react, c#) are in Examples.