Silex + RememberMeServiceProvider - login from code - silex

I'm trying to make an ajax login form.
I've configured RememberMeServiceProvider according to http://silex.sensiolabs.org/doc/providers/remember_me.html
It works great with default login form - the one that goes to 'login_path' and is managed by Silex.
I'm now trying to make custom login controller (AJAX only).
It looks like this:
public function ajaxLogin(Request $request, Application $app) {
if (!AJAX)
die;
$email = $request->request->get('_username');
$pass = $request->request->get('_password');
if (!$email || !$pass)
return 0;
try {
$user = APP::repo('users')->findOneByEmail($email);
if (!$user)
return 0;
$encodedPass = $app['security.encoder_factory']->getEncoder($user)->encodePassword($pass, $user->getSalt());
if ($encodedPass !== $user->getPassword())
return 0;
$token = new UsernamePasswordToken($user, $pass, 'all', $user->getRoles());
$app['security']->setToken($token);
return 1;
} catch (Exception $e) {
return 0;
}
}
It works great, but I have a problem with Remember Me option. How can I make it work with above custom login controller?

The problem is that you bypass the security listerner to create the authentiated token by yourself.
To create the remember-me cookie, you must trigger the loginSuccess method of your RememberMeServices.
$app['security.remember_me.service.my-firewall']->loginSuccess($request, $response, $token);
Otherwise, you should implement your own PreAuthenticator :
http://symfony.com/doc/current/cookbook/security/api_key_authentication.html

Related

Pagination is not working in twilio call logs laravel

