I need to update a value which is initially set in the main.js for my vue application, from a component. I am not sure the best way (or even if this is possible)
I have tried setting the value directly form the component, but it does not appear to update.
I would be happy with just having it set properly when the app starts. I only need this to be set once, but I want it to read the server/host info when the app starts and populate the value.
Vue.use(Adal, {
// This config gets passed along to Adal, so all settings available to adal can be used here.
config: {
// 'common' (multi-tenant gateway) or Azure AD Tenant ID
tenant: 'xxxxxxxxxxxxxxxxxxxxxxxxx',
// Application ID
clientId: 'xxxxxxxxxxxxxxxxxxxxxxx',
// Host URI
redirectUri: 'http://localhost:8080',
cacheLocation: 'localStorage'
},
// Set this to true for authentication on startup
requireAuthOnInitialize: false,
// Pass a vue-router object in to add route hooks with authentication and role checking
router
});
The redirectUri value I would like to be dynamic based on the URL that the user used to connect to the site. This is part of the adal-vue library to handle AzureAD Auth for my App.
It appears that this value is only set ONCE and cannot be modified on the fly. Is there a workaround to allow for this?
I don't know what you do in Adal.install function, I think you can try to declare an option object which is passed to Vue.use(), then you can change the value in option, as it is passed by reference, the value will be changed in Adal...
const option = {
config: {
redirectUri: 'http://localhost:8080',
}
Vue.use(Adal, option);
// then change it in somewhere
option.config.redirectUri = 'http://localhost:9000'
Related
I am having trouble getting dependency injection working for my AuthorizerService. Obviously, dep-inj is not ready until after Aurelia "starts", but I wasn't sure how to access it.
main.js:
aurelia.container.registerInstance(HttpClient, http.c());
// set your interceptors to take cookie data and put into header
return aurelia.start().then(() => {
let Authorizer = new AuthorizerService();
aurelia.container.registerInstance(AuthorizerService, Authorization);
console.log('Current State: %o', Authorizer.auth);
Authorizer.checkCookieAndPingServer().then(() => { console.log('Current State: %o', Authorizer.auth); aurelia.setRoot(PLATFORM.moduleName('app')); }, () => { aurelia.setRoot(PLATFORM.moduleName('login-redirect')); });
});
Now the problem is that if I do "new AuthorizerService()" then "this.http.fetch()" is not available in AuthorizerService.js.
Am I meant to pass "http.c()" (which delivers the HttpClient instance) as a parameter inside:
checkCookieAndPingServer(http.c())
or is there another way?
Can I delete "new AuthorizerService()" and just do (I made this up):
aurelia.container.getInstance(AuthorizerService);
Somehow FORCE it to do dependency-injection and retrieve the "registered Instance" of "http.c()"?
I can't just check cookie. I have to ping server for security and the server will set the cookie.
I think this is all sorts of wrong, because I need a global parameter that just is false by default, then it does the query to backend server and setsRoot accordingly. Perhaps only query backend in the "login page"? Okay but then I would need to do "setRoot(backtoApp); aurelia.AlsoSetLoggedIn(true);" inside login module. But when I setRoot(backtoApp) then it just starts all over again.
In other words, when setRoot(login); then setRoot(backToApp); <-- then AuthorizerService instance doesn't have its proper data set (such as loggedIn=true).
EDIT: Better Solution maybe:
main.js:
return aurelia.start().then(() => {
let Authorizer = aurelia.container.get(AuthorizerService);
let root = Authorizer.isAuthenticated() ? PLATFORM.moduleName('app') : PLATFORM.moduleName('login');
console.log('Current State: %o', Authorizer.auth);
aurelia.setRoot(root);
});
Authorizer.js
constructor(http) {
this.http = http;
this.auth = {
isAuthenticated: false,
user: {}
}
}
"this.auth" is no longer static. No longer "static auth = { isAuthenticated: false }" which was some example code I had found.
So now "auth" gets set inside "login" module. But this means the "login" module is displayed every single time the app loads briefly, before being redirected back to "setRoot(backToApp)"
If the class you want to get the instance is purely based on service classes and has no dependencies on some Aurelia plugins, it doesn't need to wait until Aurelia has started to safely invoke the container.
For your example:
aurelia.container.getInstance(AuthorizerService);
It can be
aurelia.container.get(AuthorizerService);
And you should not use new AuthorizerService(), as you have noticed in your question.
I'm using Axios in my VueJS application and I want to add a default GET param in my request. I send my API-KEY through the URL ?api-key=secret and I don't want to specify this parameter each time.
I see in the documentation that we can set Global custom defaults. With that we don't have to specify the header each time. But can we do the same for get param ?
I struggled to get this to work with axios instances using the two most commonly suggested methods:
// method 1: setting axios.defaults.params at the class level
axios.defaults.params = {}
axios.defaults.params['api-key'] = secret
and
// method 2: setting the `params` attribute at an instance level
const axClient = axios.create({
baseURL: process.env.VUE_APP_BASE_URL,
params: {
api-key: process.env.VUE_APP_API_KEY
}
});
I did however, manage to get it working nicely using interceptors like this:
// create an instance with default properties
const axClient = axios.create({
baseURL: process.env.VUE_APP_BASE_URL,
});
axClient.interceptors.request.use((config) => {
// use config.params if it has been set
config.params = config.params || {};
// add any client instance specific params to config
config.params['api-key'] = process.env.VUE_APP_API_KEY;
return config;
});
The benefit of this approach is that the instance level params can be dynamic/computed per request if needed.
As a (slightly contrived) example, if you needed to add a JWT to each request (including any logic to fetch it from your storage method of choice) and even react to the logic around that. So in this toy example, if the user doesn't have a JWT in storage, redirect them to the login page instead of making the request.
Here it is:
axios.defaults.params = {}
axios.defaults.params['api-key'] = secret
If you need to call a function before each axios request, you should use an interceptor.
Is there a way to change the Apollo endpoint after having created the Apollo client? I would like to have the user to input their own endpoint.
httpEndpoint can be a function, and it is called on each query.
As #wrod7 mentioned, you could use localStorage, but global variable should be enought
// vue-apollo.js
export { defaultOptions }
// main.js
import { createProvider, defaultOptions } from './vue-apollo'
window.apolloEndpoint = defaultOptions.httpEndpoint
new Vue({
router,
apolloProvider: createProvider({
cache,
httpEndpoint: () => window.apolloEndpoint,
}),
render: h => h(App),
}).$mount('#app')
and you can set apolloEndpoint anywhere you like, i am using window. to make eslint happy
httpEndpoint is called with current query, so you can conditionally return endpoint based on operationName
vue-apollo got support for multiple clients, it might be useful if you want to override endpoint only on some queries, but i thinks this offtopic
I am doing this on one of my applications. I store the URL string in localstorage or asyncstorage on mobile. you can check for the string when the app loads and have the user enter one if there isn't a url string stored. the application would have to refresh after entering the url and saving it to localstorage.
In the main.js file i have set the vue resource to use auth headers with every requests:
Vue.use( VueResource )
let auth = validToken()
if( auth ) {
Vue.http.interceptors.push( ( request, next ) => {
request.headers.set( 'Authorization', auth.token )
request.headers.set( 'Accept', 'application/json' )
next()
} )
}
And in the logout, i am trying to delete the header this way,
resetVueRsr: () => {
this.$http.headers.common['Authorization'] = null
}
And when a user log in, then resetting the new token to the global Vue resource like this,
this.$http.headers.common['Authorization'] = res.body.token
But once a new user is logging in the site, the vue resource still sending previous token with each request. What i am missing here?
I checked the source, and it looks like all defined interceptors are added in some internal array, and then used for requests.
According to your code sample, you obtain an object with initial token somehow and then pass it inside your arrow function, so JS creates a closure for this to make this object available inside the function, and I think a lifetime of this closure is equal to a lifetime of your app. I assume that you have a sort of SPA.
Also from the source it looks like interceptors are not related to common headers, so your way of deleting and resetting won't change your interceptor.
I am just getting started with Durandal.js so excuse me for the silly quesstion...
When a user makes it's first request to the app it is asked to choose a 'profile kind', and I need it to be accessible to every other view model in the web site, I first though of creating this property in the shell viewmodel, but don't how to do it.
How is the best way to store data in a Session like mode in a Durandal SPA?
Thanks!
Create an amd module for what data you need to store.
Then just require that module as a dependency for whatever other modules that need it.
Sort of like this:
session module
define(function () {
return {
someVariable: 'value1',
someVariable2: 'value2'
}
})
some other module
define(['session'], function(session) {
return {
getValue1: function () {
return session.someVariable;
},
obs1: ko.observable(session.someVariable2)
}
})
EDIT**
AMD modules are there to not pollute the global namespace of the window object. But if you would rather not require your session as a dependency and just access it through a global variable then that is perfectly fine.
you can declare it in your shell.js if you would like and do something like:
define(function () {
window.session = { someVariable: 'value1', someVariable2: 'value2' };
})
then inside some other module you can access the session object like so:
define(function() {
return {
getValue1: function () {
return session.someVariable;
},
obs1: ko.observable(session.someVariable2)
}
})
This information will not be persisted between page refreshes.. its only in-memory.
If your looking to persist the session data I would not look into persisting any information on the client unless you planned on making your app an off-line application.
An offline application is an app that works even w/out internet access. But if your app requires that the user is always connected to the internet then I would just store the session data on the server. So, just use web services to persist the session data and retrieve it.
You can tie the session on the server to the client by using a cookie.
As an alternative to Evan's answer, which is definitively the correct AMD approach... have you considered using a global object for that purpose?
in main.js
window.myApp = {
prop1: 'value',
subOne: {
prop1: 'value'
}
...
}
That will allow you to access the global myApp object everywhere. I know that some people will consider that as global namespace pollution and in general a bad practice, but in a SPA project (where you control window) I'd consider this still a viable approach.