programing

사용자 역할에 따른 AngularJS, ui.router, 로드 템플릿 및 컨트롤러

javajsp 2023. 3. 5. 09:29

사용자 역할에 따른 AngularJS, ui.router, 로드 템플릿 및 컨트롤러

REST API를 사용한 싱글 페이지 앱을 개발했습니다.애플리케이션에 액세스 하려면 , 유저가 로그인할 필요가 있습니다.사용자가 로그인하면 /dashboard로 리디렉션됩니다.이 URL/경로에서는 사용자(일반 사용자 또는 관리자 사용자 등)의 역할에 따라 다른 템플릿과 컨트롤러를 로드하고 싶습니다.

템플릿 섹션의 https://github.com/angular-ui/ui-router/wiki에 접속해 보았습니다만, 어느 옵션도 제가 목표로 하는 것을 지원하지 않습니다.

  • templateUrl 및 function(stateParams)을 사용하면 사용자 역할을 결정하는 데 도움이 되는 서비스를 삽입할 수 없습니다(views/user/dashboard.html 또는 views/admin/dashboard.html 등).
  • templateProvider를 사용하여 사용자 역할을 결정하는 데 도움이 되는 서비스를 주입합니다.그런 다음 템플릿을 로드하려면 어떻게 해야 하나요?

또한 모든 솔루션은 사용자 역할에 따라 UserDashboardController 또는 AdminDashboardController와 같은 다양한 컨트롤러를 로드해야 합니다.

따라서 기본적으로 필요한 것은 사용자 로그인 시 서비스로 설정된 사용자 역할 변수에 따라 다른 템플릿과 컨트롤러를 로드하는 단일 루트입니다.

올바른 방향으로 생각하고 있습니까?아니면 다른 솔루션을 구현해야 합니까?

이에 대한 어떤 도움이라도 주시면 감사하겠습니다.

사용자 역할에 따라 템플릿 및 컨트롤러 로드

말하면 「」입니다.ui-router는 templateUrl을 사용할 수 있는 .templateProviderservice그럭저럭role, 「변수」를 사용합니다.$templateFactoryHTML 텐 html html html html html 。이치노

var app = angular.module('app', ['ui.router']);

app.service('session', function($timeout, $q){
    this.role = null;

    this.loadRole = function(){
        //load role using axax request and return promise
    };
});

app.config(function($stateProvider, $urlRouterProvider){
    $stateProvider.state('dashboard', {
        url: '/dashboard',
        templateProvider: function(session, $stateParams, $templateFactory){
          return session.loadRole().then(function(role){
              if(session.role == 'admin'){
                return $templateFactory.fromUrl('/admin/dashboard.html', $stateParams);
              } else {
                return $templateFactory.fromUrl('/user/dashboard.html', $stateParams);
              }
          });
        }
      });

    $urlRouterProvider.otherwise('/dashboard');
});

★★★★★★에 대해서controller 내에 특정 를 각 템플릿의 루트 요소로 지정할 수 .ng-controller, 마찬가지로 「」를 사용할 도 있습니다controllerProvider「」를 삽입하는 service에 의해 이미 해결되었을 것입니다.다음 예시를 참조하십시오.controllerProvider inside ()ui-router태태: :

controllerProvider: function(session){
  if(session.role == 'admin'){
    return 'AdminCtrl';
  } else {
    return 'UserCtrl';  
  }
}

물론 이 코드에서 중복을 쉽게 제거하고 접근성이 뛰어난 마이크로 DSL을 정의하여 특정 역할 및 뷰에 대한 다른 규칙을 쉽게 정의할 수 있습니다.

다음 데모는 코드를 이해하는 데 도움이 될 것입니다.

이것이 올바른 접근법입니까?

보통 이것은 문맥에 따라 크게 달라진다.답변 작성을 돕기 위해 먼저 다음 질문을 제안하겠습니다.

  • 역할에 따라 표시되는 뷰의 차이는 어느 정도입니까?

