Keep Session Angularjs Authentication - javascript

I'm using the Jason project that you can find at this link in my project.
I'm using AngularJS 1.6.4 with WildFly 10 with Java 8 and SQL Server 2014. I can get the login correction, but when I refresh the page the same does not hold the session.
What could be happening? Besides the adaptations I have to do in 'user.service.js', do I have to change anything else to be able to keep the session?
My code user.service.js
(function () {
'use strict';
angular
.module('app')
.factory('UserService', UserService);
UserService.$inject = ['$http'];
function UserService($http) {
var service = {};
//service.GetAll = GetAll;
//service.GetById = GetById;
service.GetByUsername = GetByUsername;
service.Create = Create;
//service.Update = Update;
//service.Delete = Delete;
return service;
//function GetAll() {
// return $http.get('rest/usuarios/login/').then(handleSuccess, handleError('Error getting all users'));
//}
//function GetById(id) {
// return $http.get('rest/usuarios/login/' + id).then(handleSuccess, handleError('Error getting user by id'));
//}
function GetByUsername(usermatricula, usersenha) {
return $http.post('rest/usuarios/login/' + usermatricula + '/' + usersenha).then(handleSuccess, handleError('Error getting user by username'));
}
function Create(user) {
return $http.post('rest/usuarios/', user).then(handleSuccess, handleError('Error creating user'));
}
//function Update(user) {
// return $http.put('rest/usuarios/login/' + user.id, user).then(handleSuccess, handleError('Error updating user'));
//}
//function Delete(id) {
// return $http.delete('rest/usuarios/login/' + id).then(handleSuccess, handleError('Error deleting user'));
//}
// private functions
function handleSuccess(res) {
console.log(res.data);
return res.data;
}
function handleError(error) {
return function () {
return { success: false, message: error };
};
}
}
})();

You can store user data in localStorage when you get response from request as below
function handleSuccess(res) {
console.log(res.data);
// Put the object into storage
localStorage.setItem('userSession', JSON.stringify(res.data));
return res.data;
}
To check if a session exists you can do
// If an object named userSession exists in the local storage
if(localStorage.getItem('userSession')){
// Retrieve the object from storage
var userSession = JSON.parse(localStorage.getItem('userSession'));
}
And then check data in userSession

Related

Axios Async Await Function returns 'undefined' results (Using while Loop)

I am trying to get data from an api using axios.
I am first getting the token, and then using the token to make the request. Since there is a limit on how much information can be responded, I have to use a while loop to get all the data and store it all to an empty array.
However, I am getting a bunch of 'undefined', I read other similar articles online with regard to this return, and most of them is because of "no return", but since I am using a while loop, where can I return the data?
const getDailySales = async (req, res) => {
try {
const res_token = await axios.post(
`https://cysms.wuuxiang.com/api/auth/accesstoken?appid=${process.env.TCSL_APPID}&accessid=${process.env.TCSL_ACCESSID}&response_type=token`
);
const token = res_token.data.access_token;
var list = [];
var pageTotal = true;
var pageNo = 1;
while (pageTotal) {
var salesData = await axios.post(
`https://cysms.wuuxiang.com/api/datatransfer/getserialdata?centerId=${process.env.TCSL_CENTERID}&settleDate=2022-09-30&pageNo=${pageNo}&pageSize=20&shopId=12345`
{},
{
headers: {
access_token: `${token}`,
accessid: `${process.env.TCSL_ACCESSID}`,
granttype: "client",
},
}
);
list.push(salesData);
console.log(salesData.data.data.billList.shop_name);
if (salesData.data.data.pageInfo.pageTotal !== pageNo) {
pageNo += 1;
} else {
pageTotal = false;
}
}
} catch (error) {
console.log(error);
}
};
Above implementation would work.
Return list just before catch and after ending of the while loop
} else {
pageTotal = false;
}
}
return list;
} catch (error) {
console.log(error);
}
};
Few suggestions
Use let/const instead of var.
Can elaborate more error handling
return list like this:
return res.status(200).json({list});

