multiple karate.call in karate.config.js with different var names to same feature file - karate

I am trying to test role specific features in parallel in karate. I have few features for each role and needs role specific token for auth.
I am trying to call a token generation url for various roles and store the token in karate.config.js in different variable names to re-use across the respective scenarios without having to call the token generration once per feature.
var adminTokenResponse = karate.call('classpath:helpers/GenerateToken.feature',{username: 'jane', password: 'somesecret'})
config.adminToken = adminTokenResponse.token
var userTokenResponse = karate.call('classpath:helpers/GenerateToken.feature',{username: 'john', password: 'nothingsecret'})
config.userToken = userTokenResponse.token
var superAdminResponse = karate.call('classpath:helpers/GenerateToken.feature',{username: 'king', password: 'topsecret'})
config.superAdminToken = superAdminResponse.token
Expectation:
Karate calls the Generate token three times and sets appropriate tokens.
Actual:
Karate calls the Generate token only once and sets admin token to all the three variables.
I used a work around by adding three feature files as below and called the GenerateToken within them and it worked. Is there a way we can generate different tokens without having to create additional features. If there are 10 roles I have to create 10 features to get those tokens.
var adminTokenResponse = karate.call('classpath:helpers/GenerateAdminToken.feature',{username: 'jane', password: 'somesecret'})
config.adminToken = adminTokenResponse.token
var userTokenResponse = karate.call('classpath:helpers/GenerateUserToken.feature',{username: 'john', password: 'nothingsecret'})
config.userToken = userTokenResponse.token
var superAdminResponse = karate.call('classpath:helpers/GenerateSuperAdminToken.feature',{username: 'king', password: 'topsecret'})
config.superAdminToken = superAdminResponse.token

Related

SurveyMonkey API not filtering on status

I'm new to the SurveyMonkey API (and relatively new to Python in general).
I'm trying to retrieve the contacts that have either bounced or opted out (with 2 separate calls). This code was working last week (at that time, the query parameters were permissible on the contacts/bulk endpoint and they are now only on the contacts endpoint).
The code below is only returning active contacts (the default). It does 'accept' when I change the per_page parameter but I'm not sure why the status isn't working.
Where am I going wrong?
token = <our_token>
client = requests.session()
headers = {
"Authorization": "Bearer %s" % token,
"Content-Type": "application/json"
}
HOST = "https://api.surveymonkey.com"
EMAIL_ENDPOINT = "/v3/contacts"
OPTOUT = '?status=optout'
PER_PAGE = '&per_page=1000'
optout_url = "%s%s%s%s" % (HOST, EMAIL_ENDPOINT, OPTOUT, PER_PAGE)
optout_api = client.get(optout_url, headers=headers).json()
nm. Heard back from SurveyMonkey and it's an issue on their end.

