PermissionBasedRouting VueJS - vue.js

I am trying to give access to the teams with multiple users. Unfortunatly other users are also able to view the VueComponents. The Vue code runs perfectly but other users, who are not in team 'admins' are able to see the components. Also, the console prints teamName as 'admins' even the current logged user is not part of the team. For example the current user is 'test' user which is not part of admin teams but the console prints 'admins'. please see the image console output, contains teamsList with users.
Vue file
this.loadTeams()
.then((response) => {
this.teamsList = response.data;
console.log("teams list after loadteams", this.teamsList);
this.teamsList.forEach((item) => {
if (item.teamName === "admins") {
this.haveAccess = true;
console.log("teamName is :", item.teamName);
}
});
})
router file
router.beforeEach((to, from, next) => {
// condition for teams to access administration page
if (to.meta.haveAccess && store.getters("administration/teams", ["teamsList"])) {
this.teamsList.forEach((item) => {
if (item.teamName === "admins") {
next({
name:'Administration',
params: {
desiredRoute: to.fullPath
}})
}
else {
router.push({
name:'NotFound'
})
}
});
}
});

Related

How can i make sure a vuex action has finished before the page loads

I have 2 issues where i pull data from an api and use it. However, the page loads before the api request has completed.
My first problem is in the router. I have a requiresAuth, to check if i'm logged in, i have the following:
router:
router.beforeEach((to, from, next) => {
if (!to.matched.some(record => record.meta.requiresAuth)) return next(); // does not require auth, make sure to always call next()!
if (store.getters.isLoggedIn) return next();
store.dispatch('pullUserInfo').then(() => {
if (store.getters.isLoggedIn) return next(); // logged in, move it
next({
path: '/login',
{ redirect: to.fullPath } // save the location we were at to come back later
});
});
});
store action:
pullUserInfo(context) {
fetch(`${process.env.VUE_APP_API_ENDPOINT}/v3/user`)
.then(async r => {
if (r.status !== 200) return context.commit('setUserInfo', null);
const json = await r.json();
context.commit('setUserInfo', json);
});
},
app constructor:
createApp(App)
.use(router)
.use(store)
.mount('#app-mount');
When refreshing, checking in devtools, my userInfo object has data. However this data is set after router.beforeEach checks
My second issue is similar. I populate a table with data from the store, however when refreshing the store value is null because the api request is still ongoing
How do i wait for my action to complete and assure data is present before continuing?
I am using the latest vuex, vue-router and vue3. Working with SFC's and initialized with vue cli
Returning fetch()'s promise did the trick.
This answer was given in the official Vue Discord server
pullUserInfo(context) {
return fetch(`${process.env.VUE_APP_API_ENDPOINT}/v3/user`)
.then(async r => {
if (r.status !== 200) return context.commit('setUserInfo', null);
const json = await r.json();
context.commit('setUserInfo', json);
});
},

Vue.js Routing shows 404 error message briefly before redirect after auth check

I have followed a number of posts' guidance on Stack Overflow and other websites about setting up Vue routes to check for user authentication. The setup I now have does essentially work correctly (for each route, the user authentication status is checked, and redirected to the login page if necessary) but there is a small issue in that just before the user is redirected, the standard Nuxt/Vue 404 page screen flashes up momentarily.
This is an example of each route that requires user authentication that I have in router.js:
...
{
path: '/question/:id/comments',
name: 'comments',
component: page('Comments.vue'),
meta: {requiresAuth: true},
beforeEnter: (to, from, next) => {
guard(to, from, next);
}
},
...
And here is my guard() function that checks the user authentication and then redirects them with next() as required:
const guard = function(to, from, next) {
axios.get(process.env.apiUrl + 'check-auth').then(response => {
if( to.matched.some( record => record.meta.requiresAdmin ) ) {
if( response.data.is_moderator !== 1 ) {
next({ path: '/' });
} else {
next();
}
} else if( to.matched.some( record => record.meta.requiresAuth ) ) {
if( !response.data.id ) {
next({
path: '/login',
params: { nextUrl: to.fullPath }
});
} else {
next();
}
} else {
next();
}
});
};
Many articles online suggested using localStorage to check the user authentication but this doesn't work in router.js (presumably because its server side and not client side) but I got around this using a Laravel API call with Axios to check it instead.
If anyone can shed any light on why the 404 screen flashes up first before the redirect? Going to the routes directly works fine, so I am guessing it must be something to do with the next() method.

Avoiding Wix members confirmation emails or changing the sending address