예요?button의 기타 액션 요소는 기본적으로 일반 사용자만 페이지를 읽고 슈퍼 사용자가 편집할 수 있도록 합니다., , 입니다.ng-if으로 활성화할 수 .only-role='operator, admin'한편, 뷰가 크게 다른 경우는, 다른 템플릿을 사용하는 것으로 마크업을 큰폭으로 심플화할 수 있습니다.

  • 역할에 따라 특정 페이지에서 사용할 수 있는 액션이 얼마나 달라집니까?

겉으로 보기에는 비슷해 보이는 행동은 역할에 따라 내부 작업이 다릅니까?예를 들어 두 가지 모두에 대해 편집 액션을 사용할 수 있는 경우user ★★★★★★★★★★★★★★★★★」admin그러나 어떤 경우에는 UI와 같은 마법사를 시작하고, 다른 경우에는 고급 사용자를 위한 복잡한 형식을 실행한 후 별도의 역할을 수행합니다.controller한네 반면 ,, 、 약약 。adminuser1개의 컨트롤러가 있는 경우는, 조작이 간단할 것 같습니다.두 경우 모두 성과를 거두는 것은 서비스/뷰 모델/모델에 캡슐화된 행동과 뷰를 결합하는 것 뿐이라는 점에 유의하십시오.

  • 앱의 다른 위치에서 특정 페이지로 연결되는 여러 개의 컨텍스트별 링크가 있습니까?

예를 들어, 단순히 글을 쓰는 것만으로 특정 페이지에 네비게이션을 제공할 수 있습니다.ui-sref="dashboard" role다양한 맥락에서 존재한다면 도움이 될 수 있습니다., 을 단일 이 보다 할 것으로 됩니다. 루트/상태로, 다른 루트/상태로, 조건 됩니다.ui-sref/ng-href역할을 기반으로 합니다.단, 사용자 역할에 따라 동적으로 루트/상태를 정의할 수도 있습니다(동적으로 로드되는지 여부).

  • 특정 페이지의 다른 역할에서 사용할 수 있는 보기와 액션은 개별적으로 전개됩니까, 아니면 함께 전개됩니까?

처음에 일반 사용자를 위한 기능을 구축한 후 프리미엄, 궁극의 기능을 구축하는 경우도 있습니다.페이지 작업을 분할하는 것은 드문 일이 아닙니다.user ★★★★★★★★★★★★★★★★★」admin특히 명확한 경계를 쉽게 긋을 수 있는 경우 팀원들 간에., 따로따로, 따로따로, 따로따로, 따로따로, 따로따로, 따로따로, 따로따로.views ★★★★★★★★★★★★★★★★★」controllers단순히 개발자가 충돌을 피할 수 있습니다.물론 무지개와 유니콘만이 아니다 - 팀은 일어날 가능성이 높은 중복을 제거하기 위해 매우 훈련되어야 한다.

제 제안이 결정에 도움이 되기를 바랍니다.

올바른 방향으로 생각하고 있습니까?아니면 다른 솔루션을 구현해야 합니까?

IMO야, 이렇게 하면 안 돼.

여기에서는, 애플리케이션의 실장에 따라, 2개의 다른 솔루션을 제안합니다.

1) 역할의 권한을 설정할 수 있는 경우(역할을 설정하거나 역할에 권한을 할당하는 다른 페이지가 있을 수 있습니다).그런 다음 역할(일반 사용자, 관리자 사용자 등)에 대해 템플릿과 컨트롤러를 하나만 사용하고 다음을 사용합니다.ng-show,ng-class , .. HTML을 사용합니다.

이 경우 사용자가 일반 사용자인지 관리자 사용자인지는 크게 중요하지 않습니다.그것은 우리의 역할 이름일 뿐입니다.여기서 중요한 것은 권한이며, 동적인 => 따라서 설정된 권한에 따라 동적으로 html을 표시해야 합니다(사용자가 악의적인 http 요청을 작성하여 서버에 게시하는 것을 방지하기 위한 액션을 수행할 때 서버 측 체크도 반드시 필요합니다).그것을 위해 템플릿을 따로 사용한다면, 수많은 경우가 있습니다.

