accessing session variable inside a response transformer in gatling - gatling

I have a basic question for which I don't seem to be able to find the answer. How can I access session variables inside a response transformer? Something like:
.transformResponse {
case response if response.isReceived =>
new ResponseWrapper(response) {
session??
override val body = new ByteArrayResponseBody("", UTF_8)
}
};

There is no Session object in context of that partial function, so you can't access it. What do you want to achieve? Maybe check(bodyString.transform()) would be better solution as it can take (String, Session) => T as parameter so you can access session attributes in that function.

Related

Trying to get user id with Auth::id() but it doesn't work in my Model? [duplicate]

When I am tring to get loggedin user details using auth:api middleware, it returns user object with details in my controller function.
api.php (with auth:api middleware returns User object)
Route::group(['middleware' => 'auth:api'], function() {
Route::get('users/mentor_details/{uuid}','UserController#getMentorProfileDetails');
});
But when I am trying to get loggedin user details outside this auth:api middleware, it returns null.
api.php (without auth:api middleware return null)
Route::get('users/mentor_details/{uuid}','UserController#getMentorProfileDetails');
When the auth middleware is not provided, or is provided without specifying the guard, the default guard is used to determine the user. Unless you have changed this in your config/auth.php file, the default guard is the web guard.
So, when you go to a route that is not protected by a specific auth middleware, the user that is loaded is the one provided by the web guard.
Therefore, even though you may be sending the bearer token to use a specific user, the web guard doesn't know anything about that, and since you have no user logged in via the web guard, you are getting a null user.
You've got four options:
Make sure the route is protected by the auth:api middleware, which specifies the api guard. This, however, will not allow guests to access the url.
Change your default guard to api in your config/auth.php file. This is probably not what you want to do, especially if you do have normal web users.
Tell the request you want the user from the api guard. The $request->user() method takes a guard as an argument, so if you do $request->user('api'), it will retrieve the user using the api guard.
Get the user from the api guard directly: auth()->guard('api')->user().
The auth middleware is the one returning the user. auth:api just indicates to use the API guard. In the source code of laravel, the file vendor/laravel/framework/src/Illuminate/Auth/Middleware/Authenticate.php line 62, the function shouldUse is the one setting the Auth::user() object. Check out also vendor/laravel/framework/src/Illuminate/Auth/AuthManager.php shouldUse function
override createToken() method app\Models\User.php like below.
public function createToken($user_id,$name, array $scopes = [])
{
return Container::getInstance()->make(PersonalAccessTokenFactory::class)
->make(
$user_id, $name, $scopes
);
}
And create token as given below wherever you want and explicitly pass $user_id.
$user= new user();
$accessToken = $user->createToken($user_id,'authToken')->accessToken;
Now you will get $request->user()
override register() method app\Exceptions\Handler.php like below-
public function register() {
$this->renderable(function (\Illuminate\Auth\AuthenticationException $e, $request) {
if ($request->is('api/*')) {
return response()->json([
'message' => 'Not authenticated'
], 401);
}
});
}

How to use a CookieCollection in multiple functions

