I am trying to make the configuration for Pusher in my Laravel app (SaaS) dynamic.
Basically I want to store different Pusher configs for different accounts. And call the corresponding config based on the user.
I have tries to change the config in runtime using config()->set('services.pusher.xxx', 'yyyy'), but this doesn't work at any level of the framework, event in a custom ServiceProvider.
I found Laravel's BroadcastManager and tried to override the createPusherDriver() so that I could create a custom instance of PusherBroadcaster with the user's config, but I am not sure how to do that or where to put it!
What is the best-practice/standard way to do that?
I've been using a setup like this in one of my own projects, to set a custom mail config:
NOTE: Your mileage may vary due to the order in which service providers are loaded in your app.
Create a serviceprovider like app\Providers\ConfigProvider.php
public function boot()
{
$this->app->booted(function () {
$shouldSetCustomConfig = true;
// Set config values from database.
if($shouldSetCustomConfig) {
config([
'mail.host' => Config::get('mail.host'),
'mail.port' => Config::get('mail.port'),
]);
}
});
}
The $this->app->booted() is a simple callback that gets called after the application has been booted. This might not always work correctly because I've seen various packages that use this callback too to do various stuff. When this is the case, the order of registration matters. Note that it is not required to use this callback. One might simply call the config(['key' => 'newval']) directly and it could work as intended.
The service provider above should be loaded BEFORE the provider you are setting configuration for. In the example above it would be the Illuminate\Mail\MailServiceProvider::class. This should make sure the correct config is loaded.
Related
I do develop a little extension for a TYPO3 v10 where I need to gain access to the my extension-settings in a service class that extends \TYPO3\CMS\Core\Authentication\AuthenticationService.
My first attemp was to pass the settings using the DI configured in my Services.yaml according to: https://daniel-siepmann.de/concrete-typo3-dependency-injection-examples.html (Inject Extension Configuration)
However no matter what I do the settings array passed to my __constructor(array $settings) stays empty.
Then I tried to go for a more hacky attemp like:
public function __construct(array $settings)
{
$this->settings = $settings;
DebuggerUtility::var_dump($this->settings);
$configurationManager = GeneralUtility::makeInstance(\TYPO3\CMS\Extbase\Configuration\ConfigurationManager::class);
$typoscript = $configurationManager->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT);
DebuggerUtility::var_dump($typoscript);
die('debug');
}
But also loading the the full typoscript seems to fail since $typoscript is also null. Therefore I think that is has to do something with the AuthenticationService that my class extends? How can I gain access to my settings when extending TYPO3's AuthenticationService?
When the AuthenticationService is consulted for FE or BE login, typoscript is not available yet, as authentication happens early in the middleware stack (have a look at the order of the PSR-15 middlewares in the configuration module of the backend).
This is because typoscript is page dependend and whether you are eligible to access a page may be dependend on you login status or user roles.
So the question would be what kind of settings are you trying to access? You could use the site configuration (that is already loaded for authentication) or you could use global configuration in TYPO3_CONF_VARS that is always available.
I want to make boot function for my app preview, for that I have plan to add new variable to .env file and let's name it APP_Mode so I want to say:
If APP_Mode=preview prevent all actions and redirect back with
xxxxxx text as flash session message.
The point
The point of this boot action that I try to achieve is to not let users change any of my preview site settings like store/delete/update etc.
Question
Is that possible? How?
First off, might be worth considering if Laravel's maintenance mode might work for you - you can whitelist the IP addresses that are able to access the site, and it will appear down for everyone else.
If that's not going to do the trick, you'll probably be best to create your own middleware - it will likely be similar to the CheckForMaintenanceMode middleware that Laravel ships with. In the handle method you can check for the configuration option to see if you're in preview mode or not, and then decide how to handle the request.
If you're using "RESTful" routing like Laravel recommends - that is, GET requests are idempotent and don't change anything, and only POST/PUT/DELETE requests make changes - your middleware can simply return a HTTP 403 response (forbidden) if your preview mode is enabled and the request method isn't GET.
A very simple implementation (you'll likely need to tweak) to get you started would be something like this:
public function handle($request, Closure $next) {
if (config('app.mode') === 'preview' && $request->method() !== 'GET') {
abort(403);
}
return $next($request);
}
Just in regard to using config('app.mode') instead of something env('APP_MODE') is that you shouldn't be using the env helper outside of the configuration files - otherwise you can't take advantage of Laravel's config caching. So add another config option in the config/app.php file that you can use to check the mode the app is in.
I'm having a few issues with registering a Laravel service provider. In the sense that the service provider is always gets registered, even when it shouldn't.
I'm using composer require laravel/telescope --dev and looking at their docs. You can do an if statement within AppServiceProvider.php to allow this to register on occasion, in this sense I want only to register if the app has debug enabled.
I created the method.
protected function hasDebug()
{
return config('app.debug');
}
This returned whether or not debug is set within the env. I then have the following if statement within my register method.
public function register()
{
if ($this->hasDebug()) {
$this->app->register(TelescopeServiceProvider::class);
}
}
However, even when I have not enabled debugging (I can see this by doing dd($this-hasDebug()) it will return false. Everything to do with Telescope is being provided. I can still access routes, whereas realistically I do not want to be able to access anything to do with Telescope.
Can someone point out where I'm going wrong?
For anyone else who is having this issue, this is how to correct it.
The issue was to do with auto discovery within composer. It was always picking up Telescope therefore always registering it.
Although all of the logic was correct within my AppServiceProvider because it was registering it was basically ignored.
Inside of composer.json, I added this...
"extra": {
"laravel": {
"dont-discover": [
"laravel/telescope"
]
}
},
Change "app.debug" to APP_DEBUG. The config helper pulls the mappings directly from your .env file.
I have a project that is sharing much of the same functionality across multiple clients use, each with their own sub-domain to access and use. For each instance, I'd like to add the odd bit of additional formatting or information to some views and was hoping to check whether a file exists upon rendering the view.
For example:
Let's say I have three different instances of the product (so three subdomains) and when a user logs in they view /dashboard by default. If the view is rendered from views/dashboard.blade.php, I'd like to check whether there is a file called views/subdomain.dashboard.blade.php and if so, use that as the view instead. I'm thinking this may be possible using the View Composer but not entirely sure how as still getting up to speed with Laravel.
You can make a helper for that.
if (!function_exists('subdomain_view')) {
function subdomain_view($view = null, $data = [], $mergeData = [])
{
$subdomain = request()->route()->parameter('subdomain');
$altView = "{$subdomain}.{$view}";
return view(
view()->exists($altView) ? $altView : $view,
$data,
$mergeData
);
}
}
It gets the subdomain, prefixes it to the view name, check if the prefixed view exists. If it does it uses that view, otherwise it uses the original view. It also uses the same signature as the view() helper.
Note that it makes use of the request() and and view() helpers without parameters. The default behavior of these helpers when called without parameters is to return the an instance of Illuminate\Http\Request and Illuminate\Contracts\View\Factory, respectively.
Another way to make this work is to provide your own implementation of Illuminate\View\ViewFinderInterface. You can check the Illuminate\View\FileViewFinder class that implements this interface. You can just subclass from it and override the find() method. Then register the new class.
Update: You don't need to even subclass FileViewFinder, just tweak how FileViewFinder is registered inside the service provider. Other solutions include adding view namespaces. See here.
I am working on a new website being built in SilverStripe. Currently I am having a ton of trouble trying to get the system to let me change the URL alias (or create a second one) for the Security controller's login (and eventually logout) function.
I have tried playing around with the routes.yml file and I tried creating the paths in my own UserController and loading directly from the Security controller with "return Security::login()". But that gives me errors about the use of the static functions.
Unfortunately I don't come from a ton of object oriented experience and this is the first CMS I have used that actually uses a bunch of true object orientation. The current version of SilverStripe we are using is 3.0 (but we will be upgrading to 3.1.1 in a few days).
Does anyone know much about the routing in SilverStripe?
as you stated correctly, SilverStripe has routes, and they can be defined in a yaml config file.
if you take a look at the existing routes.yml in the framework you can see how the default security route is defined:
https://github.com/silverstripe/silverstripe-framework/blob/fd6a1619cb7696d0f7e3ab344bc5ac7d9f6cfe77/_config/routes.yml#L17
if you just want to replace the Secuirty in Secuirty/login, its as easy as just creating your own routes.ymlin mysite/_config/ with the following content:
---
Name: myroutesorsomeotherrandomname
Before: '*'
After:
- '#rootroutes'
- '#coreroutes'
- '#modelascontrollerroutes'
- '#adminroutes'
---
Director:
rules:
'foobar//$Action/$ID/$OtherID': 'Security'
NOTE: make sure you ran a ?flush=1 to ensure the yml file is loaded (they get cached)
also make sure you use spaces in the yml file, if you use tabs you are going to have a bad time
if you however wish to also replace /login and /logout this is no longer a thing for routing.
login and logout are actions (php functions that are listed in Security::$allowed_actions and thus available as URL) on the on Security.
but its still rather easy, just subclass Security and create the actions you want:
<?php
class MySuperSecurity extends Security {
private static $allowed_actions = array(
'showMeTheLoginForm',
'alternative_login_action_with_dashes',
'doTheLogout',
);
function showMeTheLoginForm() {
// can be visited via http://website.com/foobar/showMeTheLoginForm
return $this->login();
}
function alternative_login_action_with_dashes() {
// can be visited via http://website.com/foobar/alternative-login-action-with-dashes
return $this->login();
}
function doTheLogout($redirect = true) {
// can be visited via http://website.com/foobar/doTheLogout
return $this->logout($redirect);
}
}
and make the route point to your new class instead of Security inside the routes.yml:
'foobar//$Action/$ID/$OtherID': 'MySuperSecurity'
NOTE: again, make sure you did a ?flush=1, both the private static $allowed_actions as well as the yml config file are cached by silverstripe.
NOTE: both solutions suggested in this post will create an additional route to login and does not replace the existing one, so the old Security/login will still be available
I don't know nothing about SilverStripe excepting that is a CMS, but i think SilverStripe must provide a way to aliases Url. Also an alternative is create Alias in virtual host definition if you're using apache or in .htaccess file. Refer to apache doc to further details. If you post a skeleton of your .htaccess file or VirtualHost definition i could help you.