이 솔루션의 요점은 페이지 기능은 사용자의 역할과 동일하며 사용자를 기반으로 페이지 기능을 표시하거나 숨기기만 하면 된다는 것입니다.

2) 역할의 권한이 고정되어 있는 경우(설정할 수 없는 경우), 일반 사용자와 관리자 사용자의 보기 기능이 다른 경우.이러한 보기에 대해 개별 상태를 사용하고 로그인한 사용자를 기준으로 이러한 보기에 대한 액세스를 승인하는 것이 좋습니다(사용자가 작업을 수행할 때 서버 측에서도 인증이 있습니다).

그 이유는 관리 사용자 뷰와 일반 사용자 뷰의 기능이 다르기 때문입니다(이러한 뷰는 서로 분리해야 합니다).

1.2보다 큰 angular 버전을 사용하는 경우 templateUrl을 함수로 사용하여 디렉티브를 실행할 수 있습니다.

기본 아이디어는 사용자 수준에 따라 템플릿을 결정하는 커스텀 디렉티브가 있는 대시보드 뷰입니다.예를 들어 다음과 같습니다.

(function () {
  'use strict';
  angular.module('App.Directives')
    .directive('appDashboard', ['UserManager', function (UserManager) {
      return {
        restrict: 'EA',
        templateUrl: function(ele, attr){
            if (UserManager.currentUser.isAdmin){
                return 'admin.html';
            }else{
                return 'user.html';
            }
        }
      };
    }]);
})(); 

I. "다른 템플릿을 로드하는 단일 경로"를 사용하지 마십시오."가 제 제안이고, 답변입니다.

가능한 경우:

물러서서 디자인 를 다시 .
어플리케이션 사용자의 관심약화시키도록 합니다.

그들은 그렇지 않다.그리고 그들이 정말로 이해한다면url, 주소 표시줄...그들은 그것을 사용하여copy,send ★★★★★★★★★★★★★★★★★」paste...

II. 제안: UI 라우터 상태 사용을 강제합니다.

UI-Router스테이트를 중심으로 구성되어 있습니다.옵션으로 루트나 다른 동작이 접속되어 있을 가능성이 있습니다.

즉, 잘 정의된 상태의 그룹/계층 구조로서의 적용을 재고해 봅시다.은 가질 수 .url defined, 그럴 필요는 없습니다(들어 url이 없는 오류 상태).

III. 주(州)에서 애플리케이션을 구축하면 어떻게 이익을 얻을 수 있습니까?

문제의 분리가 우리의 목표여야 합니다.

상태는 일부 보기/컨트롤러, 해결기, 사용자 지정 데이터를 수집하는 단위입니다.

즉, 뷰, 컨트롤러 등을 재사용하는 상태가 늘어날 수 있습니다.이러한 상태는 실제로 다를 수 있습니다(같은 뷰, 다른 컨트롤러).단, 1개의 목적으로 다음과 같은 시나리오를 처리할 수 있습니다.

  • 사용자/Emplyee 레코드 관리
  • 사용자/종업원 목록 - 정보 ala PhoneList(이메일, 전화만...)
  • 보안 관리 - 사용자의 권한이란...

그리고 다시, 많은 주가 있을 수 있습니다.심지어 100개의 주(州)도 성능 문제가 되지 않을 것이다.이것은 정의일 뿐이며, 다른 부분에 대한 참조 세트입니다.이것을 사용해야 합니다.나중에...꼭 필요하다면.

상태 수준에서 사용자 사례정의한 후에는 이를 세트/히라키지로 그룹화할 수 있습니다.
이러한 그룹은 나중에 다른 형식으로 다른 사용자 역할에 표시될 수 있습니다(다른 메뉴 항목).