Can you pass error messages from Service Workers to DOM

I've been trying to work on this for a while. I'm working with google drive api -> and I'm trying to try to get the main script to re-run the request of the accessToken is incorrect and causes an error.
Can that be sent to the main script somehow?
Adding some code to show I've actually worked on this lol - left out some bc it's alot of other unrelated stuff.
I am using IndexedDB to pass info between SW and main Script
//////////////////////////////////////////////////////////////
//////////////// Check Database onload ///////////////////////
//////////////////////////////////////////////////////////////
window.addEventListener("load", checkUpload(), false);
function checkUpload() {
if (supportCheck()) {
let openRequest = indexedDB.open("GoogleDrive", 1);
openRequest.onsuccess = (e) => {
var db = e.target.result;
var objectStore = db
.transaction(["backups"], "readwrite")
.objectStore("backups");
var request = objectStore.get("1");
request.onerror = function () {
// Handle errors!
};
request.onsuccess = function (event) {
var data = event.target.result;
if (googleSignin.isAuthorizedForGDrive()) {
// Call SW Function
}
else {
//Google Sign in Error
}
let accessToken = gapi.auth.getToken().access_token;
data.access = accessToken;
// Put this updated object back into the database.
var requestUpdate = objectStore.put(data);
requestUpdate.onerror = function (event) {
// Do something with the error
};
requestUpdate.onsuccess = function (event) {
// Success - the data is updated!
// Call SW Function
};
}
}
}
}
}
//////////////////////////////////////////////////////////////
//////////////// Initialize Database Function ///////////////
//////////////////////////////////////////////////////////////
uploadBtn.addEventListener("click", handleUploadClick, false);
save.addEventListener("click", handleUploadClick, false);
//Adds/Create Data that is stored in IndexedDB so that the Service Worker can
access and use it
//ServiceWorker Call Function
function initSW() {
console.log("Script: Called InitSW()");
if ("serviceWorker" in navigator) {
navigator.serviceWorker
.register("serviceWorker.js")
.then((registration) => navigator.serviceWorker.ready)
.then((registration) => {
registration.sync.register("sendFile-sync").then(() => {
//Do Function using sync
try {
console.log("Script : Sync Registered");
} catch {
console.log("Script : Sync Not Registered");
}
});
});
}
}
SW
self.addEventListener("sync", (e) => {
if (e.tag === "sendFile-sync") {
console.log("SW Sync : Sync Found!");
e.waitUntil(fetchFile());
} else {
console.log("SW Sync : No Sync Found");
}
});
//Function Called above when sync is fired
function fetchFile() {
let openRequest = indexedDB.open("GoogleDrive", 1);
openRequest.onerror = function () {
};
openRequest.onsuccess = function () {
let db = openRequest.result;
let transaction = db.transaction(["backups"], 'readwrite');
let backups = transaction.objectStore("backups");
let request = backups.get("1");
request.onsuccess = function (event) {
let date = Date();
let accessToken = request.result.access;
console.log("SW Sync: Access Token - " + accessToken);
let BlobContent = request.result.text;
let file = BlobContent;
let metadata = {
name: "Backup " + date, // Filename
mimeType: "application/pdf", // mimeType at Google Drive
parents: ["root"], // Root Folder ID for testing
};
let form = new FormData();
form.append(
"metadata",
new Blob([JSON.stringify(metadata)], { type: "application/json" })
);
form.append("file", file);
fetch(
"https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart&fields=id",
{
method: "POST",
headers: new Headers({ Authorization: "Bearer " + accessToken }),
body: form,
}
)
.then((res) => {
return res.json();
})
.then(function (val) {
console.log(val.error.message);
<!-- message is "invalid credentials --> in our scenario
}
})
}
request.onerror = function () {
console.log("SW Sync : Getting IndexedDB values error");
};
};
}
Sure, the ServiceWorker's clients are exposed in its self.clients property, from where you can find the correct Client with which you can communicate thanks to its postMessage() method.
How to find the correct client will depend on the situation, for instance in the install or activate events there should be only one client, so you should be able to reach it by doing
const clients = await self.clients.matchAll();
const client = clients[0];
client.postMessage("something bad happenned...");
In a fetch event, the clientId is exposed on the event instance, so you can do
const client = await self.clients.get(evt.clientId);
client.postMessage("something bad happenned...");
I must admit I don't know well the BackgroundSync API, so I'm not sure if in this sync event your page would be the only one client, however, you can certainly make your page open a private communication channel with the SW even before, which by the way, sounds like a better mean of passing your API's credentials than through IDB:
const channel = new MessageChannel();
channel.port1.onmessage = SWTalksToMe; // handle messages from SW
navigator.serviceWorker
.register("serviceWorker.js")
.then((registration) => navigator.serviceWorker.ready)
.then((registration) => {
registration.postMessage("", [channel.port2]));
return registration.sync.register("sendFile-sync")
})
//...
And in your ServiceWorker
self.addEventListener("message", evt => {
if(evt.ports) {
client_port = evt.ports[0];
}
});
Finally, if you wanted to communicate with all the clients, you could use a BroadcastChannel.

