What is the database password of a tenant's database (Laravel Hyn) - multi-tenant

I have deployed a multi-tenant site on the server and I'm using Laravel Hyn (5.6). I am able to create tenant's database. But I wonder what is the password used to create the tenant's database. I'm asking this because if ever we need to check on a tenant's database, how can we access it? And I'm trying to access it remotely. I can get into the app's main database which holds the tenant's database name. But I don't know how to access the tenant's actual database because I don't know what password Hyn assigned to it.
Checking Laravel Hyn's docs, It doesnt mention anything about it.

The functionality you are looking for is in class Hyn\Tenancy\Generators\Database\DefaultPasswordGenerator function generate
Possibly if we can adapt this functionality to come up with a command that accepts the database name and returns the password. We can come up with something like this
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Hyn\Tenancy\Models\Website;
use Hyn\Tenancy\Contracts\Website as WebContract;
class GeneratePassword extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'password:generate {--database=}';
/** php artisan password:generate --database=6003c07826144979a4176b3290963ba3
* The console command description.
*
* #var string
*/
protected $description = 'Command description';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return int
*/
public function handle()
{
$database=$this->option('database');
$website =Website::where('uuid', $database)->first();
$password=$this->generate($website);
$this->info('password :'.$password);
return 0;
}
/**
* #param Website $website
* #return string
*/
private function generate(WebContract $website) : string
{
$key = config('tenancy.key');
// Backward compatibility
if ($key === null) {
return md5(sprintf(
'%s.%d',
$this->app['config']->get('app.key'),
$website->id
));
}
return md5(sprintf(
'%d.%s.%s.%s',
$website->id,
$website->uuid,
$website->created_at,
$key
));
}
}
You will now be able to generate passwords via artisan console for example
php artisan password:generate --database=6003c07826144979a4176b3290963ba3
Use the generated password to connect to your database using tenant credentials (username is the same as database name).

Related

Laravel 8 enable maintenance mode permanently

I am using this command to enable maintenance mode php artisan down --secret="1630542a-246b-4b66-afa1-dd72a4c43515.
And then, I access my site with exapmple.com/1630542a-246b-4b66-afa1-dd72a4c43515, to bypass the maintenance mode.
However, it seems to only work for one browsing session. That is, when I restart the computer, the maintenance cookie seems to be deleted and my site shows the 503 error.
So, how can I set an infinity lifetime maintenance cookie?
1. Override Create method from MaintenanceModeBypassCookie class. For this we will create a new file /App/Http/MaintenanceModeByoassCookie.php where we will include the following:
<?php
namespace App\Http;
use Illuminate\Support\Carbon;
use Symfony\Component\HttpFoundation\Cookie;
class MaintenanceModeBypassCookie extends \Illuminate\Foundation\Http\MaintenanceModeBypassCookie
{
/**
* Create a new maintenance mode bypass cookie.
*
* #param string $key
* #return \Symfony\Component\HttpFoundation\Cookie
*/
public static function create(string $key)
{
$expiresAt = Carbon::now()->addHours(1000);//Time expiration for your cookie
return new Cookie('laravel_maintenance', base64_encode(json_encode([
'expires_at' => $expiresAt->getTimestamp(),
'mac' => hash_hmac('sha256', $expiresAt->getTimestamp(), $key),
])), $expiresAt);
}
}
Note where we are overriding the expiration time for the cookie.
2. Add the following code in your /App/Http/Middleware/CheckForMaintenanceMode.php in order to override bypassResponse method:
/**
* #override
* Redirect the user back to the root of the application with a maintenance mode bypass cookie.
*
* #param string $secret
* #return \Illuminate\Http\RedirectResponse
*/
protected function bypassResponse(string $secret)
{
return redirect('/')->withCookie(
\App\Http\MaintenanceModeBypassCookie::create($secret)
);
}

Run external command via Laravel Artisan Console