그러나, 최종적으로는, 많은 자유와 심플한 유지보수를 실현했습니다.

IV. 응용 프로그램 실행확장 유지

상태가 적은 경우 유지관리는 문제가 되지 않습니다.하지만 응용 프로그램이 성공할 수도 있습니다.성공과 성장...디자인 안쪽에 있습니다.

사이트 정의(작업 단위)와 그 계층(사용자 역할이 어떤 상태에 액세스할 수 있는지)을 분할하면 관리가 단순해집니다.

스테이트 이외의 시큐러티(이벤트 리스너 ala)를 적용하는 것은, 템플릿 프로바이더의 리팩터링을 종료하는 것보다 훨씬 간단합니다.또, 시큐러티의 주된 부분은, 어떠한 UI 를 사용할 수 있는가에 관계없이, 서버에 적용할 필요가 있습니다.

V. 개요:

하지만, 이 제품에는 다음과 같은 큰 특징이 있습니다.templateProvider몇 가지 흥미로운 작업을 수행할 수 있습니다(예: 여기에서 AngularJs의 UI-Router를 사용한 탐색 메뉴 변경).

보안상으로는 사용할 수 없습니다.이는 현재 역할에 따라 기존 상태에서 작성된 메뉴/계층 구조로 구현될 수 있습니다.이벤트 리스너는 사용자가 granted 상태로 이행하고 있는지 여부를 확인해야 하지만 기본 체크는 서버에 적용해야 합니다.

라우터를 사용할 필요는 없습니다.

가장 간단한 방법은 모든 역할에 대해 하나의 템플릿을 사용하고 그 안에 다이내믹ng-include를 사용하는 것입니다.$scope에 인젝터가 있다고 가정합니다.

<div ng-include="injector.get('session').role+'_dashboard.html'"></div>

그래서 당신은user_dashboard.html ★★★★★★★★★★★★★★★★★」admin_dashboard.html예를 들어, 각각의 내부에는 개별 컨트롤러를 적용할 수 있습니다.user_dashboard.html:

<div id="user_dashboard" ng-controller="UserDashboardCtrl">
    User markup
</div>

다음과 같은 솔루션을 채용하고 있습니다(이상적이지는 않지만, 그러한 시나리오에서는 효과가 있었습니다).

  1. 는 템플릿 자체에서 사용할 수 있습니다.ngController.

  2. 하여 템플릿을 " " " " ) 。views/dashboard.html를 참조해 주세요.

  3. 변경하다views/dashboard.html 사용해서 요.$templateCache.put(...)이치노


다음은 스트라이프 다운 방식의 예입니다.

app.controller('loginCtrl', function ($location, $scope, User) {
    ...
    $scope.loginAs = function (role) {
        // First set the user role
        User.setRole(role);

        // Then navigate to Dashboard
        $location.path('/dashboard');
    };
});

// A simplified `User` service that takes care of swapping templates,
// based on the role. ("User" is probably not the best name...)
app.service('User', function ($http, $templateCache) {
    var guestRole = 'guest';
    var facadeUrl = 'views/dashboard.html';
    var emptyTmpl = '';
    var errorTmpl = 'Failed to load template !';
    var tempTmpl  = 'Loading template...';

    ...

    // Upon logout, put an empty template into `$templateCache`
    this.logout = function () {
        this.role = guestRole;
        $templateCache.put(facadeUrl, emptyTmpl);
    };

    // When the role changes (e.g. upon login), set the role as well as the template
    // (remember that the template itself will specify the appropriate controller) 
    this.setRole = function (role) {
        this.role = role;

        // The actual template URL    
        var url = 'views/' + role + '/dashboard.html';

        // Put a temporary template into `$templateCache`
        $templateCache.put(facadeUrl, tempTmpl);

        // Fetch the actual template (from the `$templateCahce` if available)
        // and store it under the "generic" URL (`views/dashboard.html`)
        $http.get(url, {cache: $templateCache}).
              success(function (tmpl) {
                  $templateCache.put(facadeUrl, tmpl);
              }).
              error(function () {
                  // Handle errors...
                  $templateCache.put(facadeUrl, errorTmpl);
              });
    };

    // Initialize role and template        
    this.logout();
});

