Ionic registration views - angularjs

I'm trying to build a registration views, but my problem is that the checking statement if the user is already registered it performs in $ionicPlatform.ready, like the following:
$ionicPlatform.ready(function() {
db = $cordovaSQLite.openDB({ name: "my.db" });
$cordovaSQLite.execute(db, "CREATE TABLE IF NOT EXISTS groups (id integer primary key, title text)");
if (typeof(Storage) != "undefined") {
// Store
var registered = localStorage["isRegistered"];
if(registered == undefined || !registered){
$location.path('/register');
}else{
$location.path('/tab/groups');
}
}
});
The problem that the $urlRouterProvider.otherwise('/tab/groups') preforms before the ionic ready, it means that in the first opening of the application, it appears the groups tab then going to the registration view.
I tried to put the statement check if the user is already registered in the otherwise like the following:
$urlRouterProvider.otherwise(function($injector, $location){
if (typeof(Storage) != "undefined") {
// Store
var registered = localStorage["isRegistered"];
if(registered == undefined || !registered){
$location.path('/register');
}else{
$location.path('/tab/groups');
}
} });
Also, I face another problem that we arrive to the groups tab (getting groups from database) before we open the database in the ionic ready.
Is there any solution to do the registration?

Ionic platform can be used anywhere in the code. You should be able to use
$urlRouterProvider.otherwise(function($injector, $location){
$ionicPlatform.ready(function(){
if (typeof(Storage) != "undefined") {
// Store
var registered = localStorage["isRegistered"];
if(registered == undefined || !registered){
$location.path('/register');
}else{
$location.path('/tab/groups');
}
}
});
});
Also, a state provider may be a better solution

Related

Maintaining a Session in MVC .net application using angularjs

I am working on an application, in which a user if has an account in db can log in the website and then perform certain functions. One of those functions involve creating a blog. The blog is being displayed in another project application using the same database. Now when user creates a blog after logging in, i need to store who created the blog in order to do that, i came up with 2 ways. Either i keep passing the user id as a parameter on every page url or i can create a session in order to store it for the duration of login.
I think the latter is a better option but i am kind of lost on how to do it. I am creating a 3 project layer Application. with the client side done in angularjs. My c# controller is being used just to pass the json data to another layer, which then communicates with the database which is in another layer.
The project files are too big but i can write a example code for it.
Html:
<div ng-app="Module">
<div ng-controller="AppController">
<input ng-model="user.Email" type="email"\>
<button type="button" ng-click="UserLogin()"\>
</div>
</div>
AngualrJs:
var app = angular.module('Module', []);
app.controller("AppController", function ($scope) {
$scope.loginchk = function () {
Post("/User/LoginValidation", $scope.user, false, $("#btnlogin")).then(function (d) {
if (d.Success) {
window.location.href = "/User/LoggedIn?emailId=" + $scope.user.Email;
}
ShowMessage(d);
});
}
})
Controller:
public JsonResult LoginValidation(LoginUser user) {
return Json((new userLogic()).LoginChk(user), JsonRequestBehavior.AllowGet);
}
Business Logic LAYER----------------
UserLogic:
public Message LoginChk(LoginUser user) {
Message msg = new Message();
try {
Account userProfile = db.Accounts.Where(b => b.Email == user.Email).FirstOrDefault();
if (userProfile == null)
{
msg.Success = false;
msg.MessageDetail = "Account Email does not exist";
}
else
{
if (userProfile.password != user.Password)
{
msg.Success = false;
msg.MessageDetail = "Wrong Password";
}
else
{
msg.Success = true;
msg.MessageDetail = "Logged In";
}
}
}
catch(Exception ex)
{
msg.Success = false;
msg.MessageDetail = "DB connection failed.";
}
return msg;
}
Now I know i can create a Session Variable in the controller like this Session['Sessionname'] = user;
but i am not sure it will work with my application because i have multiple controllers and i will still have to pass it to them. so i dont see the point of maintaining a session variable in every controller even if its not used. How do i go about creating a session?
local storage is best option to do that :
window.localStorage.setItem("userId",useId);
to get again:
localStorage.getItem("userId");
You Can use client-side LocalStorage to save the user-id and use it where ever necessary,
as it will be saved in plain text you can encrypt and save it .
check here how to encrypt using javascript
https://stackoverflow.com/a/40478682/7262120

phonegap + framework7 how to programmtacally set starting page?