I am working with a client who runs a BtoB. We have set up Member Accounts and some member roles to secure sensible information to which they would have access once approved. However, we are running with an issue that is driving me completely crazy: as Wix’s default registration process rules, once someone signs up and we approve Member Access, an email is sent to their account with a token to confirm their email.
Even though we have an email integrated with Wix with our domain, both the confirmation emails and password reset (sent after a user clicks on “forgot my password”), are not being sent from that address, but from some stupid #site-members.com address.
sender address
My client’s clients all use business emails, and most of their servers are completely blocking these emails. Therefore, they are not being able to complete the registration process and never get to login.
After trying to talk to Wix’s support - which was a complete waste of time - I started scouting the internet and found a tutorial for sending Triggered Emails as confirmation emails. I tried it and it seems to work, however, even though the Triggered Email is set to be sent from my account, it adds a via something:
via ascendbywix
Aaaand.. Guess what! After doing some testing, these get blocked as well in many servers.
So, I don’t know what else to do! Can somebody please help me to either avoid sending confirmation emails at all, or to see if there is any other way to set the email address sending those using Corvid or the Wix dashboard?
Just in case you want to see the code, there are three parts to it:
REGISTRATION LIGHTBOX
import wixWindow from 'wix-window';
import wixData from 'wix-data';
import { doRegistration } from 'backend/register';
let registration;
$w.onReady(function () {
$w("#register").onClick((event) => {
console.log("Button was clicked");
$w("#errorMessage").collapse();
$w("#emailExists").collapse();
if ($w("#email").valid && $w("#password").valid && $w("#company").valid && $w("#name").valid) {
registerPerson();
console.log("Trying to register");
} else {
$w("#errorMessage").expand();
console.log("Missing Information");
}
})
});
function registerPerson () {
let email = $w("#email").value;
let password = $w("#password").value;
let name = $w("#name").value;
let company = $w("#company").value;
let toInsert = {
"name": name,
"company": company,
"email": email
};
wixData.insert("Members", toInsert)
.then( (results) => {
let item = results;
} )
.catch( (err) => {
let errorMsg = err;
} );
doRegistration(email, password, name)
.then((result) => {
wixWindow.openLightbox("confirmation");
let userId = result.user.id
.catch((err) => {
let errMsg = err;
console.log(err);
$w("#emailExists").expand();
} );
});
}
BACKEND REGISTER.JSW
export function doRegistration(email, password, name, company) {
// register the user
return wixUsers.register(email, password, {
"contactInfo": {
"name": name,
"company": company
}
})
.then((results) => {
wixUsers.emailUser('verifyRegistration', results.user.id, {
variables: {
approvalToken: results.approvalToken
}
});
return results
});
}
export function doApproval(token) {
// approve the user
return wixUsers.approveByToken(token)
// user is now active, but not logged in
// return the session token to log in the user client-side
.then((sessionToken) => {
return { sessionToken, "approved": true };
})
.catch((error) => {
return { "approved": false, "reason": error };
});
}
CONFIRMATION PAGE (where users will be redirected after confirming their email)
import wixLocation from 'wix-location';
import wixUsers from 'wix-users';
import {doApproval} from 'backend/register';
$w.onReady( () => {
// get the token from the URL
let token = wixLocation.query.token;
doApproval(token)
.then( (result) => {
if (result.approved){
// log the user in
wixUsers.applySessionToken(result.sessionToken);
console.log("Approved");
}
else {
console.log("Not approved!");
}
} );
} );
just create the SPF record in the DNS and include everything to it along with the WIX servers (ascendbywix.com ~all).

How to write PWA in Vue js?

