I am trying to implement Gmail API for CRM based on laravel, where users can store multiple Google credentials, and using those credentials users can log in with their Google account.
I used dacastro4 laravel-gmail package, but for dacastro4/laravel-gmail package by default design, those Google credentials are stored in .env file of the laravel project.
.env
GOOGLE_PROJECT_ID=
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
GOOGLE_REDIRECT_URI=
`
I tried setting the .env variable in the controller constructor function, but not working.
for example,
env('GOOGLE_PROJECT_ID',$project_id);
//OR
putenv("GOOGLE_PROJECT_ID=".$project_id);
//OR
config(['GOOGLE_PROJECT_ID' => $project_id])
Also tried setting in the vendor dacastro4 laravel-gmail package, but the database model is not accessible.
How can I set multiple Google credentials from the controller?
Thank You.
You can set this data using the config() method, seeing as that's how Laravel accesses .env variables.
Create a config file for your variables:
config/gmail.php
<?php
return [
'project_id' => env('GOOGLE_PROJECT_ID'),
'client_id' => env('GOOGLE_CLIENT_ID'),
'client_secret' => env('GOOGLE_CLIENT_SECRET'),
'redirect_url' => env('GOOGLE_REDIRECT_URI', '/'),
]
Then set values in your controller on the go using:
config(['gmail.project_id' => $project_id]);
and retrieve the values using:
config('gmail.project_id');
Related
I use PHP Symfony for my backend. I need to download cloudinary data into my EC2 instance using the cloudinary url of a single file or folder. For that, i wanted to create a PHP script to do that.
I use cloudinary_php package (https://packagist.org/packages/cloudinary/cloudinary_php). I use the upload functionality to store my data, but it doesn't seem to have a download method.
I wanted to know if this is possible, with cloudinary_php or with another pachage ?
Thanks for your help!
In your Symfony's project root folder, you should have the file composer.json. Then add following entry that looks like this:
{
"require": {
"cloudinary/cloudinary_php": "^2"
}
}
Then make sure to install the dependencies. Follow this composer doc. After that, you can now then plug in your API key and Secret then instantiate a Cloudinary object:
require 'vendor/autoload.php';
use Cloudinary\Configuration\Configuration;
use Cloudinary\Api\Upload\UploadApi;
// configure globally via a JSON object
Configuration::instance([
'cloud' => [
'cloud_name' => 'your-cloud-name-here',
'api_key' => 'xxxxxxxx',
'api_secret' => 'xxxxxxxxxx'
],
'url' => [
'secure' => true
]
]);
//Instanstiate and generate an archive
$cloudinary = (new UploadApi());
$response = $cloudinary->createZip([
'tags' => 'jeep', // Change this base on your use case
'resource_type' => 'image' // Change this base on your use case
]);
//Check the response object
print_r($response);
//Make your own implementation here to download the archive.
The response object above should have the secure_url key where you can directly download the generated archive link. Visit the documentation here for more info. There are also lots of optional parameters you can pass and you should choose what works best for you. You should also consider Symfony's security best practices when referencing sensitive information. For general Cloudinary PHP SDK integration, visit this.
I did asked a question setting value in component dynamically from database, providing example for swiftmailer. The same was answered perfectly here
but that answer applies to mailer component only, so how I can achieve the similar functionality for example, I need to added in my config.php values like:
'pp' => [
'class' => 'app/components/paypal', // note: this has to correspond with the newly created folder, else you'd get a ReflectionError
// Next up, we set the public parameters of the class
'client_id' => 'YOUR-CLIENT-ID-FROM-PAYPAL',
'client_secret' => 'YOUR-CLIENT-SECRET-FROM-PAYPAL',
// You may choose to include other configuration options from PayPal
// as they have specified in the documentation
],
If you need to provide these credentials from the database on runtime you can define it via your code using the setComponents() method of the yii\base\Application class where you are retrieving the settings from the database for paypal and remove it from the config file.
Add the following lines to set the component on runtime and then call the desired method
Yii::$app->setComponents(
[
'pp' => [
'class' => 'app/components/paypal', //note: this has to correspond with the newly created folder, else you'd get a ReflectionError
// Next up, we set the public parameters of the class
'client_id' => 'YOUR-CLIENT-ID-FROM-PAYPAL',
'client_secret' => 'YOUR-CLIENT-SECRET-FROM-PAYPAL'
// You may choose to include other configuration options from PayPal
// as they have specified in the documentation
]
]
);
//now you can call the desired method for the pp with the above credentials
Yii::$app->pp->checkout();
I'm currently using spatie/permissions and a Subclass of User with constraints to permissions to Login to subdomains in my application.
I now want to be able to share the session between my main domain example.com and the domains some.example.com where some is dynamically loaded from database.
When my logged-in User in example.com accesses the abc.example.com domain and is able to log in there I want to use the current session.
I use different guards on subdomain and domain with the SubUser and User classes as providers.
I already use the database session driver and can see in the logs that the same session id is loaded from database.
As the application is loading the same session from database I'm wondering why my user is not already logged in.
Anyone ever tried this and got a solution for this?
So I managed to resolve this issue.
My setup is all subdomains got the user guard and the main domain has the admin guard.
I realised that the Auth::getName() included the guard name and as I logged in using different guards I ended up having two active logins in one session. But these logins had different names and where only valid with the right guard. This guard being different in main domain and subdomains resulted in not really sharing login-state over domain and subdomains.
I managed to resolve this by overriding the default laravel SessionGuard and adding my own driver like so:
In config/auth.php:
'guards' => [
'user' => [
'driver' => 'extended_session',
'provider' => 'users',
],
'admin' => [
'driver' => 'extended_session',
'provider' => 'admins',
],
]
In AppServiceProvider.php
\Auth::extend('extended_session', function ($app, $name, $config) {
$providerConfig = $this->app['config']['auth.providers.'.$config['provider']];
// If you don't use eloquent you need to alter the next line accordingly
$provider = new EloquentUserProvider($app['hash'], $providerConfig['model']);
return new SessionGuardExtended('extended_session', $provider, $this->app['session.store']);
});
And add a new Class named SessionGuardExtended like this:
use Illuminate\Auth\SessionGuard;
class SessionGuardExtended extends SessionGuard{}
This results in a shared session with the same auth name for domain and subdomains.
Add SESSION_DOMAIN to your .env file and set it to .example.com
Implementing single sign on in my laravel application. I have decided to use this plugin https://github.com/aacotroneo/laravel-saml2 which is basically a wrapper on famous SimpleSamlPhp.
I downloaded the code via composer and as per given information Remember that you don't need to implement those routes, but you'll need to add them to your IDP configuration. For example, if you use simplesamlphp, add the following to /metadata/sp-remote.php
$metadata['http://laravel_url/saml/metadata'] = array(
'AssertionConsumerService' => 'http://laravel_url/saml/acs',
'SingleLogoutService' => 'http://laravel_url/saml/sls',
//the following two affect what the $Saml2user->getUserId() will return
'NameIDFormat' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',
'simplesaml.nameidattribute' => 'uid'
);
I can't find metadata/sp-remote.php, any idea? and as far as http://laravel_url/saml/acs is concerned, do I need to deploy saml on the server? because at the moment the plugin code is in vendors in laravel core architecture code hierarchy.
First some background:
There are two parts to any SAML interaction - the Identity Provider ("IDP") and the Service Provider ("SP"). The IDP is the master authenticator if you like, to which various applications (SPs) connect.
The idea is that the user visits your app, which in turn communicates as a Service Provider to the Identity Provider to get your credentials. And because multiple apps / SPs connect to the same IDP, you get the benefits of a single sign-on.
During the set-up phase, metadata configurations are swapped between the SPs and IDP to establish trust between them. This isn't user-level data -- it's application-level data that allows them to talk.
OK. So now on to your question:
The package you are using allows your Laravel app to talk to an IDP, but before it can do so you need to swap some metadata. The metadata for your app is the snippet above. This needs to go in the IDP configurations, which is where you will find this metadata/sp-remote (or more precisely metadata/saml20-sp-remote, which is where you paste this in.
If you haven't done so already, I'd recommend using [https://simplesamlphp.org/docs/stable/][1] as the IDP here as the Laravel package works with it pretty much out of the box.
One final tip: if you are using SAML2, then I found that you need to change the metadata key to refer to saml2 instead of saml above. ie $metadata['http://laravel_url/saml2/metadata'] and not $metadata['http://laravel_url/saml/metadata']
I hope this will help others. I added saml2_settings.php in the config folder.
Updated the routes:
'logoutRoute' => '/logout',
'loginRoute' => '/homepage',
'errorRoute' => '/error',
updated x509cert (publickey.cer) and privateKey
Updated 'entityId', added the url of metadata xml.
Updated singleLogoutService and rest of the required details in the saml2_settings.php file.
Added two listeners
1) for login event
2) for logout event
Updated the routes file like this:
\Illuminate\Support\Facades\Event::listen('Aacotroneo\Saml2\Events\Saml2LogoutEvent', function ($event) {
\Illuminate\Support\Facades\Auth::logout();
\Illuminate\Support\Facades\Session::save();
return redirect("login");
});
\Illuminate\Support\Facades\Event::listen('Aacotroneo\Saml2\Events\Saml2LoginEvent', function (\Aacotroneo\Saml2\Events\Saml2LoginEvent $event) {
$user = $event->getSaml2User();
$userData = [
'id' => $user->getUserId(),
'attributes' => $user->getAttributes(),
'assertion' => $user->getRawSamlAssertion()
];
// add the login for auto login based on your settings
/// REDIRECT the user to homepage
}
});
I wrote an API using Yii2 and following the REST guide. My API is working and I want to write some tests for it, so I once again followed the guide on how to run tests and got unit tests working. I then looked around Codeception documentation about testing WebServices and got this working too.
My problem is that API calls are not using my test database. I have two databases, one called db and the other testdb. Here is my config.php file in tests/codeception/config/:
return [
'components' => [
'db' => [
'dsn' => 'mysql:host=localhost;port=8889;dbname=testdb;unix_socket=/Applications/MAMP/tmp/mysql/mysql.sock',
],
'mailer' => [
'useFileTransport' => true,
],
'urlManager' => [
'showScriptName' => true,
],
],
];
I wrote a simple test that send a GET request to an endpoint to retrieve data. My test database is empty so I am expecting to receive an empty response, but I get the content of my other database instead.
I then tried to set YII_ENV to test as described in the Environment Constant section here so that I could test against the env variable YII_ENV_TEST and change the db configuration accordingly. I tried to set this variable in the _bootstrap.php file in the tests/codeception/ folder:
defined('YII_ENV') or define('YII_ENV', 'test');
I then logged the value of YII_ENV in the web/index.php file (index-test.php is not called, might be a problem too), and it is undefined.
What am I doing wrong? I tried including the Yii2 module in my api.suite.yml file but requests don't have return code anymore if I do that, it returns N/A. Is there another way to change which database Yii should use?
You can make an test_config.php file and at the end of the config place this
if (file_exists('protected/config/test_config.php'))
{
include 'test_config.php';
}
the file will be included if it exists. And the file test_config.php should contain the overwritten value for the db connection.
Hope this helps!
Keep on coding!
Ares.
Well I found a "solution" by using this other app template: https://github.com/githubjeka/yii2-rest
The file organization fits my needs better and I can easily configure which database to use.