Angular - Як праверыць дазвол на аснове ролі і стану юрыдычнай асобы

У наш час ваша заяўка распаўсюджваецца на аўтэнтыфікацыю і аўтарызацыю. Калі вы шукаеце бібліятэкі і метады аўтарызацыі ў Інтэрнэце, вы можаце лёгка знайсці рашэнні, якія прапануюць толькі аўтарызацыю, заснаваную на ролях, але перашкаджаюць доступу да старонкі, і амаль заўсёды бывае, што вам патрэбны іншы дазвол на статус юрыдычнай асобы.

Для TL; DR тут дэма і код, які выкарыстоўваецца ў дэманстрацыі.

Іміджавыя крэдыты

Што, чорт вазьмі, дазвол юрыдычнай дзяржавы?

Ну, я думаю, нічога лепшага ў маёй галаве было назваць, калі я пісаў гэты пост. Аднак больш-менш тое, што я спрабую сказаць, звязана з сітуацыяй, калі вы павінны даць або пазбавіць бягучага карыстальніка магчымасці прыняць пэўныя дзеянні, калі бягучы статус сутнасці залежыць ад статусу X і іншага. Магчымасць пры ўключэнні сутнасці ўсталёўвае стан Y, а горшы выпадак прыйшоў, калі ўсё гэта было на адным экране ці нават у тым жа кампаненце. Усе бібліятэкі з аўтарызацыяй ролевай базы ратуюць вас ад гэтай праблемы. Мне надакучыла чытаць розныя артыкулы, у якіх старонкі, заснаваныя на ролі, перашкаджаюць рашэнню, і пачаў думаць і праграмаваць, не маючы нічога на ўвазе. Раптам я знайшоў простае, немудрагелістае і вельмі гнуткае рашэнне гэтага тыпу праблемы, якое складалася з чатырох частак.

  • Паслуга прадастаўлення інфармацыі пра бягучага карыстальніка (што сапраўды важна, гэта спосаб вызначэння роляў карыстальнікаў, якім належыць бягучы карыстальнік альбо якія былі прызначаны ім у дадатку).
  • Карта дазволу на працоўны працэс (файл JSON)
  • Аўтарызацыйная служба, якая ажыццяўляе праверку аўтарызацыі
  • Інструкцыя па праверцы службы аўтарызацыі

Крок 1. Атрымайце бягучыя ролі карыстальніка

Выканайце паслугу па загрузцы з сервера (упершыню) альбо з сеансу ці кукі, як вам зручней для наступнага выкарыстання. Важна прадаставіць карыстачу спіс навыкаў (роляў).

// Прыклад {Імя: "John Doe", email: '[email protected]', role: ['prodavač', 'sell_manager'], <- залежыць ад accessToken: 'Alotofleters, dieanaccesstokenhahahaaa!' ... яшчэ шмат
}

У маім выпадку гэта выглядае больш-менш так:

// Імпартаваць сюды ...
Экспартны клас @Injectable () CurrentUserService {private userSubject = Новы ReplaySubject (1); прыватны hasUser = false; Канструктар (прыватныя карыстальнікіApi: UserApi) {} public getUser (): назіраецца {калі (this.hasUser) {this.fetchUser (); } вярнуцца this.userSubject.asObservable (); } public fetchUser (): void {this.usersApi.getCurrent () // <== http-выклік, каб атрымаць userInfo. userSubject.next (user); this.userSubject.complete ();}, (памылка) => {this.hasUser = false; this.userSubject.error (памылка);}); }}

Другі крок: стварыце працоўны працэс і агляд аўтарызацыі

Гэта не што іншае, як ілюстрацыя таго, што мы можам зрабіць і хто мы можам зрабіць, стварыўшы дрэва з рознымі сутнасцямі і сваімі дзяржавамі. Напрыклад, разгледзім наступны працэс продажу: Наша дадатак можа мець некалькі тыпаў роляў. У нашым прыкладзе мы прысвойваем ролі Прадаўцу, рашэнням ARCHITECT і КЛІЕНТУ.

Каб мы не казалі пра працэс:

  • Па-першае, ПРОДАВАЦЬ размяшчае магчымасць, выканаўшы дзеянне "Дадаць новую магчымасць", якое, хутчэй за ўсё, створыць статус магчымасці
  • У гэты момант КЛІЕНТАР І ПРОДАВЕЦ можа дадаць патрабаванні да магчымасці, каб абодва маглі выкарыстаць дзеянне "Дадаць патрабаванні" пры выкананні патрабаванняў. Статус магчымасці можа змяніцца на Размешчаны
  • Пасля таго, як патрабаванні будуць выкананы, ARCHITECT можа захацець дадаць рашэнне, таму неабходна дзеянне: загрузіце рашэнне, і стан можа змяніцца, каб вырашыць.
  • Пасля таго, як рашэнне будзе разгорнута, КЛІЕНТАР можа захацець прыняць яго, каб яму было неабходна дзеянне па ўхваленні рашэння, а статус зменены на

Мы скароцім працэс тут, інакш гэта занадта моцна павялічыцца, і гэта не ў выпадку з гэтым чытаннем. Зыходзячы з гэтага працэсу, адлюстравання і мяркуючы, што суб'ект магчымасці мае поле адсочвання стану, наш працоўны працэс будзе выглядаць так:

{"Opportunity": {"addOpportunity": {"allowedRoles": ["SELLER"]}}, "created": {"addRequirement": {"дазволенаRoles": ["SELLER", "CLIENT"]}}}, " прадстаўлена ": {" addSolution ": {" дазволенаRoles ": [" ARCHITECT "]}}," вырашана ": {" approveSolution ": {" дазволенаRoles ": [" CLIENT "]}}}}

