2014-12-12 2 views
0

각도가 새 것이므로 아마도 완전히 잘못되었습니다./sites 컨트롤러 페이지에서 verifyAuth.getUserSiteAccess()에 액세스하여 사이트 목록을 반환하고 뷰에 대한 html 링크를 작성하려고합니다.

userSites에 로그인하면 var 인증이 없으므로 Google 인증 모듈을 사용하고 있습니다. 그러면 Google에 ping을 보내고 /api/index.php/login을 호출하여 사용자 사이트 목록을 반환 한 다음이 경우 완료합니다. $ q.defer(). resolve (true);와 함께. 문제는 사이트 컨트롤러 기능이 정의되기 전에 userSites에 액세스하려고하는 것입니다. $ q.defer() 후에 $ scope.test()를 호출 할 수있는 방법이 있습니까? 또는 이것을 할 수있는 더 좋은 방법이 있습니까?

setTimeout ($ scope.test, 500)을 실행하면 정상적으로 작동합니다.

경로 -> 사용자 액세스 토큰 확인, 정의되지 않은 경우 userSites로드 -> 섹션 액세스 확인 -> 완료 연기.

'use strict'; 

angular.module('mps', [ 
    'ngRoute', 
    'angularOauth', 
    'googleOauth', 
    'mps.global', 
    'mps.home', 
    'mps.sites', 
    'mps.site' 
]). 
config(['$routeProvider', function($routeProvider) { 
    $routeProvider.when('/', { 
    templateUrl: 'views/home/index.html', 
    controller: 'home', 
    resolve: { 
     auth: function(verifyAuth) { 
     verifyAuth.verifyUserAccess(true); 
     } 
    } 
    }); 
    $routeProvider.when('/sites', { 
    templateUrl: 'views/sites/index.html', 
    controller: 'sites', 
    resolve: { 
     auth: function(verifyAuth) { 
     console.log('sites route selected'); 
     verifyAuth.verifyUserAccess(false); 
     } 
    } 
    }); 

...

.factory('verifyAuth', ['$rootScope', '$window', '$q', '$location', '$timeout', '$http', 'Token', 

function($rootScope, $window, $q, $location, $timeout, $http, Token) { 

    var userSites = null; 

    return { 
    deferLocation: function(isToken, index) { 
     var deferred = $q.defer(); 
     var _location = $location; 
     if(isToken) { 
     switch(index) { 
      case true: 
      // Homepage/site toggling. 
      deferred.reject(); 
      _location.path('/sites'); 
      _location.replace(); 
      break; 
      default: 
      // All pages. 
      deferred.resolve(true); 
      break; 
     } 
     } else { 
     // No token, redirect to login screen. 
     this.userError(); 
     } 
    }, 
    verifySectionAccess: function(userSites, siteName, index) { 
     if(siteName) { 
     // Subpage, verify section. 
     for(var i in userSites.sites) { 
      if(userSites.sites[i].sitename === siteName) { 
      this.deferLocation(true, index); 
      return false; 
      } 
     } 
     } else { 
     // Sites page. 
     this.deferLocation(true, index); 
     return false; 
     } 
     // No access to section. 
     this.userError(); 
     return false; 
    }, 
    // Check user permission are set. 
    verifyUserAccess: function (index, siteName) { 
     var token = Token.get(); 
     var _this = this; 
     if(token) { 
     if(userSites) { 
      // Verify user section access. 
      _this.verifySectionAccess(userSites, siteName, index); 
     } else { 
      // Use google token to get user email and load site permissions. 
      Token.verifyAsync(token). 
      then(function(data) { 
       $http({method: 'GET', async: false, url: '/api/index.php/login/' + data.email}).success(function(d) { 
       userSites = d; 
       // Verify user access to specific section. 
       _this.verifySectionAccess(userSites, siteName, index); 
       }); 
      }, function(error) { 
       _this.userError(); 
       return false; 
      } 
     ); 
     } 
     } else { 
     this.deferLocation(false, index); 
     } 
    }, 
    getUserSiteAccess: function() { 
     console.log(userSites); 
     return userSites; 
    } 

답변

0

라우터 호출, 결심이 검사를 verifyUser.buildUserData을 반환합니다. 그런 다음 사이트 목록에 전역 변수가 있는지 확인하고 토큰을 Google에 핑 소리가 나지 않으면 데이터베이스에 사용자 이메일과 사용자 이메일을 보내 사이트 목록을 가져옵니다. 목록에서 루프를 반복하고 사이트 이름이 맞는지 확인합니다. buildUserData로 전달되었습니다.

아래 예제는보기가 렌더링되기 전에 모든 인증을 처리합니다. 저를 올바른 방향으로 인도 해준 데 대해 감사드립니다.

라우터 :

...

config(['$routeProvider', function($routeProvider) { 
    $routeProvider.when('/', { 
    templateUrl: 'views/home/index.html', 
    controller: 'home', 
    resolve: { 
     auth: function(verifyUser) { 
     return verifyUser.homepageRedirect(); 
     } 
    } 
    }); 
    $routeProvider.when('/sites', { 
    templateUrl: 'views/sites/index.html', 
    controller: 'sites', 
    resolve: { 
     auth: function(verifyUser) { 
     return verifyUser.buildUserData(); 
     } 
    } 
    }); 
$routeProvider.when('/sites/:site/scheduling', { 
    templateUrl: 'views/sites/scheduling/index.html', 
    controller: 'site', 
    resolve: { 
     auth: function(verifyUser, $route) { 
     return verifyUser.buildUserData($route.current.params.site); 
     } 
    } 
    }); 

...

공장

.factory('getUserEmail', ['$rootScope', '$window', '$q', '$location', '$timeout', '$http', 'Token', function($rootScope, $window, $q, $location, $timeout, $http, Token) { 
    return { 

    // Get user email address based on token. 
    getEmail: function() { 

     var deferred = $q.defer(); 

     var token = Token.get(); 

    $http({method: 'GET', async: false, url: 'https://www.googleapis.com/oauth2/v1/tokeninfo', params: {access_token: token }}). 
     success(function(data) { 
     $rootScope.username = data.email; 
     deferred.resolve(data); 
     return data; 
     }).error(function(data) { 
     deferred.reject(data); 
     }); 

     return deferred.promise; 

    } 

    } 
}]) 
.factory('getUserSites', ['$rootScope', '$window', '$q', '$location', '$timeout', '$http', 'Token', function($rootScope, $window, $q, $location, $timeout, $http, Token) { 
    return { 

    // Get user site access. 
    getSites: function() { 

     var deferred = $q.defer(); 

     console.log('site list is undefined.'); 
     $http({method: 'GET', async: false, url: '/api/index.php/login/' + $rootScope.username}). 
     success(function(data) { 
      $rootScope.sites = data.sites; 
      deferred.resolve(data); 
     }).error(function(data) { 
      deferred.reject(data); 
     }); 

     return deferred.promise; 

    } 

    } 
}]) 
.factory('verifyUser', ['$rootScope', '$window', '$q', '$location', '$timeout', '$http', 'Token', 'getUserEmail', 'getUserSites', function($rootScope, $window, $q, $location, $timeout, $http, Token, getUserEmail, getUserSites) { 
    return { 

    siteError: function() { 
     localStorage.removeItem('accessToken'); 
     $location.path('/'); 
    }, 

    // Redirect user to /sites if logged in. 
    homepageRedirect: function() { 
     var deferred = $q.defer(); 
     var token = Token.get(); 

     if(!token) { 
     deferred.resolve(true); 
     } else { 
     deferred.reject(true); 
     $location.path('/sites'); 
     } 

     return deferred.promise; 

    }, 

    // Verify user token exists and they have access to the section. 
    buildUserData: function(site) { 

     console.log('site',site,'/site'); 

     var deferred = $q.defer(); 

     var token = Token.get(); 

     var _this = this; 

     if(!token) { 
     deferred.reject('no token'); 
     localStorage.removeItem('accessToken'); 
     $location.path('/'); 
     } else { 

     if($rootScope.sites) { 
      console.log('site list present, check access.'); 
      if(site) { 
      var data = $rootScope.sites; 
      console.log(data, site); 
      for(var i in data) { 
       console.log(data[i].sitename); 
       if(data[i].sitename === site) { 
       console.log('user has access, render view.'); 
       deferred.resolve(true); 
       return false; 
       } 
      } 
      console.log('No site access, logout.'); 
      deferred.reject('No access to site.'); 
      _this.siteError(); 
      } else { 
      console.log('No access needed, landing page.'); 
      deferred.resolve(true); 
      } 
     } else { 
      console.log('no site list, get user email from google and query db with user.'); 
      getUserEmail.getEmail().then(function(data) { 
      return getUserSites.getSites(); 
      }).then(function(data) { 
      if(site) { 
       console.log('sub page'); 
       for(var i in data.sites) { 
       console.log(data.site[i]); 
       if(data.sites[i].sitename === site) { 
        console.log('user has access, render view.'); 
        deferred.resolve(true); 
        return false; 
       } 
       } 
       console.log('No site access, logout.'); 
       deferred.reject('No access to site.'); 
       _this.siteError(); 
      } else { 
       deferred.resolve(true); 
      } 
      }).catch(function(data) { 
      deferred.reject(true); 
      _this.siteError(); 
      }); 
     } 
     } 

     return deferred.promise; 

    } 

    } 
}]); 
1

당신은 ...하지 전체 파일 -

사이트 컨트롤러

'use strict'; 

angular.module('mps.sites', ['ngRoute']) 
.controller('sites', ['verifyAuth', '$rootScope', '$scope', '$q', function(verifyAuth, $rootScope, $scope, $q) { 

    $scope.test = function() { 
     var test = verifyAuth.getUserSiteAccess(); 
     console.log('test', test, '/test'); 
    }; 

    $scope.test(); 

}]); 

** 라우팅을 App.js 및 인증 ** 여기에 몇 가지 문제가 있습니다. 모두 약속이 어떻게 작동하는지에 대한 오해에서 파생되는 것 같습니다.

1) 비동기 작업을 수행하고 .then -able 인 함수는 약속을 반환해야합니다. 귀하의 경우, 귀하의 deferLocation은 (비록 그것을 반환하지는 않지만) 약속을하지만, 심지어 비동기 작업을하지 않습니다. 한편, 비동기 (verifyUserAccess)를 수행하는 유일한 기능은 약속이 전혀 없습니다.

2) resolve 매개 변수를 비동기 값 (auth 인 것처럼 보임)로 해결하려면 함수가 약속을 반환해야합니다. 그런 다음 $route은 약속이 해결 될 때까지 대기합니다. 귀하의 경우에는 아무 것도 반환하지 않습니다.

약속에 대해 더 자세히 읽어 보시기 바랍니다. 가짜로 뭔가를 작게 만드십시오. 문제가 생기면 $timeout 전화를 걸어 특정 질문을하십시오.

다음은이를 구축하는 방법에 대한 높은 수준의 생각 : 토큰이 있는지 사용자를 기록하지 않을 경우

app.factory("verifyAuth", function($q, Token, AuthSvc, SitesSvc) { 
    return { 

    verifyUserAccess: function(site){ 

     var deferred = $q.defer(); 

     var token = Token.token; 

     if (!token){ 
     deferred.reject("no-token"); 
     } else { 

     AuthSvc.verifyToken(token) 
      .then(function(result){ 
      if (result.isValid){ 
       // returns a promise to get a list of userSites 
       return SitesSvc.getSites(result.user); 
      } else { 
       return deferred.reject("token-not-valid"); 
      } 
      }) 
      .then(function(userSites){ 
      if (checkAccessPermissions(site, userSites)){ 
       deferred.resolve(true); 
      } else { 
       deferred.resolve(false); 
      } 
      }) 
      .catch(function(error){ 
      // some other error 
      deferred.reject(error); 
      }); 
     } 

     return deferred.promise; 
    } 
    }; 
}); 
+0

피드백을 주셔서 감사합니다. 나는 이것을 다음과 같이 갱신했고 console.log ('then 1') ..2.3을 실행했다. 그러나 view/controller는 여전히 반환 전에 deferred.promise를 렌더링하고있다. http://jsfiddle.net/qkLkdx2u/ – user1572796

+0

이것은 드롭 인 코드가 아니 었습니다. 이것은 높은 수준의 예였습니다. 그것은 단지 "효과가 없을 것"입니다. 사용자가 확인 될 때까지 경로 전환을 지연하려면 약속을 일부 'resolve'매개 변수로 반환해야합니다. –

+0

그래, 내가 뭔가있는 줄 알았다. 마침내 그것을 귀하의 예제를 기반으로 알아 냈어, 다시 한번 감사드립니다. – user1572796