I'm looking to execute psexec from Laravel to execute some remote command and I'd like to use the Artisan Console to do so (for now). Ideally, I'd like to navigate to a url and the command would be issued (something i'd implement after this initial stage).
What I have so far is:
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class RestartSplunk extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'splunk:restart {host}';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Restart Splunk instance on given host';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
$host = $this->argument('host');
$bar = $this->output->createProgressBar();
if ($this->confirm('Are you sure you\'d like to restart ' . $host )) {
$this->info('Restarting ' . $host . '...');
}
}
}
If someone has implemented this or can share some resources to accomplish this it'd me much appreciated.
I have found my answer The Process Component in Symphony.

Custom laravel migration command "[Illuminate\Database\Migrations\MigrationRepositoryInterface] is not instantiable"

I'm trying to create a custom laravel (5.2) migration command that basically works the same as migrate:status except it just lists the pending migrations instead of all the migrations.
To do this i've very simply copied the migrate:status into another class within my app/console directory and adjusted the code to suit my needs. However whenever I try to run it I get an error:
[Illuminate\Contracts\Container\BindingResolutionException]
Target [Illuminate\Database\Migrations\MigrationRepositoryInterface] is not instantiable while building [App\Console\Commands\PendingMigrations, Illuminate\Database\Migrations\Migrator].
The contents of the class itself and the fire() method doesn't seem to matter as it doesn't get that far, it fails within the __construct() method.
<?php namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Database\Migrations\Migrator;
class PendingMigrations extends Command
{
/**
* The console command name.
*
* #var string
*/
protected $name = 'migrate:pending';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Shows a list of pending migrations';
/**
* The migrator instance.
*
* #var \Illuminate\Database\Migrations\Migrator
*/
protected $migrator;
/**
* Create a new migration rollback command instance.
*
* #param \Illuminate\Database\Migrations\Migrator $migrator
* #return \Illuminate\Database\Console\Migrations\StatusCommand
*/
public function __construct(Migrator $migrator)
{
parent::__construct();
$this->migrator = $migrator;
}
/**
* Execute the console command.
*
* #return void
*/
public function fire()
{
}
}
The reason for it is likely to be something to do with the IoC container and the order with which things are loaded, but I don't know enough about the inner workings of Laravel to figure out any more than that.
It surely must be possible?
I am currently stuck on 5.2, so i'm not sure if this problem exists in more recent versions.
The only thing i've attempted so far is added the migration service provider to the top of the list in config/app.php however it didn't seem to have an affect and it was just a random guess anyway.
providers' => [
Illuminate\Database\MigrationServiceProvider::class,`
]
I got around this using:
$this->migrator = app('migrator');
but it is not necessarily the best way to do this
The Migrator instance is not bound to the class name in the IoC container, it is bound to the migrator alias.
From Illuminate\Database\MigrationServiceProvider:
/**
* Register the migrator service.
*
* #return void
*/
protected function registerMigrator()
{
// The migrator is responsible for actually running and rollback the migration
// files in the application. We'll pass in our database connection resolver
// so the migrator can resolve any of these connections when it needs to.
$this->app->singleton('migrator', function ($app) {
$repository = $app['migration.repository'];
return new Migrator($repository, $app['db'], $app['files']);
});
}
Since the class name is not bound in the IoC container, when Laravel resolves your command and attempts to resolve the Migrator dependency, it attempts to build a new one from scratch and fails because the Illuminate\Database\Migrations\MigrationRepositoryInterface is also not bound in the IoC container (hence the error you're receiving).
Since Laravel can't figure this out itself, you need to either register the binding for the Migrator class name, or you need to register the binding for your command. Laravel itself registers all the bindings for the commands in the Illuminate\Foundation\Providers\ArtisanServiceProvider. An example of the command.migrate binding:
/**
* Register the command.
*
* #return void
*/
protected function registerMigrateCommand()
{
$this->app->singleton('command.migrate', function ($app) {
return new MigrateCommand($app['migrator']);
});
}
So, in your AppServiceProvider, or another service provider you setup, you can add one of the following:
Register the command in the IoC:
$this->app->singleton(\App\Console\Commands\PendingMigrations::class, function ($app) {
return new \App\Console\Commands\PendingMigrations($app['migrator']);
});
Or, register the Migrator class name in the IoC:
$this->app->singleton(\Illuminate\Database\Migrations\Migrator::class, function ($app) {
return $app['migrator'];
});
As I don't want to register the migrator everywhere in the app, but I still want to extend the MigrateCommand itself, I came up with this approach to maintain my app as it is:
public function __construct()
{
app()->singleton(\App\Console\Commands\PendingMigrations::class, function ($app) {
return new \App\Console\Commands\PendingMigrations($app['migrator']);
});
parent::__construct(app('migrator'));
}

Laravel Artisan Console Command Cannot Retrieve Model Collection

I am trying to do some logic via a custom Console Command I created using Artisan but I am unable to use my model class and query using Eloquent.
When I use MyModel::all() it will return all records in a collection. This is great except the model I am using has too many records to load all of them into memory.
I am trying to use
MyModel::where('id',$currentLoopId)->get();
This returns an empty collection :(
My Console Class is as follows:
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\ProcessReferral;
use App\TargetUrl;
use App\Website;
class ProcessReferrals extends Command
{
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'process:referrals';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Process all outstanding records in process_referrals table';
protected $logArray = [];
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function handle()
{
$this->info('Start Processing Referrals');
$process_referrals = ProcessReferral::all();
$referral_count = count($process_referrals);
$this->info('Found '.$referral_count.' referral(s) that need processed');
foreach($process_referrals as $referral){
## 1. SEE IF REFERRAL WEBSITE IS ACTIVE AND VERIFIED IN AFFILIATE_WEBSITES. LOAD LAST FORCE UPDATE REFRESH CODES
########################################
$this->info('Processing Referral ID: '.$referral->id);
$this->info('Get Website from Affiliate Website Id: '.$referral->affiliate_website_id);
$websites = Website::where('id','=',$referral->affiliate_website_id)->get();
dd($websites);
... ( more Logic after I get website )
}
}
My Model Class is as follows:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Website extends Model
{
/**
* The table associated with the model.
*
* #var string
*/
protected $table = 'affiliate_websites';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
...
];
... ( Eloquent Relations )
}
Database Table:
id website_label referrals
------------------------------
1 Google UK 920685
2 Google U.S. 2940884
3 Google Germany 709603
First Dummy Data Record being processed:
id affiliate_website_id
-------------------------
2 3
Output on Terminal
$ php artisan process:referrals
Start Processing Referrals
Found 300 referral(s) that need processed
Processing Referral ID: 2
Get Website from Affiliate Website Id: 3
Website(id->62) is Active.
Illuminate\Database\Eloquent\Collection {#901
#items: []
}
I have tried a handful of different ways to query including DB::select() which returns what I am looking for but I cannot dynamically set the id I am searching for with that convention.
My Model works everywhere else in my application, I think there is some sort of Namespacing issue coming into play but I am at a complete loss as to why it wouldn't work.
Any help would be very appreciated!
As pointed out by #machuga on http://laravel.io/chat
I checked to see if the ID i was passing was an integer
$website = Website::where('id',(int)$referral->affiliate_website_id)->first();
Still had some issues but used ->first() to get a single record instead of ->get() so I dont have to loop over the Website collection

Laravel 4 artisan command not seeing binding

I created a command called AttachUsers. When I run the command I get
Argument 1 passed to AttachPhones::__construct() must be an instance of Acme\\Repositories\\Organizations\\OrganizationRepositoryInterface, none given, called in \/Users\/jonson\/sites\/acme\/app\/start\/artisan.php on line 5 and defined","file":"\/Users\/jonson\/sites\/acme\/app\/commands\/AttachPhones.php","line":30}}
I have bound my interface in the repositories service provider file AND it is currently woking in my controllers. My command file is as follows
<?php
use Illuminate\Console\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
use \Acme\Repositories\Organizations\OrganizationRepositoryInterface;
class AttachUsers extends Command {
protected $organizations;
/**
* The console command name.
*
* #var string
*/
protected $name = 'acme:attach_users';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Cron command to attach users from import to organizations';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct(OrganizationRepositoryInterface $organizations)
{
$this->organizations = $organizations;
parent::__construct();
}
You're probably calling Artisan::add(new MyCommand). Any time you use the "new" keyword, the IoC container is completely bypassed, and automatic dependency injection will not work. Instead, use Artisan::add(App::make('MyCommand')) or the shorthand, Artisan::resolve('MyCommand').

Resources