How can I write a user provider for HWIOAuthBundle - mongodb

I want to write a login feature via social networks.
if the user is not logged it persists it into the database, if the user exists, log the user in.
What should I write into my provider?
Docs state :
The bundle needs a service that is able to load users based on the
user response of the oauth endpoint. If you have a custom service it
should implement the interface:
HWI\Bundle\OAuthBundle\Security\Core\User\OAuthAwareUserProviderInterface.
So this is what I wrote and then got stuck
<?php
namespace ng\MyBundle\Controller\Listeners;
use HWI\Bundle\OAuthBundle\Security\Core\User\OAuthAwareUserProviderInterface;
class OAuthUserProvider implements OAuthAwareUserProviderInterface
{
}
Can you tell me what are the methods That I should use ?
Can anybody give me a provider example not using FOSuserBundle ?
Thanks

If you open the OAuthAwareUserProviderInterface you can see it has only one method :
/**
* Loads the user by a given UserResponseInterface object.
*
* #param UserResponseInterface $response
*
* #return UserInterface
*
* #throws UsernameNotFoundException if the user is not found
*/
public function loadUserByOAuthUserResponse(UserResponseInterface $response);
Below there is an example on how to implement it, ofcourse in your case, you should call your entity managers, and access users the way you have designed it.
/**
* {#inheritdoc}
*/
public function loadUserByOAuthUserResponse(UserResponseInterface $response)
{
$username = $response->getUsername();
$user = $this->userManager->findUserBy(array($this->getProperty($response) => $username));
//when the user is registrating
if (null === $user) {
$service = $response->getResourceOwner()->getName();
$setter = 'set'.ucfirst($service);
$setter_id = $setter.'Id';
$setter_token = $setter.'AccessToken';
// create new user here
$user = $this->userManager->createUser();
$user->$setter_id($username);
$user->$setter_token($response->getAccessToken());
//I have set all requested data with the user's username
//modify here with relevant data
$user->setUsername($username);
$user->setEmail($username);
$user->setPassword($username);
$user->setEnabled(true);
$this->userManager->updateUser($user);
return $user;
}
//if user exists - go with the HWIOAuth way
$user = parent::loadUserByOAuthUserResponse($response);
$serviceName = $response->getResourceOwner()->getName();
$setter = 'set' . ucfirst($serviceName) . 'AccessToken';
//update access token
$user->$setter($response->getAccessToken());
return $user;
}

Related

TYPO3 Extension - Redirect to another page in show action if no record is set or not available

How can I redirect to another page when someone access the detail page but without a record or if record is not available?
I have detail records like
domain.com/abc/ABC1234
When somone enters
domain.com/abc/
... I get:
Uncaught TYPO3 Exception
#1298012500: Required argument "record" is not set for Vendor\Extension\Controller\ActionController->show. (More information)
TYPO3\CMS\Extbase\Mvc\Controller\Exception\RequiredArgumentMissingException thrown in file
/is/htdocs/www/typo3_src-8.7.11/typo3/sysext/extbase/Classes/Mvc/Controller/AbstractController.php in line 425.
... in this case I want it to redirect to:
domain.com/other-page/
... I also need it if a specific record is not available.
... how to do so?
/**
* action show
*
* #param \Action $record
* #return void
*/
public function showAction(Action $record) {
$this->view->assign('record', $record);
}
Here are some examples TYPO3 Extbase - redirect to pid ... but not sure how to implement it
Edit: What works is ...
/**
* action show
*
* #param \Action $record
* #return void
*/
public function showAction(Action $record=null) {
if ($record === null) {
$pageUid = 75;
$uriBuilder = $this->uriBuilder;
$uri = $uriBuilder
->setTargetPageUid($pageUid)
->build();
$this->redirectToUri($uri, 0, 404);
} else {
$this->view->assign('record', $record);
}
}
The redirect method needs an action and controller parameter. So your redirect code is wrong.
$this->redirect($actionName, $controllerName = NULL, $extensionName = NULL, array $arguments = NULL, $pageUid = NULL, $delay = 0, $statusCode = 303);
To redirect to an PageUID you need to use the uriBuilder and the redirectToUri method. See here for an example.
This should do the trick:
public function showAction(Action $record=null) {
if ($record === null) {
$this->redirect(/* add parameters as needed */);
} else {
// other code
}
Alternative Solution (from Simon Oberländer)
public function intializeShowAction() {
if (!$this->request->hasArgument('record')) {
$this->redirect(/* add parameters as needed */); // stops further execution
}
}
Your question suggests that there should be an other action without arguments, probably a listAction, that is the DEFAULT action. The default action gets called when no action is specified. It is the first action enlisted in the ExtensionUtility::configurePlugin() call.
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
'Vendor.' . $_EXTKEY,
'Pluginname',
array(
'Domainobject' => 'list, show',
),
// non-cacheable actions
array(
'Domainobject' => 'list, show',
)
);
Regarding > The identity property "TTTT" is no UID
You have to distinguish between no parameter and an invalid parameter. For the latter you can add #ignorevalidation to the showAction comments and do your validation testing within the action - or you can leave it to extbase that displays the error message you have seen.
Where would you get a link like domain.com/abc/TTTT/ from anyhow? Unless the link is expired.
BTW: in a production system you would disable the display of exceptions, thus the display of the website would work.
This could be a solution:
```
/**
* Show a booking object
*
* #return void
* #throws \TYPO3\CMS\Extbase\Mvc\Exception\NoSuchArgumentException
*/
public function showAction()
{
$bookingObject = null;
$bookingObjectUid = 0;
if ($this->request->hasArgument('bookingObject')) {
$bookingObjectUid = (int)$this->request->getArgument('bookingObject');
}
if ($bookingObjectUid > 0) {
$bookingObject = $this->bookingObjectRepository->findByIdentifier($bookingObjectUid);
}
if (!($bookingObject instanceof BookingObject)) {
$messageBody = 'Booking object can\'t be displayed.';
$messageTitle = 'Error';
$this->addFlashMessage($messageBody, $messageTitle, AbstractMessage::ERROR);
$this->redirect('list');
}
$this->view->assign('bookingObject', $bookingObject);
}
```