// When the user navigates to '/dashboard', load the `views/dashboard.html` template.
// In a real app, you should of course verify that the user is logged in etc...
// (Here I use `ngRoute` for simplicity, but you can use any routing module.)
app.config(function ($routeProvider) {
    $routeProvider.
        when('/dashboard', {
            templateUrl: 'views/dashboard.html'
        }).
        ...
});

짧은 데모도 보세요.
는 (을) 합니다.ngRoute심플하게 하기 위해서입니다만, 모든 작업은 델에 의해서 행해지기 때문에, 전혀 차이가 없습니다.User서비스를 제공합니다.)

여기서 긴 설명은 필요 없습니다.

resolve를 사용하여 $route를 변경합니다.$$route.templateUrl 또는 새로운 루트 또는 관련 파라미터를 약속에 전달하여 routeChangeError를 사용합니다.

var md = angular.module('mymodule', ['ngRoute']);
md.config(function($routeProvider, $locationProvider) {
    $routeProvider.when('/common_route/:someparam', {
        resolve: {
            nextRoute: function($q, $route, userService) {
                defer = $q.defer()
                userService.currentRole(function(data) { defer.reject({nextRoute: 'user_based_route/'+data) });
                return defer.promise;
            }
        }
    });
    $rootScope.$on("$routeChangeError", function(evt, current, previous, rejection) {
      if (rejection.route) {
        return $location.path(rejection.route).replace();
      }
    });
});

이 질문이 올라온지 꽤 지났다는 것을 알고 있습니다만, 제가 사용하는 방법이 다른 답변과 다르기 때문에 답변을 추가합니다.

이 방법에서는 해당 사용자의 역할에 따라 루트 URL과 템플릿 URL을 완전히 분리하여 표시할 권한이 없는 경로에 있는 경우 사용자를 인덱스 페이지로 수정합니다.

UI 라우터에서는 기본적으로 다음과 같은 데이터 속성을 상태에 추가합니다.

.state('admin', {
            url: "/admin",
            templateUrl: "views/admin.html",
            data: {  requireRole: 'admin' }
        })

를 에 합니다.localstorage ★★★★★★★★★★★★★★★★★」$rootscope다음과 같이 컨트롤러로부터 송신됩니다.

var role = JSON.stringify(response.data); // response from api with role details

// Set the stringified user data into local storage
localStorage.setItem('role', role);

// Putting the user's role on $rootScope for access by other controllers
$rootScope.role = response.data;

으로,는 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★.$stateChangeStart사용자가 페이지를 표시할 필요가 없는 경우 역할을 확인하고 사용자를 리다이렉트하려면 다음 절차를 수행합니다.

.run(['$rootScope', '$state', function($rootScope, $state) {

        // $stateChangeStart is fired whenever the state changes. We can use some parameters
        // such as toState to hook into details about the state as it is changing
        $rootScope.$on('$stateChangeStart', function(event, toState) {

                var role = JSON.parse(localStorage.getItem('role'));
                $rootScope.role = role;

                // Redirect user is NOT authenticated and accesing private pages
                var requireRole = toState.data !== undefined
                                  && toState.data.requireRole;

                 if( (requireRole == 'admin' && role != 'admin')) )
                 {
                   $state.go('index');
                   event.preventDefault();
                   return;
                 }
     }

});

또한 사용자에게 데이터를 표시하기 전에 서버 측 인증 체크를 수행해야 합니다.

https://github.com/Narzerus/angular-permission에 UI가 필요한 훌륭한 프로젝트가 있습니다.그 프로젝트는 그럼에도 불구하고 잘 되고 있다.

언급URL : https://stackoverflow.com/questions/23429055/angularjs-ui-router-load-template-and-controller-based-on-user-role