Progressive Web Apps laravel cache issue - laravel

I am working with PWA for my laravel project, My PWA app working fine, my website run in https only but When i logged in my website shows my old logged user details how can i solve this issue?
I am afraid my website also run based on cache memory
In localhost PWA icon not showing in my browser how can i solve in localhost
here i added service provider js file
// Cache API
const staticCacheName = 'app-shell-v2.0';
const filesToCache = [
// Files
'.',
//css files and js file
];
self.addEventListener('install', event => {
console.log('Installing worker to cache static assets');
self.skipWaiting();
event.waitUntil(
caches.open(staticCacheName)
.then(cache => {
return cache.addAll(filesToCache);
})
);
});
self.addEventListener('activate', event => {
console.log('Activating new worker...');
const cacheWhitelist = [staticCacheName];
self.clients.claim();
event.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.map(cacheName => {
if (cacheWhitelist.indexOf(cacheName) === -1) {
return caches.delete(cacheName);
}
})
);
})
);
});
self.addEventListener('fetch', event => {
// exclude directories from cache
/*if (event.request.url.match('^.*(\/admin\/).*$','^.*(\/users\/show\/).*$')) {
return false;
}
if (event.request.url.endsWith('authenticate')) {
return false;
}*/
console.log('Fetch event for ', event.request.url);
event.respondWith(
caches.match(event.request)
.then(response => {
if (response) {
console.log('Found ', event.request.url, ' in cache');
return response;
}
console.log('Network request for ', event.request.url);
return fetch(event.request)
.then(response => {
if (response.status === 404) {
return caches.match('https://site_url/404.html');
}
return caches.open(staticCacheName)
.then(cache => {
cache.put(event.request.url, response.clone());
return response;
});
});
}).catch(error => {
console.log('Error, ', error);
return caches.match('https://site_url/offline.html');
})
);
});

Related

Download an image to React Native from a Laravel server?