How to get the url for admin page (including the key) in magento 2x custom module controller

I need the page url in Magento 2x including key in my custom module controller.
here something similar but this is for magento 1x. i need for magento 2x.
for magento 1x : Mage::helper('adminhtml')->getUrl('adminhtml/framexport/index') but i need similar for magento 2x.
The right way is, inject the UrlInterface in you model block or whatever class constructor
Then call the getUrl() function
class SomeClass extends \Some\Other\Class
{
protected $_backendUrl;
public function __construct(
...........
...........
\Magento\Backend\Model\UrlInterface $backendUrl,
...........
) {
$this->_backendUrl = $backendUrl;
}
public function someFunction()
{
$params = array('some'=>'url_parameters');
$url = $this->_backendUrl->getUrl("the/url/path", $params);
}
}
You can easily get Admin url By calling
$this->getUrl('adminhtml/module/action');
Please not that "Context" type of object is loaded in the $this object
You can get admin url as follows:
public function __construct(\Magento\Backend\Helper\Data $HelperBackend
) {
$this->HelperBackend = $HelperBackend;
}
/**
*
* #param \Magento\Framework\Event\Observer $observer
* #return void
*/
public function getAdminUrl()
{
echo $this->HelperBackend->getHomePageUrl();
}
Somehow adminhtml/module creates an extra admin slug which does not work.
My solution is:
// $this->urlBuilder is defined in __constructor() \Magento\Framework\UrlInterface $urlBuilder
$query = [
'method' => 'confirm',
'id' => $order->getEntityId()
];
$url = $this->urlBuilder->getUrl('module', $query);
It works well for secure URLs (with keys) and non-default /admin URLs, such as /backend.

PEAR QuickForm2 CSRF Protection

I was looking for a way to ensure CSRF-Protection in my Quickform2.
I found this link but it's for QuickForm1.
Any ideas how I can adapt this to QF2?
After some fiddling around I came up with this solution.
Maybe it helps someone else as well:
<?php
/**
* #uses HTML_QuickForm
* #desc Add automatic CSRF mitigation to all forms by incorporating a token that must be matched in the session and forcing the use of POST method
* Based on: http://www.zapoyok.info/2010/07/17/csrf-et-quickform-de-pear/
*/
require_once "QuickForm2.php";
class HTML_QuickForm2s extends HTML_QuickForm2
{
/**
* #property string $_sessionTokenKey The name of the session variable containing the token
*/
private $_sessionTokenKey;
/**
* #method __construct
* #desc Override the method to always use post and pass it on to the parent constructor. Create a session key for the token based on the form name.
* #param $id
* #param string $method
* #param mixed $attributes
* #param boolean $trackSubmit
*/
public function __construct($id, $method = 'post', $attributes = null, $trackSubmit = true)
{
$this->_sessionTokenKey = "QuickForm2s_" . md5($id);
parent::__construct($id, $method, $attributes, $trackSubmit);
//A token hasn't been created so do so
if (!isset($_SESSION[$this->_sessionTokenKey])) {
$_SESSION[$this->_sessionTokenKey] = md5(uniqid(rand(), true) . session_id()); //requires the session id to be known in order to add extra difficulty to compromising
}
//Hide the token at the end of the form
$this->addElement("hidden", "qfS_csrf");
$qfsCsrf= $this->getElementsByName('qfS_csrf');
$qfsCsrf[0]->setValue($_SESSION[$this->_sessionTokenKey]);
}
/**
* #method validate
* #desc Check if the passed token matches the session before allowing validation
* #return boolean
*/
public function validate()
{
$submitValues = $this->getValue();
//The token was not passed or does not match
if (!isset($submitValues['qfS_csrf']) || $submitValues['qfS_csrf'] != $_SESSION[$this->_sessionTokenKey]) {
$this->setError("Anti-CSRF token does not match");
}
return parent::validate();
}
}