<?php
namespace App\Http\Controllers\Api;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Http\Controllers\ApiController;
use App\Model\User;
use Illuminate\Support\Facades\Validator;
use Auth;
use Twilio\Rest\Client;
use Twilio\TwiML\VoiceResponse;
class TwilioController extends ApiController
{
public function __construct(){
$sid = env('TWILIO_SID');
$token = env('TWILIO_TOKEN');
$this->twilio = new Client($sid, $token);
if (request('lang'))
\App::setLocale(request('lang'));
}
public function callLogs(Request $request){
try{
$twilioNumber = Auth::user()->twilio_number;
$calls = $this->twilio->calls
->read([], 20);
$data = [];
$i = 0;
foreach($calls as $call){
$data[$i]['from'] = $call->from;
$i++;
}
$responseData = array('status'=>true, 'message'=>'Data has been returned successfully!', 'data'=>$data);
} catch (\Exception $e) {
$responseData = array('status'=>false, 'message'=>$e->getMessage(), 'data'=>[]);
}
$res = json_encode($responseData);
print $res;
}
Pagination is not working when i get call history in twilio using laravel rest api. when i use page parameter with this then pagination is not working it give me save output as given me 1st page.
Postman parameters - Page:2
Thanks
I think Twilio's page() function will help you. Like read(), it accepts an array of options to narrow your search along with a pageSize parameter defaulting to 50 calls per page. (I believe the maximum value is 1000.)
Here is an example.
//Get all call logs. 20 per page
$calls = $twilio->calls->page( [], 20 );
$data = [];
foreach($calls as $call){
$data[] = $call->sid;
}
//You can access the previous and next page urls using the resource functions in the calls object return from twilio.
return response()->json(["prev" => $calls->getPreviousPageUrl(), "next" => $calls->getNextPageUrl(), "calls" => $data]);

Calling an ASP.Net web api from a ASP.Net MVC web app. MVC web client is not building the URL properly so getting not found

When I run my web api method using Postman passing in my URL, it works fine - it returns the value of '5' which I expect since the call returns just a single integer. Also at the very bottom I include another method of my web api that I run using Postman and it too works just fine.
http://localhost:56224/api/profileandblog/validatelogin/DemoUser1/DemoUser1Password/169.254.102.60/
However, in the client - an Asp.Net MVC method, when building the URL, it is DROPPING the "/api/profileandblog" part. Note: I'm using "attribute routing" in the web api.
Here is the Asp.Net MVC method to call the web api:
I stop it on this line so I can see the error details: if (result1.IsSuccessStatusCode)
It's INCORRECTLY building the URL as: http://localhost:56224/validatelogin/DemoUser1/DemoUser1Password/169.254.102.60/
It's dropping the: "/api/profileandblog" part that should follow 56224.
So it give's me the Not found.
Why does it drop it? It has the localhost:56224 correct.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult SignIn(SignInViewModel signInViewModel)
{
int returnedApiValue = 0;
User returnedApiUser = new User();
DateTime currentDateTime = DateTime.Now;
string hostName = Dns.GetHostName();
string myIpAddress = Dns.GetHostEntry(hostName).AddressList[2].ToString();
try
{
if (!this.IsCaptchaValid("Captcha is not valid"))
{
ViewBag.errormessage = "Error: captcha entered is not valid.";
}
else
{
if (!string.IsNullOrEmpty(signInViewModel.Username) && !string.IsNullOrEmpty(signInViewModel.Password))
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:56224/api/profileandblog");
string restOfUrl = "/validatelogin/" + signInViewModel.Username + "/" + signInViewModel.Password + "/" + myIpAddress + "/";
// Call the web api to validate the sign in.
// Sends back a -1(failure), -2(validation issue) or the UserId(success) via an OUTPUT parameter.
var responseTask1 = client.GetAsync(restOfUrl);
responseTask1.Wait();
var result1 = responseTask1.Result;
if (result1.IsSuccessStatusCode)
{
var readTask1 = result1.Content.ReadAsAsync<string>();
readTask1.Wait();
returnedApiValue = Convert.ToInt32(readTask1.Result);
if (returnedApiValue == -2)
{
ViewBag.errormessage = "You entered an invalid user name and/or password";
}
else
{
// I have the 'user id'.
// Continue processing...
}
}
else
{
ModelState.AddModelError(string.Empty, "Server error on signing in. 'validatelogin'. Please contact the administrator.");
}
}
}
}
return View(signInViewModel);
}
catch (Exception)
{
throw;
}
}
Per the suggestion about not having headers, I used another tutorial (https://www.c-sharpcorner.com/article/consuming-asp-net-web-api-rest-service-in-asp-net-mvc-using-http-client/) and it has the code for defining the headers. But it is coded slightly different - using async Task<> on the method definition. I was not using async in my prior version.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> SignIn(SignInViewModel signInViewModel)
{
int returnedApiValue = 0;
User returnedApiUser = new User();
DateTime currentDateTime = DateTime.Now;
string hostName = Dns.GetHostName();
string myIpAddress = Dns.GetHostEntry(hostName).AddressList[2].ToString();
try
{
if (!this.IsCaptchaValid("Captcha is not valid"))
{
ViewBag.errormessage = "Error: captcha entered is not valid.";
}
else
{
if (!string.IsNullOrEmpty(signInViewModel.Username) && !string.IsNullOrEmpty(signInViewModel.Password))
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:56224/api/profileandblog");
string restOfUrl = "/validatelogin/" + signInViewModel.Username + "/" + signInViewModel.Password + "/" + myIpAddress + "/";
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// Call the web api to validate the sign in.
// Sends back a -1(failure), -2(validation issue) or the UserId(success) via an OUTPUT parameter.
HttpResponseMessage result1 = await client.GetAsync(restOfUrl);
if (result1.IsSuccessStatusCode)
{
var readTask1 = result1.Content.ReadAsAsync<string>();
readTask1.Wait();
returnedApiValue = Convert.ToInt32(readTask1.Result);
if (returnedApiValue == -2)
{
ViewBag.errormessage = "You entered an invalid user name and/or password";
}
else
{
// I have the 'user id'.
// Do other processing....
}
}
else
{
ModelState.AddModelError(string.Empty, "Server error on signing in. 'validatelogin'. Please contact the administrator.");
}
}
}
}
return View(signInViewModel);
}
catch (Exception)
{
throw;
}
}
It now has a header but still NOT building the URL properly as it is not including the "/api/profileandblog" part.
Here is the web api and the method being called:
namespace GbngWebApi2.Controllers
{
[RoutePrefix("api/profileandblog")]
public class WebApi2Controller : ApiController
{
[HttpGet]
[Route("validatelogin/{userName}/{userPassword}/{ipAddress}/")]
public IHttpActionResult ValidateLogin(string userName, string userPassword, string ipAddress)
{
try
{
IHttpActionResult httpActionResult;
HttpResponseMessage httpResponseMessage;
int returnValue = 0;
// Will either be a valid 'user id" or a -2 indicating a validation issue.
returnValue = dataaccesslayer.ValidateLogin(userName, userPassword, ipAddress);
httpResponseMessage = Request.CreateResponse(HttpStatusCode.OK, returnValue);
httpActionResult = ResponseMessage(httpResponseMessage);
return httpActionResult;
}
catch (Exception)
{
throw;
}
}
}
}
Here's the network tab of the client browser before I hit the button to fire of the Asp.Net MVC method.
The network tab of the client browser after I hit the button to fire of the Asp.Net MVC method and it fails.
Here's another example of Postman executing another method of my api just fine.
I got it to work by setting this as: client.BaseAddress = new Uri("localhost:56224"); and setting the string restOfUrl = "/api/profileandblog/validatesignin/" + signInViewModel.Username + "/" + signInViewModel.Password + "/" + myIpAddress + "/";