I have application which on start lets you pick - if are you contributor or user. After that I want always load the starting page for a contributor or the user. I know you can set <content src="index.html" /> to do it once on start, but how can I do it dynamically?
#proofzy answer is right, but you could still do it using only DOM7 instead of Jquery
Inside your JS file:
//to save data if user pick contributor or user button after first start.
$$("#contributor").on('click', function(){
localStorage.setItem("whois", "contributor");
});
//And call this same script but for user:
$$("#user").on('click', function(){
localStorage.setItem("whois", "user");
});
//So call this function on the end of page index.html and it will redirect programmatically
function check(){
if (localStorage.getItem("whois") !== null) { //if whois exists on localStorage
if (localStorage.getItem("whois") == "user"){ // if is USER send to User Page
window.location.href = "userIndex.html"
}else if (localStorage.getItem("whois") == "contributor"){ // if is USER send to contributor Page
window.location.href = "contributorIndex.html"
}
}
}
There are many other ways to do it, even better, but this one is simplest.
You must use
localStorage
to save data if user pick contributor or user button after first start.
Simple use jQuery script:
<script>
$("#contributor").click( function()
{
//alert('button clicked');
localStorage.setItem("contributor", "contributor");
}
);
</script>
And call this same script but for user:
<script>
$("#user").click( function()
{
//alert('button clicked');
localStorage.setItem("user", "user");
}
);
</script>
So on next html page control if user is previously press "user" or "contributor".
$(document).ready(function() {
if (localStorage.getItem("user") === null) {
//user is null
} else {
document.location.href = "userIndex.html"
}
if (localStorage.getItem("contributor") === null) {
//contributor is null
} else {
document.location.href = "contributorIndex.html"
}
});
Good luck!

Link Sails's authenticated user to websocket's user

I am currently trying to create an sails+angular web-app.
I already have a user-authentication system working (based on this tutorial : https://github.com/balderdashy/activity-overlord-2-preview). I am trying to integrate a very simple chat inside using websocket.
My issue is to link websocket's "user" to the authenticated user.
Because when an authenticated user writes a message, I want to send the message as data but not the id of the current user, i would like to get this id from the sail's controller.
This is my actual sails chatController :
module.exports = {
addmsg:function (req,res) {
var data_from_client = req.params.all();
if(req.isSocket && req.method === 'GET'){
// will be used later
}
else if(req.isSocket && req.method === 'POST'){
var socketId = sails.sockets.getId(req);
/* Chat.create(data_from_client)
.exec(function(error,data_from_client){
console.log(data_from_client);
Chat.publishCreate({message : data_from_client.message , user:currentuser});
}); */
}
else if(req.isSocket){
console.log( 'User subscribed to ' + req.socket.id );
}
}
}
and this is my angular's controller
io.socket.get('http://localhost:1337/chat/addmsg');
$scope.sendMsg = function(){
io.socket.post('http://localhost:1337/chat/addmsg',{message: $scope.chatMessage});
};
req.session.me
...was the solution.

How to update user field in angular-meteor?

I've configured all users to be created with an empty favorites array: user.favorites: []
Since the users collection is treated differently, how should I publish, subscribe, and access subscribed favorites data in angular-meteor?
Here's what I have so far:
// Meteor.methods ==========================================
addFavorite: function(attendeeId){
var loggedInUser = Meteor.user();
if( !loggedInUser ){
throw new Meteor.Error("must be logged in");
}
loggedInUser.favorites.push(attendeeId);
loggedInUser.username = loggedInUser.username+"x";
console.log(loggedInUser.favorites);
}
// controller ========================================
$scope.addFavorite = function(attendeeId){
$meteor.call("addFavorite", attendeeId);
}
// server =======================================================
Meteor.publish('myFavorites', function(){
if(!this.userId) return null;
return Meteor.users.find(this.userId);
});
Meteor.users.allow({
insert: function(userId, doc){
return true;
},
update: function(useId, doc, fieldNames, modifier){
return true;
},
remove: function(userId, doc){
return true;
}
});
User.favorites is empty. When addFavorite is called, it logs an array with a single userId that doesn't update the mongoDB at all. It looks as if Meteor.user() isn't reactivly updating. Does anyone know what I'm doing wrong? Thank you!
EDIT
Latest iteration of code. Favorites are passed into $scope.favorites but isn't reactive. How do I fix this? Thanks!
// publish
Meteor.publish('myFavorites', function(){
if(this.userId){
return Meteor.users.find(this.userId, {
fields: {
favorites: 1
}
});
}else{
this.ready();
}
});
// subscribe
$meteor.subscribe('myFavorites')
.then(function(subscriptionHandle)
{
var user = $meteor.collection(function(){
return Meteor.users.find({_id: Meteor.userId()});
});
$scope.favorites = user[0].favorites;
});
tldr;
Accounts collection is reactive, but by default only the username, emails, and profile fields are published. The quickest fix is to attach the favorites as a new field on the User.profile object.
// Meteor.methods ==========================================
addFavorite: function(attendeeId){
var loggedInUser = Meteor.user();
if( !loggedInUser ){
throw new Meteor.Error("must be logged in");
}
if (loggedInUser.profile.favorites){
loggedInUser.profile.favorites.push(attendeeId);
}
else {
loggedInUser.profile.favorites = [];
loggedInUser.profile.favorites.push(attendeeId);
}
loggedInUser.username = loggedInUser.username+"x";
console.log(loggedInUser.profile.favorites);
}
Although right now you probably are writing to the user, which you can verify by using meteor mongo --> db.users.find().pretty(), but the subscription does not publish your favorites field.
Alternative approach
Alternatively, you can publish the favorites field
// Server code --------
Meteor.publish("userData", function () {
if (this.userId) {
return Meteor.users.find({_id: this.userId},
{fields: {'favorites': 1}});
} else {
this.ready();
}
});
Opinionated Meteor.users philosophy
I like to structure my users object around 3 properties:
User.profile --> published to the client, and directly modifiable by the client through client-side code
User.public --> published to the client, but not modifiable except through server-side Meteor methods
User.private --> not published to the client (i.e. only accessible to read on server code), and only modifiable by server code (with client simulation)
Just make sure that when you remove the insecure and autopublish packages that you double-check your Collections security by using the Meteor.users.allow() function in your server code
Run meteor list to if you want to verify whether or not insecure and autopublish packages are being used in your current project. NOTE: By default Meteor does install them when you first create your app)
// Server code --------
Meteor.publish("userData", function () {
if (this.userId) {
return Meteor.users.find({_id: this.userId},
{fields: {'public': 1}});
} else {
this.ready();
}
});

Enforcing unique usernames with Firebase simplelogin

I have recently followed a tutorial over on Thinkster for creating a web app using Angular and Firebase.
The tutorial uses the Firebase simpleLogin method allows a 'profile' to be created that includes a username.
Factory:
app.factory('Auth', function($firebaseSimpleLogin, $firebase, FIREBASE_URL, $rootScope) {
var ref = new Firebase(FIREBASE_URL);
var auth = $firebaseSimpleLogin(ref);
var Auth = {
register: function(user) {
return auth.$createUser(user.email, user.password);
},
createProfile: function(user) {
var profile = {
username: user.username,
md5_hash: user.md5_hash
};
var profileRef = $firebase(ref.child('profile'));
return profileRef.$set(user.uid, profile);
},
login: function(user) {
return auth.$login('password', user);
},
logout: function() {
auth.$logout();
},
resolveUser: function() {
return auth.$getCurrentUser();
},
signedIn: function() {
return !!Auth.user.provider;
},
user: {}
};
$rootScope.$on('$firebaseSimpleLogin:login', function(e, user) {
angular.copy(user, Auth.user);
Auth.user.profile = $firebase(ref.child('profile').child(Auth.user.uid)).$asObject();
console.log(Auth.user);
});
$rootScope.$on('$firebaseSimpleLogin:logout', function() {
console.log('logged out');
if (Auth.user && Auth.user.profile) {
Auth.user.profile.$destroy();
}
angular.copy({}, Auth.user);
});
return Auth;
});
Controller:
$scope.register = function() {
Auth.register($scope.user).then(function(user) {
return Auth.login($scope.user).then(function() {
user.username = $scope.user.username;
return Auth.createProfile(user);
}).then(function() {
$location.path('/');
});
}, function(error) {
$scope.error = error.toString();
});
};
At the very end of the tutorial there is a 'next steps' section which includes:
Enforce username uniqueness-- this one is tricky, check out Firebase priorities and see if you can use them to query user profiles by username
I have searched and searched but can't find a clear explanation of how to do this, particularly in terms of the setPriority() function of Firebase
I'm quite the Firebase newbie so any help here would be gratefully recieved.
There are a few similar questions, but I can't seem to get my head around how to sort this out.
Enormous thanks in advance.
EDIT
From Marein's answer I have updated the register function in my controller to:
$scope.register = function() {
var ref = new Firebase(FIREBASE_URL);
var q = ref.child('profile').orderByChild('username').equalTo($scope.user.username);
q.once('value', function(snapshot) {
if (snapshot.val() === null) {
Auth.register($scope.user).then(function(user) {
return Auth.login($scope.user).then(function() {
user.username = $scope.user.username;
return Auth.createProfile(user);
}).then(function() {
$location.path('/');
});
}, function(error) {
$scope.error = error.toString();
});
} else {
// username already exists, ask user for a different name
}
});
};
But it is throwing an 'undefined is not a function' error in the line var q = ref.child('profile').orderByChild('username').equalTo($scope.user.username);. I have commented out the code after and tried just console.log(q) but still no joy.
EDIT 2
The issue with the above was that the Thinkster tutorial uses Firebase 0.8 and orderByChild is available only in later versions. Updated and Marein's answer is perfect.
There are two things to do here, a client-side check and a server-side rule.
At the client side, you want to check whether the username already exists, so that you can tell the user that their input is invalid, before sending it to the server. Where exactly you implement this up to you, but the code would look something like this:
var ref = new Firebase('https://YourFirebase.firebaseio.com');
var q = ref.child('profiles').orderByChild('username').equalTo(newUsername);
q.once('value', function(snapshot) {
if (snapshot.val() === null) {
// username does not yet exist, go ahead and add new user
} else {
// username already exists, ask user for a different name
}
});
You can use this to check before writing to the server. However, what if a user is malicious and decides to use the JS console to write to the server anyway? To prevent this you need server-side security.
I tried to come up with an example solution but I ran into a problem. Hopefully someone more knowledgeable will come along. My problem is as follows. Let's say your database structure looks like this:
{
"profiles" : {
"profile1" : {
"username" : "Nick",
"md5_hash" : "..."
},
"profile2" : {
"username" : "Marein",
"md5_hash" : "..."
}
}
}
When adding a new profile, you'd want to have a rule ensuring that no profile object with the same username property exists. However, as far as I know the Firebase security language does not support this, with this data structure.
A solution would be to change the datastructure to use username as the key for each profile (instead of profile1, profile2, ...). That way there can only ever be one object with that username, automatically. Database structure would be:
{
"profiles" : {
"Nick" : {
"md5_hash" : "..."
},
"Marein" : {
"md5_hash" : "..."
}
}
}
This might be a viable solution in this case. However, what if not only the username, but for example also the email has to be unique? They can't both be the object key (unless we use string concatenation...).
One more thing that comes to mind is to, in addition to the list of profiles, keep a separate list of usernames and a separate list of emails as well. Then those can be used easily in security rules to check whether the given username and email already exist. The rules would look something like this:
{
"rules" : {
".write" : true,
".read" : true,
"profiles" : {
"$profile" : {
"username" : {
".validate" : "!root.child('usernames').child(newData.val()).exists()"
}
}
},
"usernames" : {
"$username" : {
".validate" : "newData.isString()"
}
}
}
}
However now we run into another problem; how to ensure that when a new profile is created, the username (and email) are also placed into these new lists? [1]
This in turn can be solved by taking the profile creation code out of the client and placing it on a server instead. The client would then need to ask the server to create a new profile, and the server would ensure that all the necessary tasks are executed.
However, it seems we have gone very far down a hole to answer this question. Perhaps I have overlooked something and things are simpler than they seem. Any thoughts are appreciated.
Also, apologies if this answer is more like a question than an answer, I'm new to SO and not sure yet what is appropriate as an answer.
[1] Although maybe you could argue that this does not need to be ensured, as a malicious user would only harm themselves by not claiming their unique identity?
I had a similar problem. But it was after registering the user with password and email. In the user profile could save a user name that must be unique and I have found a solution, maybe this can serve you.
Query for username unique in Firebase
var ref = new Firebase(FIREBASE_URL + '/users');
ref.orderByChild("username").equalTo(profile.username).on("child_added", function(snapshot) {
if (currentUser != snapshot.key()) {
scope.used = true;
}
});
ref.orderByChild("username").equalTo(profile.username).once("value", function(snap) {
//console.log("initial data loaded!", Object.keys(snap.val()).length === count);
if (scope.used) {
console.log('username already exists');
scope.used = false;
}else{
console.log('username doesnt exists, update it');
userRef.child('username').set(profile.username);
}
});
};

Resources