I am looking to download an image stored on a server into my React Native app.
I had a function that looked like this:
public function image(Request $request, $id)
{
$company = Company::find($id);
$filePath = storage_path() . '/app/' . $company->image;
return response()->file($filePath);
}
And it returned nothing I could read within the app when I tried the following function:
setCompany = async () => {
let company = await AsyncStorage.getItem('currentCompany');
company = JSON.parse(company);
if (company.image !== null) {
let image = await getCompanyPicture({company_id: company.id});
console.log('Here: ', image);
// This is blank, react native returns a warning about data not being of a readable type
}
this.setState({company});
};
I am able to get the image in base_64 using this method:
public function image(Request $request, $id)
{
$company = Company::find($id);
$file_path = storage_path('/app/' . $company->image);
if (file_exists($file_path)) {
$fileData = file_get_contents($file_path);
$fileEncode = base64_encode($fileData);
return response()->json(['status' => 'success', 'data' => ['file' => $fileEncode, 'file_path' => $file_path]]);
}
return response()->json(['status' => 'failure', 'data' => ['file' => null, 'file_path' => $file_path]]);
}
Here is my Axios method too just in case:
export const sendRequest = async (url, data, token, method) => {
let headers = {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Method': 'POST, GET, DELETE, PUT',
};
if (typeof token !== 'undefined' && token !== 'undefined' && token.length) {
headers.Authorization = 'Bearer ' + token;
}
if (method === 'get' && data) {
url +=
'?' +
Object.keys(data)
.map((value) => {
return value + '=' + data[value];
})
.join('&');
data = null;
}
return await axios({
headers: headers,
method: method ? method : 'post',
url: url,
data: data,
})
.then((response) => {
return response;
})
.then((json) => {
return json.data;
})
.catch((error) => {
console.error(error);
if (
error.message !== 'Network Error' &&
error.response.status !== 500 &&
error.response.status !== 413
) {
return error.response.data;
} else if (error.message === 'Network Error') {
return {
status: 'error',
message: 'Unable to connect to server',
};
} else if (error.response.status === 500) {
return {
status: 'error',
message: 'Internal Server Error',
};
} else if (error.response.status === 413) {
return {
status: 'error',
message: 'The file(s) size is too large',
};
} else {
return {
status: 'error',
message: error.message,
};
}
});
};
If anyone could comment on the performance impact of using base_64 instead of the straight file download that would also be helpful
But ultimately I would like a solution for handling the Laravel response()->file() if possible (which I'll use if base_64 is less efficient)
I'm not sure about RN code syntax, but I've ready code with jQuery+poorJS, which looks like this:
$.ajax({
url: "load-image-url", // URL FOR GET REQUEST
cache:false,
xhr: function() { // ACTUALLY THIS PART CAN BE USED AND CUSTOMIZED BY YOU
let xhr = new XMLHttpRequest();
xhr.responseType= 'blob'
return xhr;
},
success: function(data) {
let url = window.URL || window.webkitURL;
$('#image').attr('src', url.createObjectURL(data));
},
error: function(err) {
// console.log(err);
}
}).fail(function() {
$('#ss_product_image').attr('src', "default-image-url.jpg");
});
In my example I've used GET request (but you can try to modify it and test if you want, honestly IDK about that).
This is the back-end part:
public function image(Request $request, $id)
{
// HERE YOU NEED TO GET YOUR IMAGE (using $id or/and $request params) CONTENT FROM SOMEWHERE YOU WANT
$content = <CONTENT>;
return response()->make($content, 200, [
'Content-Type' => (new \finfo(FILEINFO_MIME))->buffer($content),
'Content-length' => strlen($content),
]);
}
I was able to solve this issue by using rn-blob-fetch.
The files are downloaded into a temp cache which can then be accessed for previewing and saving.
this is my function now:
downloadFiles = async (isReply) => {
let {enquiry, reply} = this.state;
this.setState({isLoading: true});
const token = await AsyncStorage.getItem('userToken');
let filePaths = [];
let fileCount = 0;
let files = enquiry.files;
if (isReply) {
files = reply.files;
}
const dirToSave =
Platform.OS == 'ios'
? RNFetchBlob.fs.dirs.DocumentDir
: RNFetchBlob.fs.dirs.DownloadDir;
new Promise((resolve, reject) => {
for (var i = 0; i < files.length; i++) {
var id = files[i].file_id;
var name = files[i].file.file_name;
var ext = extension(name);
const configOptions = Platform.select({
ios: {
appendExt: ext,
fileCache: true,
title: name,
path: `${dirToSave}/${name}`,
},
android: {
useDownloadManager: true,
notification: true,
mediaScannable: true,
fileCache: true,
title: name,
path: `${dirToSave}/${name}`,
},
});
var mime = content(ext);
let headers = {
'Content-Type': mime,
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Method': 'POST, GET, DELETE, PUT',
Authorization: 'Bearer ' + token,
};
RNFetchBlob.config(configOptions)
.fetch('GET', BASE_API + '/enquiries/files/download/' + id, headers)
.then(async (response) => {
RNFetchBlob.fs.writeFile(
configOptions.path,
response.data,
'base64',
);
filePaths.push({
title: configOptions.title,
path: configOptions.path,
ext: extension(configOptions.title),
mime,
});
fileCount++;
if (fileCount >= files.length) {
resolve('Download Successful!');
}
})
.catch((error) => {
console.log('File Download Error: ', error.message);
reject('Download Failed');
});
}
})
.then((data) => {
this.setState({isLoading: false, filePaths});
})
.catch((error) => {
console.log('Download Promise Error: ', error);
this.setState({isLoading: false});
});
};
previewDocument = (id) => {
let {filePaths} = this.state;
if (Platform.OS == 'ios') {
RNFetchBlob.ios.openDocument(filePaths[id].path);
} else if (Platform.OS == 'android') {
RNFetchBlob.android.actionViewIntent(
filePaths[id].path,
filePaths[id].mime,
);
}
};

Image is not defined (Firebase storage - React Native)

The problem:
I am able to successfully upload an image to firebase storage, but when I try to sign-out, then sign-in again, I am stucked on the log-in page. and after few minutes this error appears
This is my code on fetching the image and log-in
if (currentUser != null) {
uid = currentUser.uid;
const db = firebase.firestore();
const docRef = db.collection("users").doc(uid);
console.log("uid")
console.log(uid)
console.log("currentUser")
console.log(currentUser)
console.log("docRef")
console.log(docRef)
docRef.get().then((doc) => {
console.log("doc");
console.log(doc);
if (doc.exists) {
console.log("Document data:", doc.data());
const userData = doc.data();
const imageRef = firebase.storage().ref(`/userProfilePictures/${uid}`).child('profile.jpg');
imageRef.getDownloadURL().then(function(url) {
dispatch({ type: GET_PROFILE_PICTURE, payload: url })
dispatch({ type: GET_USER_DATA, payload: userData});
Actions.home();
}).catch((error) => {
dispatch({type: GET_PROFILE_PICTURE, payload: ''})
console.log(error);
})
} else {
console.log("No such document!");
}
}).catch((error) => {
console.log("Error getting document:", error);
});
}else {
console.log('something went wrong');
}
})
.catch((error) => {
loginUserFail(dispatch)
const errorCode = error.code;
const errorMessage = error.message;
console.log(errorMessage);
});
After loggin in again, it seems that the user is authenticated, but It can't execute this line docRef.get().then((doc) => { there is no error on the console.log.
And then if you try to reload again, then sign-in again you can see the newly uploaded image.

How to turn on Autorization?

"By default, an admin-on-rest app doesn’t require authentication".
I have written an application with AOR and Loopback API, etc, and it works well. Except for one thing, I can't turn on turn on authentication. Any username/password will work, just like in the Demo.
From what I can see all required components load, AuthClient etc., Loopback is configured and is waiting for user authorization requests but never gets any.
I copy/pasted a lot of Demo's parts...
Any hints please?
I use the unchanged authClient from kimkha aor loopback
import storage from './storage';
export const authClient = (loginApiUrl, noAccessPage = '/login') => {
return (type, params) => {
if (type === 'AUTH_LOGIN') {
const request = new Request(loginApiUrl, {
method: 'POST',
body: JSON.stringify(params),
headers: new Headers({ 'Content-Type': 'application/json' }),
});
return fetch(request)
.then(response => {
if (response.status < 200 || response.status >= 300) {
throw new Error(response.statusText);
}
return response.json();
})
.then(({ ttl, ...data }) => {
storage.save('lbtoken', data, ttl);
});
}
if (type === 'AUTH_LOGOUT') {
storage.remove('lbtoken');
return Promise.resolve();
}
if (type === 'AUTH_ERROR') {
const { status } = params;
if (status === 401 || status === 403) {
storage.remove('lbtoken');
return Promise.reject();
}
return Promise.resolve();
}
if (type === 'AUTH_CHECK') {
const token = storage.load('lbtoken');
if (token && token.id) {
return Promise.resolve();
} else {
storage.remove('lbtoken');
return Promise.reject({ redirectTo: noAccessPage });
}
}
return Promise.reject('Unkown method');
};
};

Service worker should not cache the whole page