Router Match not returning matchedRouteName

I have been slowly working my way through a few issues with the help of this website. I think I am onto my last problem now. In my boostrap I have the following code:
$eventManager = $event->getApplication()->getEventManager();
$moduleRouteListener = new ModuleRouteListener();
$moduleRouteListener->attach($eventManager);
$serviceManager = $event->getApplication()->getServiceManager();
$eventManager->attach(MvcEvent::EVENT_DISPATCH_ERROR, function($event) use ($serviceManager ){
$exception = $event->getParam('exception');
if ($exception) {
do {
$serviceManager->get('Logger')->crit(
sprintf(
"%s:%d %s (%d) [%s]\n",
$exception->getFile(),
$exception->getLine(),
$exception->getMessage(),
$exception->getCode(),
get_class($exception)
)
);
} while ($ex = $exception->getPrevious());
$response = $event->getResponse();
$response->setHeaders(
$response->getHeaders()->addHeaderLine('Location', "/")
);
$response->setStatusCode(302);
$response->sendHeaders();
return $response;
} else {
//no route - redirect to cms handler
$newEvent = clone $event;
$eventManager = $newEvent->getApplication()->getEventManager();
$routeMatch = new Router\RouteMatch(array('controller'=>'Website\Controller\Index','action'=>'index'));
$event->stopPropagation(TRUE);
$newEvent->setRouteMatch($routeMatch);
$newEvent->getResponse()->setStatusCode(200);
$eventManager->trigger('dispatch', $newEvent);
}
});
This all works fine except that $routeMatch is not returning matchedRouteName - and so I get a 404. I know that the contoller and action names are correct as for now I am just redirecting to homepage and by echoing out $routeMatch on "Displatch" the same info is coming back.
So, it seems simply using the trigger "dispatch" is not enough.
Any help appreciated.
Thanks
Adam
Further Info: I have confirmed that the dispatch is actually working - however, the triggered 404 is still being acted upon. That is a 404 header status is being set and the default 404 handler (view etc) is being displayed.
Solved by adding: $newEvent->getResponse()->setStatusCode(200);

Zend2: how to render view wrapped in layout into a variable?

I need to save all rendered content (layout + view) in a variable to save it with Zend_Cache, I can't use Varnish, nginx or other software to do so. Currently I'm doing it like that:
$view->setTemplate('application/index/index');
$viewContent = $renderer->render($view);
$view = $this->getEvent()->getViewModel();
$view->content = $viewContent;
$content = $renderer->render($view);
Can anyone suggest me more elegant solution? Mb catching native render event with EventManager or some tricks with Response object or dispatch event? Would like to hear all suggestions.
Thanks!
Add two listeners to your Module class. one listener checks early, just after route if the match is one that's cached. The second listener waits for render and grabs the output to store it in cache:
namespace MyModule;
use Zend\Mvc\MvcEvent;
class Module
{
public function onBootstrap(MvcEvent $e)
{
// A list of routes to be cached
$routes = array('foo/bar', 'foo/baz');
$app = $e->getApplication();
$em = $app->getEventManager();
$sm = $app->getServiceManager();
$em->attach(MvcEvent::EVENT_ROUTE, function($e) use ($sm) {
$route = $e->getRouteMatch()->getMatchedRouteName();
$cache = $sm->get('cache-service');
$key = 'route-cache-' . $route;
if ($cache->hasItem($key)) {
// Handle response
$content = $cache->getItem($key);
$response = $e->getResponse();
$response->setContent($content);
return $response;
}
}, -1000); // Low, then routing has happened
$em->attach(MvcEvent::EVENT_RENDER, function($e) use ($sm, $routes) {
$route = $e->getRouteMatch()->getMatchedRouteName();
if (!in_array($route, $routes)) {
return;
}
$response = $e->getResponse();
$content = $response->getContent();
$cache = $sm->get('cache-service');
$key = 'route-cache-' . $route;
$cache->setItem($key, $content);
}, -1000); // Late, then rendering has happened
}
}
Just make sure you register a cache instance under cache-service in the service manager. You can update above example to check during the render event if the route is in the $routes array. Now you just check if the cache has the key, which might be slower than doing in_array($route, $routes) like during the render event.