Getting data from function

I am having some trouble getting the logged in status from the below function.
I can set the loggedIn status with currentUser.setProfile(username, token), which works.
But when i then try to get the isLoggedIn afterwards, i can't seem to get it.
console.log(currentUser) return the 2 functions, setProfile and getProfile. But getProfile is just an empty function.
I have tried currentUser.getProfile.isLoggedIn among others, but they all just return undefined.
What am i doing wrong?
Function:
(function () {
"use strict";
angular
.module("myApp")
.factory("currentUser",
currentUser)
function currentUser() {
var profile = {
isLoggedIn: false,
username: "",
token: ""
};
var setProfile = function (username, token) {
profile.username = username;
profile.token = token;
profile.isLoggedIn = true;
};
var getProfile = function () {
return profile;
}
return {
setProfile: setProfile,
getProfile: getProfile
}
}
})();
Because getProfile is a function, you should call it like
currentUser.getProfile().isLoggedIn

node.js redis and how to use promise when using a module

I have an Express route like this in an node server (file is required):
var redis = require('../modules/redis');
module.exports = function (app) {
var redisClient = redis.init();
app.post('/auth/ticket', cors(), function (req, res) {
var hashes = ['hash1','hash2', 'hash3'];
var candidates = []; // An array to collect valid hashes
var key;
// to check each hash against a RedisDB I use a For Loop
for (key in hashes) {
var hash = hashes[key];
console.log("Hash " + hash + " will be proofed now:");
//now I try to collect the valid hashes in the candidates array
if (redisClient.exists(hash) === 1) candidates.push(hash);
}
console.log(JSON.stringify(candidates));
});
};
Now here is the code of my module which shall manage all the redis requests:
exports.init = function () {
Redis = exports.Redis = function () {
var promiseFactory = require("q").Promise,
redis = require('promise-redis')(promiseFactory);
this.client = redis.createClient();
this.client.on('error', function (err) {
console.log('redis error – ' + client.host + ':' + client.port + ' – ' + err);
});
Redis.prototype.exists = function (key) {
this.client.exists(key, function (err, data) {
return data === 1 ? true : false;
});
};
return new Redis();
};
So what I experience is that the module is able to console.log the results properly. If a hash is valid, it returns true and otherwise false. This works as expected.
Problem is, that the for-loop continuous the execution without fetching getting the results. I think this is caused by race-conditions.
As you can see, I have started to workout something there with the use of Q and promise-redis in the top of my code:
var promiseFactory = require("q").Promise,
redis = require('promise-redis')(promiseFactory);
this.client = redis.createClient();
I like to know, how I make my for-loop (in the Express route) waiting for the results of redisClient.exists(hash) or in other words, to get all valid hashes into my candidates array.
Please help
like #brad said, you could use Q.all, it would take an array of promises as input and then return an array of results when all the promises are finished:
there is a mistake in your answer:
Redis.prototype.exists = function (key) {
return this.client.exists(key) // CHANGED, you still need to return a promise.
.then(function (reply) {
console.log("reply " + reply);
return (reply);
})
.catch(console.log);
};
If I understand correctly, what you want is something like
exports.init = function () {
Redis = exports.Redis = function () {
var Q = require("q"),
promiseFactory = Q.Promise,
redis = require('promise-redis')(promiseFactory);
this.client = redis.createClient();
this.client.on('error', function (err) {
console.log('redis error – ' + client.host + ':' + client.port + ' – ' + err);
});
Redis.prototype.exists = function (key) {
return this.client.exists(key).then(function (data) {
return data === 1 ? true : false;
});
};
Redis.prototype.getActive = function (arry) {
var self = this;
return Q.all(arry.map(self.exists.bind(self))
).then(function(res){
return arry.filter(function(val, idx){ return res[idx];});
});
};
return new Redis();
};
# mido22: But did you also recognize that I outsourced all the reds functions to the module file (1st Codeblock) which requires the promise-redid and builds a factory for Q. I changed the code inside the module file to:
Redis.prototype.exists = function (key) {
this.client.exists(key)
.then(function (reply) {
console.log("reply " + reply);
return (reply);
})
.catch(console.log);
};
and this results correctly like the console.log evidently shows.
Your codechange of the for-loop works very well but I think it don't fulfills my needs perfectly. If I could, I would like to have it completely outsourced in to the module file, so that I can use the prototyped method in similar cases from everywhere. Is that possible anyhow?
I see, that it would result in having two promise supported functionalities, if I would create an Instance of Redis Client with promise-redid and Q inside the auth/ticket/ router, too.
like this:
var Q = require('q'),
promiseFactory = Q.Promise,
redis = require("promise-redis")(promiseFactory),
client;
an then the express route (there are a lot of more routes each in a single file) like in your code.
Do you understand what I mean? Of course your solution will be fine for my needs at all, but a module resolving the job completely could have more elegance if possible so far.
Using with redis, bluebird and typescript:
import { RedisClient, createClient, ClientOpts } from "redis";
import { promisifyAll, PromisifyAllOptions } from "bluebird";
export module FMC_Redis {
export class Redis {
opt: ClientOpts;
private rc: RedisClient;
private rcPromise: any;
private static _instance: Redis = null;
public static current(_opt?: ClientOpts): Redis {
if (!Redis._instance) {
Redis._instance = new Redis(_opt);
Redis._instance.redisConnect();
}
return Redis._instance;
}
public get client(): RedisClient {
if (!this.rc.connected) throw new Error("There is no connection to Redis DB!");
return this.rc;
}
/******* BLUEBIRD ********/
public get clientAsync(): any {
// promisifyAll functions of redisClient
// creating new redis client object which contains xxxAsync(..) functions.
return this.rcPromise = promisifyAll(this.client);
}
private constructor(_opt?: ClientOpts) {
if (Redis._instance) return;
this.opt = _opt
? _opt
: {
host: "127.0.0.1",
port: 6379,
db: "0"
};
}
public redisConnect(): void {
this.rc = createClient(this.opt);
this.rc
.on("ready", this.onReady)
.on("end", this.onEnd)
.on("error", this.onError);
}
private onReady(): void { console.log("Redis connection was successfully established." + arguments); }
private onEnd(): void { console.warn("Redis connection was closed."); }
private onError(err: any): void { console.error("There is an error: " + err); }
/****** PROMISE *********/
// promise redis test
public getRegularPromise() {
let rc = this.client;
return new Promise(function (res, rej) {
console.warn("> getKeyPromise() ::");
rc.get("cem", function (err, val) {
console.log("DB Response OK.");
// if DB generated error:
if (err) rej(err);
// DB generated result:
else res(val);
});
});
}
/******* ASYNC - AWAIT *******/
// async - await test function
public delay(ms) {
return new Promise<string>((fnResolve, fnReject) => {
setTimeout(fnResolve("> delay(" + ms + ") > successfull result"), ms);
});
}
public async delayTest() {
console.log("\n****** delayTest ")
let a = this.delay(500).then(a => console.log("\t" + a));
let b = await this.delay(400);
console.log("\tb::: " + b);
}
// async - await function
public async getKey(key: string) {
let reply = await this.clientAsync.getAsync("cem");
return reply.toString();
}
}
}
let a = FMC_Redis.Redis.current();
// setTimeout(function () {
// console.warn(a.client.set("cem", "naber"));
// console.warn(a.client.get("cem"));
// console.warn(a.client.keys("cem"));
// }, 1000);
/***** async await test client *****/
a.delayTest();
/** Standart Redis Client test client */
setTimeout(function () {
a.client.get("cem", function (err, val) {
console.log("\n****** Standart Redis Client")
if (err) console.error("\tError: " + err);
else console.log("\tValue ::" + val);
});
}, 100)
/***** Using regular Promise with Redis Client > test client *****/
setTimeout(function () {
a.getRegularPromise().then(function (v) {
console.log("\n***** Regular Promise with Redis Client")
console.log("\t> Then ::" + v);
}).catch(function (e) {
console.error("\t> Catch ::" + e);
});
}, 100);
/***** Using bluebird promisify with Redis Client > test client *****/
setTimeout(function () {
var header = "\n***** bluebird promisify with Redis Client";
a.clientAsync.getAsync("cem").then(result => console.log(header + result)).catch(console.error);
}, 100);

How to Implement $child method in new AngularFire v0.8.0?

A user is logged in to the website and tries to create a post. Whenever a new post is created, this post gets associated with the user who created the post.
Referring to a thinkster.io Tutorial, which uses older API of AngularFire.
When using AngularFire API v0.8.0, this line of code which adds the post breaks:
user.$child('posts').$child(postId).$set(postId);
The Post Factory (post.js) with the method for creating post is:
app.factory('Post',
function ($firebase, FIREBASE_URL, User) {
var ref = new Firebase(FIREBASE_URL + 'posts');
var posts = $firebase(ref).$asArray();
var Post = {
all: posts,
//Starting of create function
create: function (post) {
if (User.signedIn()) {
var user = User.getCurrent(); //Gets the current logged in user
post.owner = user.username;
return posts.$add(post).then(function (ref) {
var postId = ref.name();
user.$child('posts').$child(postId).$set(postId);
//user.$getRecord('posts').$getRecord(postId).$set(postId);
return postId;
});
}
},
//End of create function
Changelog for AngularFire states that
$child() no longer exists. The data already exists in the parent object and creating additional synchronized children is not efficient and discouraged. Use data transformations, flatten your data, or drop down to the Firebase SDK and use its child() method.
I am confused as to how to change the code to work with the update in the API.
After Edit
This is the getCurrent method:
getCurrent: function(){ // retrieves current user
return $rootScope.currentUser;
},
Which belongs to user.js Factory:
'use strict';
app.factory('User', function ($firebase, FIREBASE_URL, Auth, $rootScope) {
var ref = new Firebase(FIREBASE_URL + 'users');
var users = $firebase(ref);
var usersdiv = $firebase(ref).$asArray();
var User = {
create: function (authUser, username) {
users[username] = {
md5_hash: authUser.md5_hash,
username: username
};
users.$update(username, {
md5_hash: authUser.md5_hash,
username: username
}).then(function (dataRef) {
dataRef.setPriority(authUser.uid);
setCurrentUser(username);
});
}, // end of create method
findByUsername: function(username){
if(username){
return usersdiv.$getRecord(username);
}
},
getCurrent: function(){ // retrieves current user
return $rootScope.currentUser;
},
signedIn: function(){ //checks if user is signed in
return $rootScope.currentUser !== undefined;
}
}; // end of User
// so that we can pull info about user when logged in
function setCurrentUser (username){
$rootScope.currentUser = User.findByUsername(username);
}
//for logins and refreshes
$rootScope.$on('$firebaseSimpleLogin:login', function(e, authUser){
var queryRef = ref.startAt(authUser.uid).endAt(authUser.uid);
var queryArray = $firebase(queryRef).$asArray();
queryArray.$loaded().then(function() {
setCurrentUser(queryArray.$keyAt(0));
});
});
//logout
$rootScope.$on('$firebaseSimpleLogin:logout', function(){
delete $rootScope.currentUser;
});
return User;
});
You don't need to create a synchronized object locally (what $child used to do) just to set a value in Firebase. You can do this at any time with the Firebase ref you've already created. I can't tell exactly what the data structure of user is since it wasn't included, but something like this:
new Firebase(FIREBASE_URL).child('...path/to/posts').child(postId).set(postId);
Most likely, this belongs on your user object, so that in the Post factory, you can just do something like user.addPost(postId).
I was facing the same problem. As Kato suggested, you will have to use the child function in the Firebase object. I chose to add the post to the user in the Post factory itself.
Adding Post to User
var usersref = new Firebase(FIREBASE_URL + 'users');
usersref.child(post.owner).child('posts').child(postId).set(postId);
The Entire post.js is as below:
'use strict';
app.factory('Post',
function($firebase, FIREBASE_URL, User){
var ref = new Firebase(FIREBASE_URL + 'posts');
var usersref = new Firebase(FIREBASE_URL + 'users');
var posts = $firebase(ref).$asArray();
var Post = {
all : posts,
create : function(post){
if(User.signedIn()){
var user = User.getCurrent();
post.owner = user.username;
return posts.$add(post).then(function(ref){
var postId = ref.name();
usersref.child(post.owner).child('posts').child(postId).set(postId);
return postId;
});
}
},
find: function(postId){
return $firebase(ref.child(postId)).$asObject();
},
delete: function(postId){
if(User.signedIn()){
var postToDel = Post.find(postId);
postToDel.$loaded().then(function(){
var p = posts[postToDel.$id];
posts.$remove(postId).then(function(){
$firebase(usersref.child(p.owner).child('posts')).$asArray().$remove(p.$id);
});
});
}
}
};
return Post;
});
Correct Answer is:
'use strict';
app.factory('Post',
function ($firebase, FIREBASE_URL, User) {
var postsref = new Firebase(FIREBASE_URL + 'posts');
var usersref = new Firebase(FIREBASE_URL + 'users');
var posts = $firebase(postsref).$asArray();
var Post = {
all: posts,
create: function (post) {
if (User.signedIn()) {
var user = User.getCurrent();
post.owner = user.username;
return posts.$add(post).then(function (ref) {
var postId = ref.name();
//a child in user forge should be made with its key as postID
usersref.child(post.owner).child('posts').child(postId).set(postId);
return postId;
});
}
},
find: function (postId) {
return $firebase(postsref.child(postId)).$asObject();
},
delete: function (postId) {
if (User.signedIn()) {
var postToDel = Post.find(postId);
postToDel.$loaded().then(function(){
var p = posts[postToDel.$id];
posts.$remove(postId).then(function(){
$firebase(usersref.child(p.owner).child('posts')).$remove(p.$id);
});
});
}
},
Thus, child can be used at Firebase SDK Level.
Example:
var ref = new Firebase(FIREBASE_URL);
var userArray = $firebase(ref.child('user')).$asArray();
var userObject = $firebase(ref.child('user')).$asObject();

Categories

Resources