-
-
Notifications
You must be signed in to change notification settings - Fork 445
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Redirect on Login and Tenant Creation #194
Comments
So you want the users to be able to login on your central domain (i.e. |
Exactly. |
In |
And regarding the redirect on login, I'd have to see how you identify the tenant based on the user account. If the account exists both in your central app and inside the tenant app as some sort of superadmin, I think you should be able to use Laravel's auth inside the central app to see what tenant that user "is", and then you could probably use If the account exists only as part of the tenant table, this would be easier. Please share more information about your set up and I'll try to come up with some code you could use. |
@drbyte thanks for your answer. I know how to redirect after the registration but maybe I don't understand the package correctly. I don't have an app yet with this package. I want to create a saas app with this package, but I don't know how to use it the right way. Let me explain: At the moment I have another small saas app with a single-db multitenancy (I use this package https://github.com/romegadigital/Multitenancy) But I find the idea of your stancl/tenancy so much better because each tenant has it own db etc. How would you guys create a basic saas app? I know how to create a new tenant and run the migrations after that (set to true in config). But the registered user is then outside off the tenant or am I wrong? |
My Idea is to create a landing page where you create the tenant in the first step, than it runs the migration with the user table inside the tenant migration and in the second step the actual user registration happens. |
I see. I've added a feature that lets you do this to a dev branch yesterday, so when 2.2.0 is out, you will be able to do that even if the migration is queued. |
You are awesome! Thanks so much! |
Something like this works:
use RegistersUsers;
protected $redirectTo = '/login'; // default was /home
public function __construct()
{
$this->middleware('guest');
}
protected function validator(array $data)
{
return Validator::make($data, [
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255'],
'password' => ['required', 'string', 'min:7', 'confirmed'],
'domain' => ['required','unique:domains,domain'],
]);
}
public function register(Request $request)
{
$validated = $this->validator($request->all())->validate();
$domain = $request->input('domain');
// TODO: consider appending a tld suffix so the redirect makes sense
$user = (new \App\Services\TenantSetup)->createAndReturnUser($domain, $validated);
event(new Registered($user));
return $this->registered($request, $user)
?: redirect('https://' . $domain . $this->redirectTo);
}
namespace App\Services;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log;
class TenantSetup
{
public static function listTenants()
{
return tenancy()->all();
}
public function createAndReturnUser($domain, $requestFields)
{
config()->set('tenancy.migrate_after_creation', true);
config()->set('tenancy.seed_after_migration', true);
config()->set('tenancy.seeder_parameters', ['--class' => 'DatabaseSeeder']);
$tenant = \Stancl\Tenancy\Tenant::create($domain, ['id' => $requestFields['domain']]);
return $tenant->run(
function ($tenant) use ($requestFields) {
[$first] = explode(' ', $requestFields['name']);
$last = substr($requestFields['name'], strlen($first));
$user = \App\User::create([
'first' => $first,
'last' => $last,
'username' => $requestFields['email'],
'email' => $requestFields['email'],
'password' => Hash::make($requestFields['password']),
// OPTIONAL: 'primary_domain' => \strtoupper($requestFields['domain']),
]);
// @TODO: if assigning roles/permissions, do that here too
return $user;
}
);
}
} |
A saw the new release of 2.2.0. Is there any documentation or "best practice" how to use the package in a saas style app? For example: On the landing site (myapp.com) the user can register and login. When a new user signs up a new tenant gets created and the tenants migration runs with the user table and also the redirect to tenants dashboard happens. I know how to do that. But how do you guys manage the user? Dou you have two users tables? Inside the main app and inside the tenant? How is it possible to have a central login (myapp.com/login) with the correct redirect to the tenant domain when I have different user in the tenants user table? Do I have to loop trough all tenants do find the user email adress and redirect to this tenant domain? I hope you understand what I mean. |
When I was working on 2.2.0 I implemented this functionality into a test app like this: Central app's action to register the tenant: Tenant::new()->withDomains($domain)->withData([
'admin_fullname' => $request->post('name'),
'app_name' => $request->post('website_name'),
'email' => $request->post('email'),
'password' => Hash::make($request->post('password')),
'primary_domain' => $domain,
'post_registration_login_token' => $token,
'initial_migration_complete' => false,
])->save();
return redirect()->route('_post_tenant_registration', ['token' => $token])->tenant($domain); Tenant app: Route::get('_post_tenant_registration/{token}', 'DashboardController@postTenantRegistration')->name('_post_tenant_registration');
// Controller
public function postTenantRegistration(string $token)
{
if (! tenant('initial_migration_complete')) {
return view('errors.building'); // we're building your site-type view
}
if (tenant('post_registration_login_token') === $token) {
$user = User::where('email', tenant('email'))->firstOrFail();
Auth::login($user, true);
tenant()->deleteKey('post_registration_login_token');
}
return redirect()->route('admin.dashboard');
} AppServiceProvider: Tenancy::hook('database.creating', function (TenantManager $m, string $db, Tenant $tenant) {
return [
new AfterCreatingTenant($tenant->id)
];
}); AfterCreatingTenant job: $tenant = tenancy()->find($this->tenantId);
$tenant->run(function ($tenant) {
User::create(['name' => $tenant->admin_fullname, 'email' => $tenant->email, 'password' => $tenant->password, 'admin' => true]);
});
$tenant->deleteKey('admin_fullname');
$tenant->set('initial_migration_complete', true); Does this help? :) |
Thanks for your answer. This helps and thank you for for great package and support! But I still have one question. How to you handle the problem when a user forgot his subdomain? For example on Freshdesk (https://freshdesk.com/login) every user can enter his own email adress to get the subdomain. Thanks! |
You could do something like this: public function submitLogin(Request $request)
{
$this->validate($request, [
'email' => 'required|email',
]);
try {
$domain = tenancy()->findByEmail($email = $request->post('email'))->primary_domain;
} catch (TenantCouldNotBeIdentifiedException $e) {
return redirect()->back()->withInput()->withErrors(["No website is associated with email $email."]);
}
return redirect()->route('admin.dashboard')->tenant($domain)->with('email', tenant('email'));
} |
But that would only work with the user how created the tenant, right? Because that email is stored within "withData" or does this search trough the tenants user tables? |
This only searches in the tenant data. Searching in tenant databases comes with more complexity because the same email address can exist in multiple databases. |
I created a function wich search inside the tenants databases for the users email. I am just a developer in my spare time, but at least this code works for me.
|
Sure, if it makes sense for your app to lookup users in tenant DBs, this is the how you'd solve it. |
Good night, I'm loving your package. Have a more detailed example? It is very well explained, but I don't know which instances, builders, I should start at the beginning of each file. Whenever I try to give a dump-autoload composer, the prompt raises an error .... Could you send an example already with the instances and the builders? |
What do you mean? The full class names? |
This comment was marked as off-topic.
This comment was marked as off-topic.
I know that this is old and all, but, will this still work on version 3 or do you have some sort of new implementation of this for version 3? |
You can now use the impersonation logic for this, the sponsor docs have a pretty much copy-pasteable example. |
Thank you for the quick response. I did the sponsorship and you have to forgive me but this what I can afford for now. Note: Sadly, there's a require tier for the docs :'( |
Hi,
first I have to say that your stancl tenancy is awesome!
But I have two question:
Is it the best way to create a tenant register controller and then runs all migration (like user table etc.) after registration? I know that I can activate it in the config file and I can also redirect to their domain after registration. But how can I redirect a user after login to their domain?
Thanks!
The text was updated successfully, but these errors were encountered: