Here's my initializer:
...
Ember.SimpleAuth.Session.reopen({
currentUser: function() {
var userId = this.get('user_id');
if (!Ember.isEmpty(userId)) {
return container.lookup('store:main').find('user', userId);
}
}.property('user_id')
});
...
Controller:
isAdmin: function() {
var session = this.get('session.currentUser'),
role = session.get('role'); // 'role' is undefined
return role.get('name') == "Administrator";
}.property()
But when I tried from Templates:
{{session.currentUser.role.name}}
It works perfectly.
How do I access the currentUser to all Controllers or even in Routes?
I think it's because session.currentUser is a promise. Try this in your controller:
isAdmin: function() {
return this.get('session.currentUser').then(function(r) {
return r.get('role.name') == 'Administrator';
});
}.property()
Why don't you add isAdmin to your SimpleAuth Session:
isAdmin: function() {
return #get('current_user.role.name') == 'Administrator';
}.property('current_user')
Then you should be able to do
{{session.isAdmin}}
in your templates.
while login or register save user information in codeigniter session.
then access current login user information form session across the pages.
$userinfo = array(name=>'abc','userid'=>234);
$this->session->set_userdata($userinfo );//use for store user inforamtion
$current = $this->session->userdata('userid'); //for access
echo $current;
Related
So, what I'm trying to do here is something simple:
check the role of the loggedUser on each route (with a resolve that sets the user if a token or login credentials are valid on the backend)
redirect to the intended route
if not allowed for a route, redirect to a different route
In my route provider I have something like
$routeProvider
...
.when('/admin', {
templateUrl: 'views/admin/dashboard.html',
controller: 'AdminDashboardCtrl',
resolve: {
checkLoggedUser: check
}
})
...
where ckeck is this function
var check = function($rootScope, $q, AuthService) {
var deferred = $q.defer();
if($rootScope.loggedUser) {
return;
}
console.log('inside resolve check')
AuthService.check().success(function(data) {
$rootScope.loggedUser = data.user;
deferred.resolve(data.user);
});
console.log('finished check')
return deferred.promise;
};
And my AuthService.check() is this function
check: function()
{
var authtoken = StorageService.get('authtoken');
if(!authtoken) {
$location.path('login');
}
console.log('before returning');
return $http.post($rootScope.base + 'auth/authenticate', { 'authtoken': authtoken });
},
In my .run(function I have
$rootScope.$on('$routeChangeSuccess', function() {
setIntendedUrl();
console.log($rootScope.loggedUser);
console.log($location.path());
});
and setIntendedUrl() check for the loggedUser and redirects to the correct page (or, in what I'm trying to accomplish, redirect to a different page if not allowed, for example the loggedUser has role = 1, can visit only the routes /admin, if a user has role = 2, and the requested path is /admin, he has to be redirected to /user)
So after all this code, when the app run this is my log in the console (see in the code where are they called)
inside resolve check app.js:29
before returning authservice.js:24
finished check app.js:36
intended: /admin/agents/create app.js:149 <--- here is where I redirect the user
Object {id: "21", name: "Kyle", surname: "Butler", roleId: "2"...} app.js:167
/admin/agents/create <--- requested path
This is not what I was expecting, so the first three logs are good, the third doesn't wait the promise to be returned (so I don't have a loggedUser) then the AuthService:check() returns the user and it's everything done at this point, the user with role = 2 is in a route that is not allowed to see.
Just to complete the code, this is the setIntendedUrl function
var setIntendedUrl = function() {
intended = $location.path();
console.log('intended: ' + intended)
if(intended !== '/login') {
if($rootScope.loggedUser && $rootScope.loggedUser.roleId === '1' && !/^\/admin*/.test(intended)) {
intended = '/admin';
} else if($rootScope.loggedUser && $rootScope.loggedUser.roleId === '2' && !/^\/manager*/.test(intended)) {
intended = '/manager';
}
StorageService.set('intended', intended);
//$location.path(intended);
}
};
What I am doing wrong? Why the user in the check function is not resolved before the other code is executed?
Can you make use of session/locals storage or $rootScope where you can store the users authorization object with given routes, permission info once user logged in.
Now is route resolve or run() block you can retrieve the user auth object perform authorization action.
e.g.
.run(['sessionService', '$rootScope', '$location', function(sessionService, $rootScope, $location) {
$rootScope.$on( "$routeChangeStart", function(event, next, current) {
var currentUser = sessionService.get('user_details');
if(next.taskAccess && next.taskAccess != ""){
var hasPerm = $rootScope.getPermission(next.taskAccess);
if(!hasPerm){
$location.path('/unauthorized');
}
}
});
}]);
Im building an login with angularjs and PHP. The problem I have is that the session not seem to have been set.
I have this controller that uses a service when I hit the login button:
Controller:
$scope.doLogin = function() {
loginService.login({username: $scope.username, password: $scope.password});
};
Here is my services:
'use strict';
angular.module('gameApp_services').factory('sessionService', ['$http', function($http) {
return {
set:function(key, value) {
return sessionStorage.setItem(key,value);
},
get:function(key) {
return sessionStorage.getItem(key);
},
destroy:function(key) {
$http.post('lib/destroy_session.php'); //Förstör sessionen
return sessionStorage.removeItem(key);
}
};
}]).factory('loginService', function($http,$location,sessionService) {
return {
login: function(data, scope) {
var $promise = $http.post("lib/action.php", data); //send data to action.php
$promise.then(function(msg) {
var uid = msg.data;
console.log(uid);
if(uid) {
//scope.msgtxt='Correct information';
sessionService.set('sess_id', uid);
$location.path('/game');
} else {
scope.msgtxt='Incorrect information';
$location.path('/firstpage');
}
});
},
logout:function() {
sessionService.destroy('sess_id');
$location.path('/firstpage');
},
islogged:function() {
var $checkSessionServer = $http.post('lib/check_session.php');
return $checkSessionServer;
/*if(sessionService.get('user')) {
return true;
}*/
}
}
});
As you can see, I'm making a call to my backend, where I check the username and password, and set's the session. The uid that is returned, contains the sessionID=1:
public function DoLogin($username, $password)
{
//Kolla så att användarnamn och lösenord är korrekt, returnera true eller false
$get_user = "SELECT id, username,password FROM users WHERE username='".$username."' AND password='".$password."'";
$user_result = mysql_query($get_user)
or die(mysql_error());
if(mysql_num_rows($user_result) == 1)
{
$_SESSION['sess_id'] = mysql_result($user_result, 0);
$_SESSION['sess_user'] = $username;
return $_SESSION['sess_id'];
}
else
{
return false;
}
}
This works, the correct data is returned back as expected, thus, the session id 1.
In my app.js I have code that prevents you from going to the /game page by typing it in the URL:
gameApp.run(function($rootScope, $location, loginService) {
var routespermission=['/game']; //route that require login
$rootScope.$on('$routeChangeStart', function() {
if(routespermission.indexOf($location.path()) !=-1)
{
var connected = loginService.islogged();
connected.then(function(msg) {
console.log(msg);
if(!msg.data) {
$location.path('/');
}
});
}
});
});
As you can see, Im using my loginService here, where I'm refering to islooged in the service. In islogged I make a call to my PHP backend, check_session.php, where I check if the session exists:
<?php
session_start();
if(isset($_SESSION['sess_id'])) {
echo "authentified";
}
?>
This returns an empty string, the session is not set. When I try var_dump($_SESSION), the result is NULL.
How can this be possible, when I set the session in my backend when I log in, and the resulting value is 1?
Are you sure you want to operate session with angular?
Session is store at browser and server,when you start a request by angular,session will be carried by request header automatically, and you can verify it with you php function at backend, so I think you should check your php code to confirm if session store is avaliable or your broswer can store session by cookies or session store
All,
I'm simply trying to store a user object in sessionStorage in an AngularJS app. If I step through this in either the Chrome or FF debugger, the sessionStorage never gets set. Here is my angular service code:
// Authentication/authorization Module
stonewall.authModule = angular.module("authModule", [
// Module dependencies
"ngStorage"
]);
// Authentication/authorization service tracks the current user
stonewall.authModule.service('authService', function ($localStorage, $sessionStorage) {
// Initialize current user
var currentUser = {};
restoreSession();
// Declare storage type-this may change if user selects
// "Keep me signed in"
var storageType = {};
// Return the current user object
this.getCurrentUser = function () {
return currentUser;
};
// Returns whether there is a currently authorized user
this.userAuth = function() {
return currentUser.sid != "";
};
// Logout function, initializes the user object
this.logout = function() {
currentUser = {
sid: "",
status: 0,
pswLastSet: 0,
id: "",
sigUID: "",
sig: ""
};
//persistSession();
};
// Login
this.login = function(user, subj) {
if (user == null) return;
currentUser = {
sid: user.Principal.SId,
status: user.Principal.ControlStatus,
pswLastSet: new Date(user.Principal.PasswordLastSet),
id: user.Identity.Id.DN,
sigUID: user.Identity.Certificates[0].UID,
sig: stonewall.hash(user.Principal.SId + subj.pswd),
};
persistSession();
};
// Persist to session storage
function persistSession() {
$sessionStorage.currentUser = currentUser;
};
// Restore session
function restoreSession() {
currentUser = $sessionStorage.currentUser;
if (currentUser == null) {
// Initialize to empty user
currentUser = {
sid: "",
status: 0,
pswLastSet: 0,
id: "",
sigUID: "",
sig: ""
};
}
};
});
And, here is a screencap that shows my FF debugging session. You can see that after persistSession is called that $sessionStorage has my user.
But, if I switch over to the DOM inspector, sessionStorage has no items in it...
Any help is, as always, appreciated.
Are you sure you are using angular's sessionStorage in the right way?
Session storage is a property of the $window object in angular, so I don't know if you have made your own service wrapper or something like that?
Anyway, here is a codepen that shows another approach that I use myself, using $window.sessionStorage instead: http://codepen.io/chrisenytc/pen/gyGcx
Tutorial: http://www.thinkster.io/angularjs/wBhtRLWHIR/6-authenticating-users-with-a-service
I'm following this tutorial and it seems like I'm losing my user as soon as they register.
Here is my auth.js factory:
'use strict';
app.factory('Auth', function($firebaseSimpleLogin, 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);
},
signedIn : function() {
// PROBLEM: authUser is always null
console.log(auth.user);
return auth.user !== null;
},
logout : function () {
auth.$logout();
}
};
$rootScope.signedIn = function () {
return Auth.signedIn();
};
return Auth;
});
Here is my auth.js controller:
'use strict';
app.controller('AuthCtrl', function($scope, $location, Auth){
if (Auth.signedIn()) {
$location.path('/');
}
$scope.register = function () {
Auth.register($scope.user).then(function (authUser) {
console.log(authUser);
$location.path('/');
});
};
});
The console.log under signedIn in the factory is always null. Any idea where the disconnect is? The registration itself is working fine, and authUser is populated in the console.log in the controller when registering.
The latest documentation for Angularfire says that the $createUser method of $firebaseSimpleLogin returns a promise but it doesn't mention any parameters being passed to the then callback.
You can use the $getCurrentUser method to get the current user after the user registers.
The tutorial needs to be updated and you should always be checking the documentation for whatever libraries you're using yourself.
Your code for signedIn should look like this:
Auth.signedIn = function() {
auth.$getCurrentUser().then(function(currentUser) {
console.log(currentUser);
}, function() {
console.log('error');
});
};
I found a very similar question that is further along in the tutorial :can't show logout button after $createUser
In the answer I learned that angularfire used to automatically log the user in after it was created. Apparently now it no longer does that which is why the auth.user in signedIn was null.
I am now doing the same tutorial. This code (in auth controller) worked for me:
$scope.register = function () {
Auth.register($scope.user).then(function (authUser) {
console.log(authUser);
Auth.login($scope.user);
$location.path('/');
});
};
I'm a total n00b, but what (I think) this is doing is authenticating the user, then running a function that logs the user in right after. Logout button is now functioning as expected.
Working on my social app I've found a strange behavior in the collection Meteor.users, this problem does not occur with other Collections using the same methodologies
I would like to have an initial list of users downloading a minimum number of information for everyone and when I open the panel to a specific user I subscribe a different showing more information if the specified user is a friend of mine.
But after subscribe the client collection Meteor.users is not updated!
CLIENT
Meteor.startup(function() {
Meteor.subscribe('usersByIds', Meteor.user().profile.friends, function() {
//... make users list panel using minimal fields
});
//performed when click on a user
function userLoadInfo(userId) {
Meteor.subscribe('userById', userId, function() {
var userProfile = Meteor.users.findOne(userId).profile;
//...
//make template user panel using full or minimal user fields
//...
//BUT NOT WORK!
//HERE Meteor.users.findOne(userId) keep minial user fields!!
//then if userId is my friend!
});
}
});
SERVER
//return minimal user fields
getUsersByIds = function(usersIds) {
return Meteor.users.find({_id: {$in: usersIds} },
{
fields: {
'profile.username':1,
'profile.avatar_url':1
}
});
};
//return all user fields
getFriendById = function(userId) {
return Meteor.users.find({_id: userId},
{
fields: {
'profile.username':1,
'profile.avatar_url':1
//ADDITIONAL FIELDS
'profile.online':1,
'profile.favorites':1,
'profile.friends':1
}
});
};
//Publish all users, with minimal fields
Meteor.publish('usersByIds', function(userId) {
if(!this.userId) return null;
return getUsersByIds( [userId] );
});
//Publish user, IF IS FRIEND full fields
Meteor.publish('userById', function(userId) {
if(!this.userId) return null;
var userCur = getFriendById(userId),
userProfile = userCur.fetch()[0].profile;
if(userProfile.friends.indexOf(this.userId) != -1) //I'm in his friends list
{
console.log('userdById IS FRIEND');
return userCur; //all fields
}
else
return getUsersByIds( [userId] ); //minimal fields
});
This is a limitation or bug in DDP. See this.
A workaround is to move data out of users.profile.
Like this:
//limited publish
Meteor.publish( 'basicData', function( reqId ){
if ( this.userId ) {
return Meteor.users.find({_id: reqId },{
fields: { 'profile.username':1,'profile.avatar_url':1}
});
}
else {
this.ready();
}
});
//friend Publish
Meteor.publish( 'friendData', function( reqId ){
if ( this.userId ) {
return Meteor.users.find( {_id: reqId, 'friendProfile.friends': this.userId }, {
fields: {
'friendProfile.online':1,
'friendProfile.favorites':1,
'friendProfile.friends':1
}
});
}
else {
this.ready();
}
});
//example user
var someUser = {
_id: "abcd",
profile: {
username: "abcd",
avatar_url: "http://pic.jpg"
},
friendProfile: {
friends: ['bcde', 'cdef' ],
online: true,
favorites: ['stuff', 'otherStuff' ]
}
}
As given in a comment, this link reveals your problem. The current DDP Protocol does not allow publishing of subdocuments. One way to get around this is to create a separate collection with your data but a better way would probably to just remove some of the data and make it a direct object off of your user.
The best way to do this is add the data to your user's profile upon insert and then in the onCreateUser move the data onto the user directly:
Accounts.onCreateUser(function(options, user) {
if (options.profile) {
if (options.profile.publicData) {
user.publicData = options.profile.publicData;
delete options.profile.publicData;
}
user.profile = options.profile;
}
return user;
});
If you are allowing clients to perform user inserts make sure you validate the data better though. This way you can have the online, favorites, and friends in the profile and publish that specifically when you want it. You can then have username and avatar_url in the publicData object directly on the user and just always publish all-the-time.