Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: new command shield:extend #1141

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions examples/Controllers/LoginController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

declare(strict_types=1);

/**
* This file is part of CodeIgniter Shield.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

namespace CodeIgniter\Shield\Controllers;

use App\Controllers\BaseController;
use CodeIgniter\HTTP\RedirectResponse;

class LoginController extends BaseController
{
/**
* Displays the form the login to the site.
*
* @return RedirectResponse|string
*/
public function loginView()
{
if (auth()->loggedIn()) {
return redirect()->to(config('Auth')->loginRedirect());
}

/** @var Session $authenticator */
$authenticator = auth('session')->getAuthenticator();

// If an action has been defined, start it up.
if ($authenticator->hasAction()) {
return redirect()->route('auth-action-show');
}

return $this->view(setting('Auth.views')['login']);
}
}
104 changes: 104 additions & 0 deletions examples/Controllers/MagicLinkController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<?php

declare(strict_types=1);

/**
* This file is part of CodeIgniter Shield.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

namespace CodeIgniter\Shield\Controllers;

use App\Controllers\BaseController;
use CodeIgniter\HTTP\RedirectResponse;

/**
* Handles "Magic Link" logins - an email-based
* no-password login protocol. This works much
* like password reset would, but Shield provides
* this in place of password reset. It can also
* be used on it's own without an email/password
* login strategy.
*/
class MagicLinkController extends BaseController
{

/**
* Receives the email from the user, creates the hash
* to a user identity, and sends an email to the given
* email address.
*
* @return RedirectResponse|string
*/
public function loginAction()
{
if (! setting('Auth.allowMagicLinkLogins')) {
return redirect()->route('login')->with('error', lang('Auth.magicLinkDisabled'));
}

// Validate email format
$rules = $this->getValidationRules();
if (! $this->validateData($this->request->getPost(), $rules, [], config('Auth')->DBGroup)) {
return redirect()->route('magic-link')->with('errors', $this->validator->getErrors());
}

// Check if the user exists
$email = $this->request->getPost('email');
$user = $this->provider->findByCredentials(['email' => $email]);

if ($user === null) {
return redirect()->route('magic-link')->with('error', lang('Auth.invalidEmail'));
}

/** @var UserIdentityModel $identityModel */
$identityModel = model(UserIdentityModel::class);

// Delete any previous magic-link identities
$identityModel->deleteIdentitiesByType($user, Session::ID_TYPE_MAGIC_LINK);

// Generate the code and save it as an identity
helper('text');
$token = random_string('crypto', 20);

$identityModel->insert([
'user_id' => $user->id,
'type' => Session::ID_TYPE_MAGIC_LINK,
'secret' => $token,
'expires' => Time::now()->addSeconds(setting('Auth.magicLinkLifetime')),
]);

/** @var IncomingRequest $request */
$request = service('request');

$ipAddress = $request->getIPAddress();
$userAgent = (string) $request->getUserAgent();
$date = Time::now()->toDateTimeString();

// Send the user an email with the code
helper('email');
$email = emailer(['mailType' => 'html'])
->setFrom(setting('Email.fromEmail'), setting('Email.fromName') ?? '');
$email->setTo($user->email);
$email->setSubject(lang('Auth.magicLinkSubject'));
$email->setMessage($this->view(
setting('Auth.views')['magic-link-email'],
['token' => $token, 'ipAddress' => $ipAddress, 'userAgent' => $userAgent, 'date' => $date],
['debug' => false]
));

if ($email->send(false) === false) {
log_message('error', $email->printDebugger(['headers']));

return redirect()->route('magic-link')->with('error', lang('Auth.unableSendEmailToUser', [$user->email]));
}

// Clear the email
$email->clear();

return $this->displayMessage();
}
}
126 changes: 126 additions & 0 deletions examples/Controllers/RegisterController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
<?php

declare(strict_types=1);

/**
* This file is part of CodeIgniter Shield.
*
* (c) CodeIgniter Foundation <admin@codeigniter.com>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/

namespace CodeIgniter\Shield\Controllers;

use App\Controllers\BaseController;
use CodeIgniter\HTTP\RedirectResponse;
use CodeIgniter\Events\Events;


/**
* Class RegisterController
*
* Handles displaying registration form,
* and handling actual registration flow.
*/
class RegisterController extends BaseController
{
/**
* Displays the registration form.
*
* @return RedirectResponse|string
*/
public function registerView()
{
if (auth()->loggedIn()) {
return redirect()->to(config('Auth')->registerRedirect());
}

// Check if registration is allowed
if (! setting('Auth.allowRegistration')) {
return redirect()->back()->withInput()
->with('error', lang('Auth.registerDisabled'));
}

/** @var Session $authenticator */
$authenticator = auth('session')->getAuthenticator();

// If an action has been defined, start it up.
if ($authenticator->hasAction()) {
return redirect()->route('auth-action-show');
}

return $this->view(setting('Auth.views')['register']);
}

/**
* Attempts to register the user.
*/
public function registerAction(): RedirectResponse
{
if (auth()->loggedIn()) {
return redirect()->to(config('Auth')->registerRedirect());
}

// Check if registration is allowed
if (! setting('Auth.allowRegistration')) {
return redirect()->back()->withInput()
->with('error', lang('Auth.registerDisabled'));
}

$users = $this->getUserProvider();

// Validate here first, since some things,
// like the password, can only be validated properly here.
$rules = $this->getValidationRules();

if (! $this->validateData($this->request->getPost(), $rules, [], config('Auth')->DBGroup)) {
return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
}

// Save the user
$allowedPostFields = array_keys($rules);
$user = $this->getUserEntity();
$user->fill($this->request->getPost($allowedPostFields));

// Workaround for email only registration/login
if ($user->username === null) {
$user->username = null;
}

try {
$users->save($user);
} catch (ValidationException $e) {
return redirect()->back()->withInput()->with('errors', $users->errors());
}

// To get the complete user object with ID, we need to get from the database
$user = $users->findById($users->getInsertID());

// Add to default group
$users->addToDefaultGroup($user);

Events::trigger('register', $user);

/** @var Session $authenticator */
$authenticator = auth('session')->getAuthenticator();

$authenticator->startLogin($user);

// If an action has been defined for register, start it up.
$hasAction = $authenticator->startUpAction('register', $user);
if ($hasAction) {
return redirect()->route('auth-action-show');
}

// Set the user active
$user->activate();

$authenticator->completeLogin($user);

// Success!
return redirect()->to(config('Auth')->registerRedirect())
->with('message', lang('Auth.registerSuccess'));
}
}
Loading
Loading