I register '/' (route) .css and .js file as URL that should be cached at first.
But after that I realize that it cached the whole page, which means I don't see any update on my view, event there is an update on database.
So I change it only cache my .css and .js file not route ('/') anymore , I expected that's the problem.
But after awhile, the same problem still occurred. I check on my console it did cache the whole page again, even though my Service Worker file already change like this:
var CACHE_NAME = 'cache-v2';
var urlsToCache = [
'/assets/css/app.css',
'/assets/js/main.js',
'/assets/js/other.js'
];
self.addEventListener('install', function(event) {
event.waitUntil(
caches.open(CACHE_NAME)
.then(function(cache) {
console.log('Opened cache');
return cache.addAll(urlsToCache);
})
);
});
self.addEventListener('activate', function(e) {
console.log('[ServiceWorker] Activate');
e.waitUntil(
caches.keys().then(function(keyList) {
return Promise.all(keyList.map(function(key) {
if (key !== CACHE_NAME) {
console.log('[ServiceWorker] Removing old cache', key);
return caches.delete(key);
}
}));
})
);
return self.clients.claim();
});
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request)
.then(function(response) {
// Cache hit - return response
if (response) {
return response;
}
var fetchRequest = event.request.clone();
return fetch(fetchRequest).then(
function(response) {
if(!response || response.status !== 200 || response.type !== 'basic') {
return response;
}
var responseToCache = response.clone();
caches.open(CACHE_NAME)
.then(function(cache) {
cache.put(event.request, responseToCache);
});
return response;
}
);
})
);
});
in case anyone has the same problem,
here is what i should change
self.addEventListener('fetch', function(e) {
console.log('[ServiceWorker] Fetch', e.request.url);
e.respondWith(
caches.match(e.request).then(function(response) {
return response || fetch(e.request);
})
);
});
so my previous fetch looks like the problem

Can not connect with API , so couldn't retrieve post from db?

I got problem while I move into https://github.com/DaftMonk/generator-angular-fullstack.
Before my project was working. Here is code for frontend and backend part related to comment.
I am getting all time error 404. I don't know why I cannot find following path.
POST http://localhost:9000/api/providers/554a1dba53d9ca8c2a2a31ff/posts/554b1726f1116e00256e3d82/comments 404 (Not Found)
I am struggling couple of days to discover which part of my code have problem but I couldn't realize that.
server side
in comment.controller
// Creates a new comment in the DB.
exports.create = function(req, res) {
console.log('i ma inside api');
Post.findById(req.originalUrl.split('/')[3], function (err, post) { //here can not find post at all.
if (err) {
return handleError(res, err);
}
if (!post) {
return res.status(404).send('Post not found');
}
Comment.create(req.body, function (err, comment) {
if (err) {
return handleError(res, err);
}
post.comments.push(comment.id);
post.save(function (err) {
if (err) return handleError(res, err);
return res.status(201).json(comment);
});
});
});
};
route.js
app.use('/api/providers/:providerId/posts/:postId/comments', require('./api/provider/post/comment'));
index.js
var controller = require('./comment.controller.js');
var router = express.Router();
router.get('/', controller.index);
router.get('/:id', controller.show);
router.post('/', controller.create);
router.put('/:id', controller.update);
router.patch('/:id', controller.update);
router.delete('/:id', controller.destroy);
router.put('/:id/upvote', controller.upvote);
in client side:
factory:
//create new comment for post
ob.createComment = function(providerId, postId,comment) {
console.log('i am inside factory');
return $http.post('/api/providers/'+ providerId + '/posts/' + postId + '/comments' ,comment, {
headers: {Authorization: 'Bearer '+Auth.getToken()}
}).success(function(data){
_.forEach(ob.provider.posts,function(value,index){
if(value._id === post._id){
ob.posts[index].comments.push(data);
}
})
ob.current.comments.push(data)
// ob.provider1._id.posts.push(data);
});
};
in my controller
$scope.addComment = function(){
// if(!$scope.title || $scope.title === '') { return; }
if(!$scope.body || $scope.body === '') { return; }
console.log('$stateParams',$stateParams);
providers.createComment($stateParams.providerId, $stateParams.postId,{
//title: $scope.title,
body: $scope.body
});
$scope.body = '';
$scope.title = '';
};
This is my model in whole the project.

Resources