ZF2 Redirect out of Controller

Before all, sorry for my poor english.
Good night/day/afternoon (depending of your location)
Sorry if I ask something that could be searched here, and I searched, even found it, but maybe I di not understand.
I need to check authentication in my controllers, so, I implement a master controller and extend all my real controllers to it. In my master controller I check authentication and do it well, but when I try to redirect an unauthenticated user it crashes!
Searching in web, I realized that "init, preDispatch, etc" methods even don't exist more, just the "construct" method, so I try in it, but in construct there is not an event manager, so I stop here...
This is my code:
public function __construct(){
$r = new SimpleRouteStack();
$r->addRoute('logoff', Literal::factory(array(
'route'=>'/suporte/logoff',
'defaults' => array(
'action' => 'logoff',
'controller' => 'Suporte\Controller\Index',
)
)
)
);
$e = new MvcEvent();
$e->setRouter($r);
$this->setEvent($e);
$this->getEvent()->setResponse(new Response());
$this->getEventManager()->attach('*',array($this,'mvcPreDispatch'),100);
public function mvcPreDispatch(){
$uri = explode('/',substr($_SERVER['REQUEST_URI'],1));
$uri[2] = !isset($uri[2]) ? "index" : $uri[2];
$auth = new AuthenticationService();
$identity = $auth->getStorage()->read();
$acl = $identity[2];
if (!$auth->hasIdentity()){
$this->redirect()->toRoute('suporte/logoff');
}elseif ( !$acl->hasResource($uri[0].'/'.$uri[1])
||
!$acl->isAllowed($identity[1],
$uri[0].'/'.$uri[1],
$uri[2]
)
)
$this->redirect()->toRoute('logoff');
else{
/* $this->layout()->id = $identity[0]->getId();
$this->layout()->nome = $identity[0]->getNome();
$this->layout()->cargo = $identity[0]->getCargo(); */
echo "permitido";
//$this->layout()->recursos = $this->acl->getResources();
}
}
is your Suporte\Controller\logoff also extending the masterclass. If yes then it will lead to an infinite loop indexController>masterController(!loggedin)>logoutController>masterController(!loggedin)>logoutController>..
How I used to say "IT is witchcraft"!!!
When I wake up today, turn on my computer, test the controller and BAZINGA!!! is running ok...
Why? I don't dare to question...
my code is that:
abstract class PadraoControllerSuporte extends AbstractActionController{
public function setEventManager(EventManagerInterface $events){
parent::setEventManager($events);
$controller = $this;
$events->attach('dispatch', function ($e) use ($controller) {
if (is_callable(array($controller, 'verificaAuth'))){
call_user_func(array($controller, 'verificaAuth'));
}
}, 100);
}
public function verificaAuth(){
$uri = explode('/',substr($_SERVER['REQUEST_URI'],1));
$uri[2] = !isset($uri[2]) ? "index" : $uri[2];
$auth = new AuthenticationService();
$identity = $auth->getStorage()->read();
$acl = $identity[2];
if (!$auth->hasIdentity())
$this->redirect()->toRoute('suporte/logoff');
elseif ( !$acl->hasResource($uri[0].'/'.$uri[1]) !$acl->isAllowed( $identity[1],
$uri[0].'/'.$uri[1],
$uri[2]
)
)
$this->redirect()->toRoute('logoff');
else{
/* $this->layout()->id = $identity[0]->getId();
$this->layout()->nome = $identity[0]->getNome();
$this->layout()->cargo = $identity[0]->getCargo(); */
echo "permitido";
//$this->layout()->recursos = $this->acl->getResources();
}
}
What I understood:
I think that "setEventManager" was superimposed, so it sets to listen the "dispatch" event and call my verificaAuth function what redirects (if not authenticated) to logoff or allow it is authenticated.
Hope this is usefull...
Thanks for all!!!

Resources