Zend Framework - Router - Creating Aliases

I'm building a Zend Framework 1.11.11 application and would like to make the routes and content database driven.
I've written a FrontController Plugin that retrieves the 'paths' from the database and creates an entry in the Router for each one, with the associated controller and action.
However, I'd like to be able to use 'aliases' - a URL that behaves like a normal URL, but is an alias.
For example, if I create the following:
// Create the Zend Route
$entry = new Zend_Controller_Router_Route_Static(
$route->getUrl(), // The string/url to match
array('controller' => $route->getControllers()->getName(),
'action' => $route->getActions()->getName())
);
// Add the route to the router
$router->addRoute($route->getUrl(), $entry);
Then a route for /about/ for example can goto the staticController, indexAction.
However, what's the best way for me to create an alias of this route? So if I went to /abt/ it would render the same Controller and Action?
To me it doesn't make sense to recreate the same route as I'll be using the route as the page 'identifier' to then load content from the database for the page...
you can extend static router:
class My_Route_ArrayStatic extends Zend_Controller_Router_Route_Static
{
protected $_routes = array();
/**
* Prepares the array of routes for mapping
* first route in array will become primary, all others
* aliases
*
* #param array $routes array of routes
* #param array $defaults
*/
public function __construct(array $routes, $defaults = array())
{
$this->_routes = $routes;
$route = reset($routes);
parent::__construct($route, $defaults);
}
/**
* Matches a user submitted path with a previously specified array of routes
*
* #param string $path
* #param boolean $partial
* #return array|false
*/
public function match($path, $partial = false)
{
$return = false;
foreach ($this->_routes as $route) {
$this->setRoute($route);
$success = parent::match($path, $partial);
if (false !== $success) {
$return = $success;
break;
}
}
$this->setRoute(reset($this->_routes));
return $return;
}
public function setRoute($route)
{
$this->_route = trim($route, '/');
}
}
and add new router this way:
$r = My_Route_ArrayStatic(array('about', 'abt'), $defaults);

non-object error on Doctrine 2 entity manager object

I'm trying to learn the zend framework by reading through a book. So far all the code in it has worked, but now I'm having trouble authenticating users. The book suggests doing this through an action helper and doctrine 2's entity managers.
here's the code i'm using for this
my authenticate helper class...
public function init()
{
// Initialize the errors array
Zend_Layout::getMvcInstance()->getView()->errors = array();
$auth = Zend_Auth::getInstance();
$em = $this->getActionController()->getInvokeArg('bootstrap')->getResource('entityManager');
if ($auth->hasIdentity()) {
$identity = $auth->getIdentity();
if (isset($identity)) {
$user = $em->getRepository('Entities\User')->findOneByEmail($identity);
Zend_Layout::getMvcInstance()->getView()->user = $user;
}
}
}
the entity repository function...
public function findOneByEmail($email)
{
$rsm = new ResultSetMapping;
$rsm->addEntityResult('Entities\User', 'a');
$rsm->addFieldResult('a', 'id', 'id');
$rsm->addFieldResult('a', 'email', 'email');
$rsm->addFieldResult('a', 'fname', 'fname');
$query = $this->_em->createNativeQuery(
'SELECT a.id, a.fname, a.email FROM users a
WHERE a.email = :email',
$rsm
);
$query->setParameter('email', $email);
return $query->getResult();
}
On the page view, i'm using the following code to check that the user is logged in:
<?php
if($this->user){
?>Welcome back, <?php echo $this->user->fname; ?> • Logout<?php
} ?>
the if condition passes when i'm logged in, but it won't print the user's name.
here's the error message I get on it:
Notice: Trying to get property of non-object in C:\Program Files (x86)\Zend\Apache2\htdocs\dev.test.com\application\views\scripts\user\index.phtml on line 3
Can anyone help me fix this?
I think part of the problem is here:
if (isset($identity)) {
$user = $em->getRepository('Entities\User')->findOneByEmail($identity);
Zend_Layout::getMvcInstance()->getView()->user = $user;
}
It looks like findOneByEmail expects the email address as the parameter but the whole identity object is being passed.
That probably causes return $query->getResult(); to return null or false so $view->user is not an object and has no property fname.
I think in findOneByEmail you need to do something like $user = $em->getRepository('Entities\User')->findOneByEmail($identity->email); where $identity->email is the property that contains the email address.