Pipe request, resend request to another endpoint (make a common endpoint that lead to another endpoint

I want to create a common /me endpoint for all my roles (operators, managers, simple users, etc.) for all 4 methods, GET, POST, DELETE, UPDATE.
I found 2 methods to do it:
Call correspond function inside endpoint (requires to create a separate endpoint for every HTTP method).
Redirection (Allow to create a single function).
That is how it looks:
#router.get(path="/me", status_code=200) # Var 1
async def get_my_profile(
token: str = Depends(config.oauth2_scheme),
postgres_session: AsyncSession = Depends(database.get_db), ):
try:
token_payload = jose_jwt.get_unverified_claims(token=token)
if token_payload['role'] == config.USER_ROLE:
return await routers.users.get_user(user_id=int(token_payload['sub']),
token=token,
postgres_session=postgres_session)
except Exception as error:
services.error_handler(error)
#router.api_router(path="/me", status_code=200, methods=["GET", "POST", "DELETE", "PATCH"]) # Var 2
async def get_my_profile(request: Request, token: str = Depends(config.oauth2_scheme),):
try:
token_payload = services.get_token_payload(token=token)
scheme_ip_port = f'{request.url.scheme}://{request.url.hostname}:{request.url.port}'
urls = [f"{scheme_ip_port}/users/{token_payload['sub']}",
f"{scheme_ip_port}/operators/{token_payload['sub']}",
f"{scheme_ip_port}/clinics/employees/{token_payload['sub']}",
]
for i, url in enumerate(iterable=urls):
if i == token_payload['role']:
return responses.RedirectResponse(url=url)
except Exception as error:
services.error_handler(error)
Which one is preferred to use? What drawbacks every solution has?

Karate - switch between headers

Presume I have 2 users and I use basic authentication. I'd like to generate the 2 basic auth tokens once and reuse it per scenario in one feature. On top of that I have scnearios where no authorization is needed. How could I achieve this with the least biolerplate? Currently I have
auth-header.js
function(creds) {
var temp = creds.username + ':' + creds.password;
var Base64 = Java.type('java.util.Base64');
var encoded = Base64.getEncoder().encodeToString(temp.bytes);
return 'Basic ' + encoded;
}
karate-config.js
...
config.apitester1AuthHeader =
karate.call('classpath:auth-headers.js', {username:'apitester1', password:'xxx'});
config.apitester2AuthHeader =
karate.call('classpath:auth-headers.js', {username:'apitester2', password:'xxx'});
...
project-get.feature
Feature: project end-point
Background:
* url baseUrl
Scenario: get projects user has right to
* configure headers = {Authorization : '#(apitester1AuthHeader)'}
Given path 'project'
...
What you have looks reasonable.
Note that if you do:
* configure headers = null
It will have the effect of temporary no authorization. I would recommend stick with what you have and it is quite modular already.

Writing to a config file dynamically using PHP

Implementing a SAAS (multi-tenant) app, I have a situation where an app would need to connect to different databases based on the user who wants to login. The databases are for separate institutions. Let's say MANAGER-A for institution-A, MANAGER-B for institution-B, want to login into their various institutions.
The process I'm implementing is this: There are 3 databases involved: DEFAULT-DB, INSTITUTION-A-DB, INSTITUTION-B-DB. The DEFAULT-DB contains all the login and database credentials of each user. This means that before MANAGER-A can login to his app, what happens is that, first, he will be logged in into the DEFAULT-DB, if successful, his details would be fetched and logged and set as the parameter of the config.php file. This means that connection will be dynamic based on the params fetched and passed by the DEFAULT-DB. My questions are these:
How do I write these params dynamically to the config.php file?
Secondly, I'm open to experts advise if my implementation is not the best.
Config.php file
<?php
unset($CFG);
global $CFG;
$CFG = new stdClass();
$CFG->dbtype = 'mysqli';
$CFG->dblibrary = 'native';
$CFG->dbhost = 'localhost';
$CFG->dbname = 'mydb';
$CFG->dbuser = 'root';
$CFG->dbpass = '';
$CFG->prefix = 'my_';
$CFG->dboptions = array (
'dbpersist' => 0,
'dbport' => '',
'dbsocket' => '1',
'dbcollation' => 'utf8mb4_unicode_ci',
);
$CFG->wwwroot = 'http://localhost:8888/myapp';
$CFG->dataroot = '/Applications/MAMP/data/myapp_data';
$CFG->admin = 'admin';
$CFG->directorypermissions = 0777;
require_once(dirname(__FILE__) . '/lib/setup.php');
This is Moodle. I have tried IOMAD, it is a great app but does not address my need.
That is a bad solution, IMHO. When you rewrite the configuration file, what happens when the next request comes in that loads that file? They will load the wrong configuration.
I would create two additional configuration files: config_inst_a.php and config_inst_b.php. Then set a session variable when the user logs in that contains the settings file name to load. You can then redefine the database information variables in the additional settings files. If the session variable has a filename in it, load that file AFTER the default config and the database connection values will be replaced.
Added sample code:
Really, really brief:
// Log in user here, and get info about what user company..
$session_start();
$_SESSION['User_ConfigFile'] = 'settings'.$userCompany.'.php';
// More code, or page redirect, or whatever, but the below goes on every page AFTER the default DB is included:
$session_start();
require_once($_SESSION['User_ConfigFile']);
If it helps somebody, my solution, not in production yet, but for now it works like a charm.
if ($_SERVER['SERVER_NAME'] == 'institutionA.mydomain.com') {
$CFG->dbname = 'institutionA'; // database name, eg moodle
$CFG->dbuser = 'user_institutionA'; // your database username
$CFG->wwwroot = 'https://institutionA.mydomain.com';
$CFG->dataroot = 'dataroot_institutionA';
//
$CFG->some_custom_data = 'my_institutiona_data';
} else
if ($_SERVER['SERVER_NAME'] == 'institutionB.mydomain.com') {
$CFG->dbname = 'institutionB'; // database name, eg moodle
$CFG->dbuser = 'user_institutionB'; // your database username
$CFG->wwwroot = 'https://institutionB.mydomain.com';
$CFG->dataroot = 'dataroot_institutionB';
//
$CFG->some_custom_data = 'my_institutionB_data';
} else {
...... anything you need in this case
}

Retrieve username and password from text files and collect them in a log in variable(params)

I have got a function that stores the username and password in each separate text files (Titanium.Filesystem.applicationDataDirectory, "userName.txt") and (Titanium.Filesystem.applicationDataDirectory, "passWord.txt") after the login has been confirmed valid by the webserver(php).
Now I need a function that retrieve the values(text content) from userName.txt and passWord.txt and collect these values in a var params that post them to the php-server on an event:
var params = {
username: username.value,
password: Ti.Utils.md5HexDigest(password.value)
};
Why don't you use the Ti.App.Properties? It is designed for storing data just like this.
Ti.App.Properties.setString('username', username.value);
username.value = Ti.App.Properties.getString('username');
http://docs.appcelerator.com/titanium/2.0/index.html#!/api/Titanium.App.Properties
If you must use files (which I do not recommend):
var file = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, 'username.txt');
file.write(username.value);
username.value = file.read();