Крок 3. Служба аўтарызацыі праверкі на выкарыстанне працоўнага працэсу і агляду аўтарызацыі

Пасля супастаўлення працэсу ў працоўны працэс і адлюстраванне дазволу, нам трэба стварыць службу, каб выкарыстоўваць яго і праверыць, ці права карыстача аўтарызаваны. Гэта можа выглядаць так:

// Інструкцыі па імпарце сюды // Дарэчы, у Angular-Cli мы можам змясціць файл JSON у // Environment.ts
@Injectable () клас экспарту WorkflowEvents {толькі для чытання WORKFLOW_EVENTS = Навакольнае асяроддзе ['Працоўны працэс']; прыватныя правы карыстальніка: усталяваны ;
// Вы памятаеце крок 1? ён выкарыстоўваецца тут канструктарам (прыватны currentUserService: CurrentUserService) {} // вяртае булевую публічную праверку аўтарызацыі (шлях: любы): назіраецца {// Мы загружаем ролі толькі адзін раз, калі (this.userRoles) {return this.currentUserService.getUser () .map (currentUser => currentUser.roles) .do (role => {const role = role.map ( role => role.name); this.userRoles = новы набор (ролі);}) .map (роля => this.doCheckAuthorization (шлях)); } вярнуцца Observable.of (this.doCheckAuthorization (шлях)); } прыватнае doCheckAuthorization (шлях: string []): булевы {калі (path.length) {const entry = this.findEntry (this.WORKFLOW_EVENTS, шлях); if (entry && entry ['allowedRoles'] && this.userRoles.size) {return entry.permittedRoles .some (allowedRole => this.userRoles.has (дазволенаRole)); } вярнуць ілжывае; } вярнуць ілжывае; }
/ ** * Рэкурсіўна шукаць запісы на карце працоўнага працэсу на аснове радкоў шляху * / private findEntry (currentObject: любы, ключ: string [], індэкс = 0) {const key = keys [індэкс]; калі (currentObject [ключ] & & індэкс

У прынцыпе, вам трэба шукаць сапраўдны запіс і правяраць, ці ўваходзяць у склад дазволеных роляў бягучыя ролі карыстальніка.

Файл 4: Палітыка

Пасля таго, як у нас з'явяцца бягучыя ролі карыстальніка, дрэва аўтарызацыі працоўнага працэсу і служба па праверцы аўтарызацыі на бягучыя ролі карыстальніка, нам трэба рэалізаваць гэта ў куце 2/4 з дапамогай дырэктывы. Першапачаткова дырэктыва, якую я напісаў, была дырэктывай атрыбутаў, якая пераключала атрыбут адлюстравання CSS. Аднак гэта можа прывесці да праблем з прадукцыйнасцю, таму што кампаненты, якія захоўваюцца ў DOM, усё яшчэ загружаныя. Таму лепш выкарыстоўваць структурныя дырэктывы (дзякуй майму калегу Пецью Чолакову за гэты добры ўлоў (гл. Розніцу тут), бо мы можам змяніць DOM мэтавага элемента і яго нашчадкаў, каб пазбегнуць загрузкі нявыкарыстаных элементаў.

@Directive ({Selector: '[appCanAccess]'}) клас экспарту CanAccessDirective рэалізуе OnInit, OnDestroy {@Input ('appCanAccess') appCanAccess: string | радок []; прыватны дазвол $: падпіска; Канструктар (прыватны templateRef: TemplateRef) , private viewContainer: ViewContainerRef, private workflowEvents: WorkflowEvents) {} ngOnInit (): void {this.applyPermission (); } private applyPermission (): void {this.permission $ = this.workflowEvents .checkAuthorization (this.appCanAccess). .viewContainer.clear ();}}); } ngOnDestroy (): void {this.permission $ .unsubscribe (); }}

Нарэшце атрыманая праца

Цяпер усё, што нам трэба, гэта час, каб рэалізаваць гэта. Адзінае, што мы павінны зрабіць у нашым шаблоне HTML, гэта наступны код

Скажам, у нас ёсць узор кампанента, які змяшчае аб'ект магчымасці:

@Component ({selector: 'sp-price-panel', template: ` 
 
 
 
 `}) Экспарт класа SampleComponent рэалізуе OnInit {@Input () OpportunityObject: любы;
Канструктар () {} ngOnInit () {}}

І гэта ўсё, мы можам мець просты кампанент, які прадстаўляе паводзіны на аснове роляў карыстальніка і стану юрыдычнай асобы.

Дзякуючы маім калегам Пецье і Говінда за ўлоў і крытыку майго дрэннага кадавання, мы змаглі знайсці гэтае рашэнне, якое цалкам адпавядае нашым патрэбам. Я спадзяюся, што і вам гэта дапаможа.

Чэрвень 2018 г., невялікі ўзор працы => https://emsedano.github.io/ng-entity-state/