I'm setting up a web page using cookies to determine if the user already logged in, using a cookie containing his id. Problem is : The cookie is either not written or the cookie collection is not updated.
I've tried reading the documentation, but it does not define the usage of CookieCollection.
Here's the function where i write my cookie :
function displayData(){
$id = $this->getRequest()->getSession()->read('id');
$cookies = CookieCollection::createFromServerRequest($this->getRequest());
if(!$cookies->has('id')){
$cookie = (new Cookie('id'))
->withValue($id)
->withExpiry(new DateTime('+999 year'))
->withPath('/')
->withDomain('break-first.eu')
->withSecure(true)
->withHttpOnly(true);
$cookies = $cookies->add($cookie);
}
// Other stuff
}
And where I try reading it :
function index(){
$cookies = $this->getRequest()->getCookieCollection();
dd($cookies);
}
I expect having a cookie named "id", but I don't have it. Only CAKEPHP and pll_language are showing up.
First things first, CakePHP provides authentication functionality with cookie authentication, you may want to have a look at that instead of driving a custom solution.
Cookbook > Plugins > Authentication
That being said, what you're doing there will create a cookie collection object, which however is just that, a lone object somewhere in space, it won't affect the state of your application, in order for that to happen you have to actually modify the response object.
However what you're trying to do there doesn't require cookie collections in the first place, you can simply read and write cookies directly via the methods provided by the request and response objects, like:
// will be `null` in case the cookie doesn't exist
$cookie = $this->getRequest()->getCookie('id');
// responses are immutable, they need to be reassinged
this->setResponse(
$this->getResponse()->withCookie(
(new Cookie('id'))
->withValue($id)
->withExpiry(new DateTime('+999 year'))
->withPath('/')
->withDomain('break-first.eu')
->withSecure(true)
->withHttpOnly(true)
)
);
And if you where to use a cookie collection for whatever reason, then you'd use withCookieCollection() to pass it into the response:
$this->setResponse($this->getResponse()->withCookieCollection($cookies));
If you run into strict typing errors, you could for example create a custom reponse class with an overridden Response::convertCookieToArray() method and cast the string to an integer there (make sure that PHP_INT_MAX covers your target date timestamp, 32-Bit incompatibility is why the fix that landed in CakePHP 4.x, probably won't come to 3.x), something like:
src/Http/Response.php
namespace App\Http;
use Cake\Http\Cookie\CookieInterface;
use Cake\Http\Response as CakeResponse;
class Response extends CakeResponse
{
protected function convertCookieToArray(CookieInterface $cookie)
{
$data = parent::convertCookieToArray($cookie);
$data['expire'] = (int)$data['expire'];
return $data;
}
}
You can pass that into the app in your webroot/index.php file, as the second argument of the $server->run() call:
// ...
$server->emit($server->run(null, new \App\Http\Response()));
See also
Cookbook > Request & Response Objects > Request > Cookies
Cookbook > Request & Response Objects > Response > Setting Cookies

Cakephp 3 - CRUD plugin - Use id from auth component

Currently, I'm using the CRUD v4 plugin for Cakephp 3. For the edit function in my user controller it is important that only a user itself can alter his or her credentials. I want to make this possible by inserting the user id from the authentication component. The following controller method:
public function edit($id = null){
$this->Crud->on('beforeSave', function(\Cake\Event\Event $event) {
$event->subject()->entity->id = $this->Auth->user('id');
});
return $this->Crud->execute();
}
How can I make sure I don't need to give the id through the url? The standard implementation requires the url give like this: http://domain.com/api/users/edit/1.json through PUT request. What I want to do is that a user can just fill in http://domain.com/api/users/edit.json and send a JSON body with it.
I already tried several things under which:
$id = null when the parameter is given, like in the example above. Without giving any id in the url this will throw a 404 error which is caused by the _notFound method in the FindMethodTrait.php
Use beforeFind instead of beforeSave. This doesn't work either since this isn't the appropriate method for the edit function.
Give just a random id which doesn't exist in the database. This will through a 404 error. I think this is the most significant sign (combined with point 1) that there is something wrong. Since I try to overwrite this value, the CRUD plugin doesn't allow me to do that in a way that my inserting value is just totally ignored (overwriting the $event->subject()->entity->id).
Try to access the method with PUT through http://domain.com/api/users.json. This will try to route the action to the index method.
Just a few checks: the controllerTrait is used in my AppController and the crud edit function is not disabled.
Does anyone know what I'm doing wrong here? Is this a bug?
I personally would use the controller authorize in the Auth component to prevent anyone from updating someone else's information. That way you do not have to change up the crud code. Something like this...
Add this line to config of the Auth component (which is probably in your AppController):
'authorize' => ['Controller']
Then, inside the app controller create a function called isAuthorized:
public function isAuthorized($user) {
return true;
}
Then, inside your UsersController you can override the isAuthorized function:
public function isAuthorized($user) {
// The owner of an article can edit and delete it
if (in_array($this->request->action, ['edit'])) {
$userId = (int)$this->request->params['pass'][0];
if ($user['id'] !== $userId) {
return false;
}
}
return parent::isAuthorized($user);
}

Making calls from the Javascript client library with #Named and unnamed parameters makes no sense

I have a Cloud Endpoints method that looks like this:
//HTTP POST
#ApiMethod(name = "hylyts.insert")
public Hylyt insertHylyt(#Named("url") String url, Hylyt hylyt, User user)
throws OAuthRequestException{
log.info("Trying to save hylyt '"+hylyt+"' with id '"+hylyt.getId());
if (user== null) throw new OAuthRequestException("Your token is no good here.");
hylyt.setArticle(getArticleKey(url, user));
ofy().save().entity(hylyt);
return hylyt;
}
I call it from the Javascript Client Library using this:
gapi.client.hylytit.hylyts.insert({PARAMS}).execute(callback);
Now, if I structure {PARAMS} as suggested in the docs (second example),
{
'url': url,
'resource': {
'hylyt': {
'contentType': 'application/json',
'data': hylyt
}
}
}
I get a null object in the endpoint (not to mention that the whole point of this library is to make these calls simple, which this structure clearly violates).
When I structure {PARAMS} as these answers suggest,
{
'url': url,
'resource': hylyt
}
I get a null object in the endpoint again. The correct syntax is this:
{
'url': url,
'id': hylyt.id
'text': hylyt.text
}
Which just blows my mind. Am I doing this all wrong? Is this a bug? Is it only happening because gapi is also passing the auth token in the background?
Yes, I could use the request syntax instead, but, again, why even use the library if it's just as complex as making the XHRs in pure javascript? I wouldn't mind the complexity if Google explained in the docs why things are happening. But the docs, paraphrased, just say use these methods and the auth, CORS, and XHR magic will happen behind closed doors.
Is the API method correctly recognized as POST method?
The resource parameter which is sent as POST body won't work correctly in a GET request.
The way it looks you are actually sending a GET request with the Hylyt properties in the query string.
To make sure you can change the method annotation to this:
#ApiMethod(name = "hylyts.insert", httpMethod = HttpMethod.POST)
Yup, agreed it's a bug. caused me great pains as well.
So i guess the work around is to create a combined object to pass to your api all named and un named parameters. Rather than hardcode each.. a quick loop might be better.
var param = {};
param["url"] = url;
for (var prop in hylyt) {
param[prop] = hylyt[prop];
}
gapi.client.hylytit.hylyts.insert(param).execute(callback);
That mashing together of parameters / objects can become a slick function if you really want.. but it's a band aid for what I'd consider a defect.
I see in the related question (cloud endpoints resource attribute for transmitting named params & body not working), you actually logged a defect.. Good stuff. Though there still appears no movement on this one. fingers crossed for someday!
The bug has been resolved. The correct syntax is
gapi.client.hylytit.hylyts.insert({url: url}, hylyt).execute(callback);

How to know if a Kohana request is an internal one?

I'm writing an API using Kohana. Each external request must be signed by the client to be accepted.
However, I also sometime need to do internal requests by building a Request object and calling execute(). In these cases, the signature is unnecessary since I know the request is safe. So I need to know that the request was internal so that I can skip the signature check.
So is there any way to find out if the request was manually created using a Request object?
Can you use the is_initial() method of the request object? Using this method, you can determine if a request is a sub request.
Kohana 3.2 API, Request - is_initial()
It sounds like you could easily solve this issue by setting some sort of static variable your app can check. If it's not FALSE, then you know it's internal.
This is how I ended up doing it: I've overridden the Request object and added a is_server_side property to it. Now, when I create the request, I just set this to true so that I know it's been created server-side:
$request = Request::factory($url);
$request->is_server_side(true);
$response = $request->execute();
Then later in the controller receiving the request:
if ($this->request->is_server_side()) {
// Skip signature check
} else {
// Do signature check
}
And here is the overridden request class in application/classes/request.php:
<?php defined('SYSPATH') or die('No direct script access.');
class Request extends Kohana_Request {
protected $is_server_side_ = false;
public function is_server_side($v = null) {
if ($v === null) return $this->is_server_side_;
$this->is_server_side_ = $v;
}
}
Looking through Request it looks like your new request would be considered an internal request but does not have any special flags it sets to tell you this. Look at 782 to 832 in Kohana_Request...nothing to help you.
With that, I'd suggest extending the Kohana_Request_Internal to add a flag that shows it as internal and pulling that in your app when you need to check if it is internal/all others.
Maybe you are looking for is_external method:
http://kohanaframework.org/3.2/guide/api/Request#is_external
Kohana 3.3 in the controller :
$this->request->is_initial()
http://kohanaframework.org/3.3/guide-api/Request#is_initial

Resources