i used to write pwa via vanilla javascript like this
importScripts('/src/js/idb.js');
importScripts('/src/js/utility.js');
const CACHE_STATIC_NAME = 'static-v4';
const CACHE_DYNAMIC_NAME = 'dynamic-v2';
const STATIC_FILES = [
'/',
'/index.html',
'/offline.html',
'/src/js/app.js',
'/src/js/feed.js',
'/src/js/promise.js',
'/src/js/fetch.js',
'/src/js/idb.js',
'/src/js/material.min.js',
'/src/css/app.css',
'/src/css/feed.css',
'/src/images/main-image.jpg',
'https://fonts.googleapis.com/css?family=Roboto:400,700',
'https://fonts.googleapis.com/icon?family=Material+Icons',
'https://cdnjs.cloudflare.com/ajax/libs/material-design-lite/1.3.0/material.indigo-pink.min.css'
];
self.addEventListener('install', function(e) {
e.waitUntil(
caches.open(CACHE_STATIC_NAME)
.then(function(cache) {
console.log('[Service Worker] Installing Service Worker ...');
cache.addAll(STATIC_FILES);
})
);
});
self.addEventListener('activate', function(e) {
console.log('[Service Worker] Activating Service Worker ...');
// clear old cache
e.waitUntil(
caches.keys()
.then(function(cachedKeys) {
return Promise.all(cachedKeys.map(function(key) {
if(key !== CACHE_STATIC_NAME && key !== CACHE_DYNAMIC_NAME) {
return caches.delete(key);
}
}))
})
);
// Tell the active service worker to take control of the page immediately.
return self.clients.claim(); // to ensure that activating is correctly done
});
//After install, fetch event is triggered for every page request
self.addEventListener('fetch', function(event) {
let url = 'https://pwa-training-4a918.firebaseio.com/posts.json';
if(event.request.url === url) {
event.respondWith(
fetch(event.request).then(res => {
let clonedRes = res.clone();
// in order to clear ol data if new data is different from the original one
clearAllData('posts')
.then(() => {
return clonedRes.json()
})
.then(data => {
for(let key in data) {
writeData('posts', data[key])
}
});
return res;
})
);
// USE Cache only Strategy if the request is in the static Files
} else if(STATIC_FILES.includes(event.request.url)) {
event.respondWith(
caches.match(event.request)
);
} else {
event.respondWith(
caches.match(event.request).then(response => {
return response || fetch(event.request).then(response => {
return caches.open(CACHE_DYNAMIC_NAME).then(cache => {
cache.put(event.request, response.clone());
return response;
})
})
})
.catch(err => {
return caches.open(CACHE_STATIC_NAME).then(cache => {
// i need to show offline page only if the failure is in the help Page
// because it does not make any sence if i show this page in case of the failure in files like css
if(event.request.headers.get('accept').includes('text/html')) {
return cache.match('/offline.html');
}
})
})
);
}
});
but when I'm trying to write my own in vuejs app I installed pwa via vue add pwa it created for me a file called registerServiceWorker.js that I don't understand because I'm not used to use it
This file contains the following
/* eslint-disable no-console */
import { register } from 'register-service-worker'
if (process.env.NODE_ENV === 'production') {
register(`${process.env.BASE_URL}service-worker.js`, {
ready () {
console.log(
'App is being served from cache by a service worker.\n' +
)
},
registered () {
console.log('Service worker has been registered.')
},
cached () {
console.log('Content has been cached for offline use.')
},
updatefound () {
console.log('New content is downloading.')
},
updated () {
console.log('New content is available; please refresh.')
},
offline () {
console.log('No internet connection found. App is running in offline mode.')
},
error (error) {
console.error('Error during service worker registration:', error)
}
})
}
I don't know how to write my own pwa code here or where I can do that?
Also I don't know if it will work on localhost or not because from what I'm noticing it works in Production
So My Question is, How Can I Write PWA As I used to do with vanilla js in vue app? What are the steps should I do in order to accomplish my full custom PWA?
Can I Do That without using workbox?
if anyone can help me i'll be appreciated.
Thanks in advance.
I/(pretty sure most of us) won't likely throw to redo service worker from scratch in any project, Workbox is also recommended tools in Google Developers' page other than Vue CLI.
As the registerServiceWorker.js, that's boilerplate for your service worker cycle in your App, as the logs pretty straightforward in the flow of your app process
If you wanna to do from scratch still, i would suggest read https://developers.google.com/web/fundamentals/primers/service-workers/ to understand the fundamentals. I would recommend because service-worker pretty much "I hope you know what you doing with your app like what-when-to update/caching/do-when-offline/"

Pusher Chatkit in Vue - onNewMessage hook triggered twice?

I have a Vue.js application using the Pusher Chatkit.
I have a problem I haven't been able to find an answer for some time now.
Whenever I re-visit a view/component the Chatkit onNewMessage() hook is triggered multiple times. It depends on the times I re-visit the page.
Page refresh or first-time load resolves the issue until next re-visit.
It must be that I am creating multiple listeners each time I visit the view, but I don't get what these listeners are.
Pusher states that room subscriptions "override" the old ones when done twice.
Here is my chat.vue component
import chatConnection from '../chatkit.js'
created(){
let chatManagerConnectPromise = chatConnection(this, uid)
Promise.all([..., chatManagerConnectPromise, ...])
.then(results => {
// ...
this.initiateNewChatState(results[1])
// ...
})
.catch(error =>{
});
},
methods: {
initiateNewChatState(currentUser){
this.subscribeToAllUserRooms(currentUser)
},
subscribeToAllUserRooms(currentUser){
for(let room of currentUser.rooms){
this.subscribeToRoom(currentUser, room.id)
}
},
subscribeToRoom(currentUser, roomId){
currentUser.subscribeToRoom({
roomId: roomId,
hooks: {
onNewMessage: message => {
console.log("CHAT | onNewMessage | new: ", message.text)
}
},
messageLimit: 10
})
.catch(error => {
this.notifyError("Uh oh", "Something is not right")
});
}
}
And here is my chatkit.js content:
import { ChatManager, TokenProvider } from '#pusher/chatkit'
export const chatConnection = ({ state, actions }, uid) =>{
return new ChatManager({
instanceLocator: "##:###:###:####:####",
userId: uid,
tokenProvider: new TokenProvider({url: 'https://...' })
})
.connect({
onAddedToRoom: room => {
// some action taken
},
onRemovedFromRoom: room => {
// some action taken
},
onRoomDeleted: room => {
// some action taken
}
})
.then(user => {
return user
})
.catch(error => console.log('CHATKIT | Error on connection', error))
}
Again, the problem is that the onNewMessage() is triggered once the first time after the page refresh/first load, but then increases by one with each new page visit (back and forth navigation).
I am creating some listeners with each visit but it cannot be the ChatManager not the User.subscribeToRoom!?
Thanks for any pointers.