jadjoubran / laravel5-angular-material-starter

Get started with Laravel 5.3 and AngularJS (material)
https://laravel-angular.readme.io/
MIT License
1.66k stars 400 forks source link

loading view after login service has been resolved #346

Closed harryy2510 closed 8 years ago

harryy2510 commented 8 years ago

I want to check authentication and save/update user data in local storage every time app is loaded for first time. So i made a service which checks for authentication through token and saves data in local storage and i am running this service in run block.

Now the problem lies here:

AccountService

        constructor($auth,API,$sessionStorage){
            'ngInject';
            this.API = API;
            this.$auth = $auth;
            this.$sessionStorage = $sessionStorage;
        }
        checkLogin(){
            return this.API.one('auth/checkLogin').post().then((response) => {
                this.$sessionStorage.user = response.user;
                this.$sessionStorage.logged_in = true;
                return true;
            }, (error) => {
                delete this.$sessionStorage.user;
                delete this.$sessionStorage.logged_in;
                this.$auth.removeToken();
                return false;
            });
        }

routes_config

...
.state('auth', {
            resolve:{
                checkLogin:  function(AccountService){
                    return AccountService.checkLogin();
                }
            },
            abstract: true,
            data: {auth:true},
            views: {
                header: {
                    templateUrl: getView('header-user')
                },
                footer: {
                    templateUrl: getView('footer')
                },
                main: {}
            }
        })
...
flick36 commented 8 years ago

In every route except login, register, forgot, reset password, and the abstract one wich is the parent one set data: { auth: true }

harryy2510 commented 8 years ago

@flick36 Hi, i have already did that part of authenticating routes, but i want to refresh user data in local storage or session storage everytime the app loads and then use that data in page

flick36 commented 8 years ago

Yeah, i answer before you edit your post...

Well it's gonna be hard since you are using your own logic to authenticate an user, i do not know what your auth/checkLogin API route does :/ or why do you even have the auth state.

Maybe this can help you: https://github.com/jadjoubran/laravel5-angular-material-starter/pull/297

What i do to accomplish what you want to do is this: https://github.com/jadjoubran/laravel5-angular-material-starter/issues/329#issuecomment-224057736

harryy2510 commented 8 years ago

auth/checkLogin

public function checkLogin()
    {
        try {

            if (! $user = JWTAuth::parseToken()->authenticate()) {
                return response()->json(['user_not_found'], 400);
            }

        } catch (TokenExpiredException $e) {

            return response()->json(['token_expired'], 400);

        } catch (TokenInvalidException $e) {

            return response()->json(['token_invalid'], 400);

        } catch (JWTException $e) {

            return response()->json(['token_absent'], 400);

        }
        $user->role = Role::find($user->role_id)->first()->name;
        unset($user->roles);
        unset($user->role_id);
        return response()->json(compact('user'));
    }

auth state is just the name for the state where all the routes are accessed only after authentication. name won't matter i will change it later on

harryy2510 commented 8 years ago

the main issue is when i have to activate a user account (link sent to email), and if the satellizer token is valid (which means user is already logged in, which i am checking in accountservice), user should be redirected to dashboard page instead of letting him send the activation account request

flick36 commented 8 years ago

Like i said, take a look at https://github.com/jadjoubran/laravel5-angular-material-starter/pull/297 i think that's what you want, basically what this PR does, is to redirect the user if its a;ready logged in therefore, when the token is valid, with this PR you can implement your own logic in routes.config.js

harryy2510 commented 8 years ago

lets take an example...

flick36 commented 8 years ago

Your

resolve:{
    checkLogin:  function(AccountService){
        return AccountService.checkLogin();
    }
},

works? i mean if you console.log(AccountService.checkLogin()) it returns what expected?

and how are you acquiring that checkLogin in your html?

harryy2510 commented 8 years ago

yes.. i tried it with $timeout too.. results are expected.. but the thing is before accountservice is called, view is already loaded

flick36 commented 8 years ago

Here's the thing, when you are using Restagular on the resolve, you are returning a promise which is rejected if you dont return an instance, resolve will get resolved even when your request is still loading so maybe if you do this:

resolve: {
    checkLogin: ["AccountService", function (AccountService) {
        var deferred = $q.defer();
        AccountService.checkLogin().then(function(data) {
            deferred.resolve(data); // Data should be equal to true in this case
        }, function(err) {
            deferred.resolve(err); // Err should be equal to false in this case
        });
       return deferred.promise; 
    }],
  }

If i'm correct this should work... but i have the feeling it won't so try it please and tell me if you get error, you'll probably will

harryy2510 commented 8 years ago

it is not calling the api now :( page is loading and loading but no requests are made to backend

flick36 commented 8 years ago

yeah sorry i forgt to inject $q xD

resolve: {
    checkLogin: ["$q","AccountService", function ($q, AccountService) {
        var deferred = $q.defer();
        AccountService.checkLogin().then(function(data) {
            deferred.resolve(data); // Data should be equal to true in this case
        }, function(err) {
            deferred.resolve(err); // Err should be equal to false in this case
        });
       return deferred.promise; 
    }],
  }

Does it throws any error? try to console.log() something at the beginning and at the end of the resolve fucntion please

harryy2510 commented 8 years ago

its also working but view is loading before resolve returns the promise.

flick36 commented 8 years ago

What view are you loading? can you post the state?