Commit 556cb5aa5df8ddd7eafe39e5a9336d63d5d88226

Authored by Vladyslav_Prykhodko
1 parent cea56664

Refactoring OAuth2

... ... @@ -22,7 +22,6 @@ export interface AuthPayload {
22 22 userTokenAccessEnabled: boolean;
23 23 allowedDashboardIds: string[];
24 24 forceFullscreen: boolean;
25   - allowOAuth2Configuration: boolean;
26 25 }
27 26
28 27 export interface AuthState {
... ... @@ -34,5 +33,4 @@ export interface AuthState {
34 33 allowedDashboardIds: string[];
35 34 forceFullscreen: boolean;
36 35 lastPublicDashboardId: string;
37   - allowOAuth2Configuration: boolean;
38 36 }
... ...
... ... @@ -22,7 +22,6 @@ const emptyUserAuthState: AuthPayload = {
22 22 userDetails: null,
23 23 userTokenAccessEnabled: false,
24 24 forceFullscreen: false,
25   - allowOAuth2Configuration: false,
26 25 allowedDashboardIds: []
27 26 };
28 27
... ...
... ... @@ -18,7 +18,7 @@ import { Injectable, NgZone } from '@angular/core';
18 18 import { JwtHelperService } from '@auth0/angular-jwt';
19 19 import { HttpClient } from '@angular/common/http';
20 20
21   -import { forkJoin, Observable, of, throwError, ReplaySubject } from 'rxjs';
  21 +import { forkJoin, Observable, of, ReplaySubject, throwError } from 'rxjs';
22 22 import { catchError, map, mergeMap, tap } from 'rxjs/operators';
23 23
24 24 import { LoginRequest, LoginResponse, OAuth2Client, PublicLoginRequest } from '@shared/models/login.models';
... ... @@ -425,25 +425,15 @@ export class AuthService {
425 425 }
426 426 }
427 427
428   - private loadIsOAuth2ConfigurationAllow(authUser: AuthUser): Observable<boolean> {
429   - if (authUser.authority === Authority.TENANT_ADMIN) {
430   - return this.http.get<boolean>('/api/oauth2/config/isAllowed', defaultHttpOptions());
431   - } else {
432   - return of(false);
433   - }
434   - }
435   -
436 428 private loadSystemParams(authPayload: AuthPayload): Observable<any> {
437 429 const sources: Array<Observable<any>> = [this.loadIsUserTokenAccessEnabled(authPayload.authUser),
438 430 this.fetchAllowedDashboardIds(authPayload),
439   - this.loadIsOAuth2ConfigurationAllow(authPayload.authUser),
440 431 this.timeService.loadMaxDatapointsLimit()];
441 432 return forkJoin(sources)
442 433 .pipe(map((data) => {
443 434 const userTokenAccessEnabled: boolean = data[0];
444 435 const allowedDashboardIds: string[] = data[1];
445   - const allowOAuth2Configuration: boolean = data[2];
446   - return {userTokenAccessEnabled, allowedDashboardIds, allowOAuth2Configuration};
  436 + return {userTokenAccessEnabled, allowedDashboardIds};
447 437 }));
448 438 }
449 439
... ...
1   -///
2   -/// Copyright © 2016-2020 The Thingsboard Authors
3   -///
4   -/// Licensed under the Apache License, Version 2.0 (the "License");
5   -/// you may not use this file except in compliance with the License.
6   -/// You may obtain a copy of the License at
7   -///
8   -/// http://www.apache.org/licenses/LICENSE-2.0
9   -///
10   -/// Unless required by applicable law or agreed to in writing, software
11   -/// distributed under the License is distributed on an "AS IS" BASIS,
12   -/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   -/// See the License for the specific language governing permissions and
14   -/// limitations under the License.
15   -///
16   -
17   -import { Injectable } from '@angular/core';
18   -import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
19   -import { AuthState } from '@core/auth/auth.models';
20   -import { select, Store } from '@ngrx/store';
21   -import { selectAuth } from '@core/auth/auth.selectors';
22   -import { take } from 'rxjs/operators';
23   -import { AppState } from '@core/core.state';
24   -import { Authority } from '@shared/models/authority.enum';
25   -
26   -@Injectable({
27   - providedIn: 'root'
28   -})
29   -export class RedirectGuardSettings implements CanActivate {
30   - constructor(private store: Store<AppState>,
31   - private router: Router) { }
32   -
33   - canActivate(
34   - next: ActivatedRouteSnapshot,
35   - state: RouterStateSnapshot) {
36   - let auth: AuthState = null;
37   - this.store.pipe(select(selectAuth), take(1)).subscribe(
38   - (authState: AuthState) => {
39   - auth = authState;
40   - }
41   - );
42   -
43   - if (auth?.userDetails?.authority === Authority.TENANT_ADMIN) {
44   - this.router.navigateByUrl('/settings/oauth2');
45   - return false;
46   - }
47   - this.router.navigateByUrl('/settings/general');
48   - return false;
49   - }
50   -
51   -}
... ... @@ -18,13 +18,12 @@ import { Injectable } from '@angular/core';
18 18 import { AuthService } from '../auth/auth.service';
19 19 import { select, Store } from '@ngrx/store';
20 20 import { AppState } from '../core.state';
21   -import { getCurrentAuthState, selectAuthUser, selectIsAuthenticated } from '../auth/auth.selectors';
  21 +import { selectAuthUser, selectIsAuthenticated } from '../auth/auth.selectors';
22 22 import { take } from 'rxjs/operators';
23 23 import { HomeSection, MenuSection } from '@core/services/menu.models';
24 24 import { BehaviorSubject, Observable, Subject } from 'rxjs';
25 25 import { Authority } from '@shared/models/authority.enum';
26 26 import { AuthUser } from '@shared/models/user.model';
27   -import { AuthState } from '@core/auth/auth.models';
28 27
29 28 @Injectable({
30 29 providedIn: 'root'
... ... @@ -44,8 +43,6 @@ export class MenuService {
44 43 );
45 44 }
46 45
47   - authState: AuthState = getCurrentAuthState(this.store);
48   -
49 46 private buildMenu() {
50 47 this.store.pipe(select(selectAuthUser), take(1)).subscribe(
51 48 (authUser: AuthUser) => {
... ... @@ -236,25 +233,6 @@ export class MenuService {
236 233 icon: 'track_changes'
237 234 }
238 235 );
239   -
240   - if (this.authState.allowOAuth2Configuration) {
241   - sections.push({
242   - name: 'admin.settings',
243   - type: 'toggle',
244   - path: '/settings',
245   - height: '40px',
246   - icon: 'settings',
247   - pages: [
248   - {
249   - name: 'admin.oauth2.oauth2',
250   - type: 'link',
251   - path: '/settings/oauth2',
252   - icon: 'security'
253   - }
254   - ]
255   - });
256   - }
257   -
258 236 return sections;
259 237 }
260 238
... ...
... ... @@ -23,7 +23,6 @@ import { Authority } from '@shared/models/authority.enum';
23 23 import { GeneralSettingsComponent } from '@modules/home/pages/admin/general-settings.component';
24 24 import { SecuritySettingsComponent } from '@modules/home/pages/admin/security-settings.component';
25 25 import { OAuth2SettingsComponent } from '@home/pages/admin/oauth2-settings.component';
26   -import { RedirectGuardSettings } from '../../../../core/guards/redirect-guard-settings.service';
27 26
28 27 const routes: Routes = [
29 28 {
... ... @@ -38,7 +37,7 @@ const routes: Routes = [
38 37 children: [
39 38 {
40 39 path: '',
41   - canActivate: [RedirectGuardSettings],
  40 + redirectTo: 'general',
42 41 pathMatch: 'full'
43 42 },
44 43 {
... ... @@ -85,7 +84,7 @@ const routes: Routes = [
85 84 component: OAuth2SettingsComponent,
86 85 canDeactivate: [ConfirmOnExitGuard],
87 86 data: {
88   - auth: [Authority.SYS_ADMIN, Authority.TENANT_ADMIN],
  87 + auth: [Authority.SYS_ADMIN],
89 88 title: 'admin.oauth2.oauth2',
90 89 breadcrumb: {
91 90 label: 'admin.oauth2.oauth2',
... ...
... ... @@ -60,7 +60,7 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
60 60 additionalInfo: {
61 61 providerName: 'Custom'
62 62 },
63   - clientAuthenticationMethod: 'Post',
  63 + clientAuthenticationMethod: 'POST',
64 64 userNameAttributeName: 'email',
65 65 mapperConfig: {
66 66 allowUserCreation: true,
... ... @@ -249,17 +249,17 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
249 249 loginButtonIcon: [registrationData?.loginButtonIcon ? registrationData.loginButtonIcon : null],
250 250 clientId: [registrationData?.clientId ? registrationData.clientId : '', Validators.required],
251 251 clientSecret: [registrationData?.clientSecret ? registrationData.clientSecret : '', Validators.required],
252   - accessTokenUri: [registrationData?.accessTokenUri ? registrationData.accessTokenUri : '', [
253   - Validators.required,
254   - Validators.pattern(this.URL_REGEXP)]],
255   - authorizationUri: [registrationData?.authorizationUri ? registrationData.authorizationUri : '', [
256   - Validators.required,
257   - Validators.pattern(this.URL_REGEXP)]],
  252 + accessTokenUri: [registrationData?.accessTokenUri ? registrationData.accessTokenUri : '',
  253 + [Validators.required,
  254 + Validators.pattern(this.URL_REGEXP)]],
  255 + authorizationUri: [registrationData?.authorizationUri ? registrationData.authorizationUri : '',
  256 + [Validators.required,
  257 + Validators.pattern(this.URL_REGEXP)]],
258 258 scope: this.fb.array(registrationData?.scope ? registrationData.scope : []),
259 259 jwkSetUri: [registrationData?.jwkSetUri ? registrationData.jwkSetUri : '', Validators.pattern(this.URL_REGEXP)],
260   - userInfoUri: [registrationData?.userInfoUri ? registrationData.userInfoUri : '', [
261   - Validators.required,
262   - Validators.pattern(this.URL_REGEXP)]],
  260 + userInfoUri: [registrationData?.userInfoUri ? registrationData.userInfoUri : '',
  261 + [Validators.required,
  262 + Validators.pattern(this.URL_REGEXP)]],
263 263 clientAuthenticationMethod: [
264 264 registrationData?.clientAuthenticationMethod ? registrationData.clientAuthenticationMethod : 'POST', Validators.required],
265 265 userNameAttributeName: [
... ... @@ -285,7 +285,8 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
285 285 this.subscriptions.push(clientRegistration.get('additionalInfo.providerName').valueChanges.subscribe((provider) => {
286 286 (clientRegistration.get('scope') as FormArray).clear();
287 287 if (provider === 'Custom') {
288   - clientRegistration.reset(this.defaultProvider, {emitEvent: false});
  288 + const defaultSettings = {...this.defaultProvider, ...{id: clientRegistration.get('id').value}};
  289 + clientRegistration.reset(defaultSettings, {emitEvent: false});
289 290 clientRegistration.get('accessTokenUri').enable();
290 291 clientRegistration.get('authorizationUri').enable();
291 292 clientRegistration.get('jwkSetUri').enable();
... ... @@ -294,6 +295,8 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
294 295 const template = this.templates.get(provider);
295 296 delete template.id;
296 297 delete template.additionalInfo;
  298 + template.clientId = '';
  299 + template.clientSecret = '';
297 300 template.scope.forEach(() => {
298 301 (clientRegistration.get('scope') as FormArray).push(this.fb.control(''));
299 302 });
... ... @@ -301,13 +304,7 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
301 304 clientRegistration.get('authorizationUri').disable();
302 305 clientRegistration.get('jwkSetUri').disable();
303 306 clientRegistration.get('userInfoUri').disable();
304   - clientRegistration.patchValue({
305   - ...template, ...{
306   - clientId: '',
307   - clientSecret: '',
308   - id: {id: null, entityType: null}
309   - }
310   - }, {emitEvent: false});
  307 + clientRegistration.patchValue(template, {emitEvent: false});
311 308 }
312 309 }));
313 310
... ... @@ -469,7 +466,8 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
469 466 componentRef.onDestroy(() => {
470 467 if (componentRef.instance.result !== null) {
471 468 const attributeValue = componentRef.instance.result;
472   - this.clientDomains.at(index).get('redirectUriTemplate').patchValue(attributeValue, {emitEvent: true});
  469 + this.clientDomains.at(index).get('redirectUriTemplate').patchValue(attributeValue);
  470 + this.clientDomains.at(index).get('redirectUriTemplate').markAsDirty();
473 471 }
474 472 });
475 473 }
... ...
... ... @@ -54,9 +54,6 @@
54 54 <mat-label translate>tenant.description</mat-label>
55 55 <textarea matInput formControlName="description" rows="2"></textarea>
56 56 </mat-form-field>
57   - <mat-checkbox fxFlex formControlName="allowOAuth2Configuration" style="padding-bottom: 16px;">
58   - {{ 'tenant.allow-oauth2-configuration' | translate }}
59   - </mat-checkbox>
60 57 </div>
61 58 <tb-contact [parentForm]="entityForm" [isEdit]="isEdit"></tb-contact>
62 59 <div fxLayout="column">
... ...
... ... @@ -23,7 +23,6 @@ import { ActionNotificationShow } from '@app/core/notification/notification.acti
23 23 import { TranslateService } from '@ngx-translate/core';
24 24 import { ContactBasedComponent } from '../../components/entity/contact-based.component';
25 25 import { EntityTableConfig } from '@home/models/entity/entities-table-config.models';
26   -import { isDefined } from '@core/utils';
27 26
28 27 @Component({
29 28 selector: 'tb-tenant',
... ... @@ -54,11 +53,8 @@ export class TenantComponent extends ContactBasedComponent<Tenant> {
54 53 title: [entity ? entity.title : '', [Validators.required]],
55 54 isolatedTbCore: [entity ? entity.isolatedTbCore : false, []],
56 55 isolatedTbRuleEngine: [entity ? entity.isolatedTbRuleEngine : false, []],
57   - additionalInfo: this.fb.group(
58   - {
59   - description: [entity && entity.additionalInfo ? entity.additionalInfo.description : ''],
60   - allowOAuth2Configuration: [isDefined(entity?.additionalInfo?.allowOAuth2Configuration) ?
61   - entity.additionalInfo.allowOAuth2Configuration : false]
  56 + additionalInfo: this.fb.group({
  57 + description: [entity && entity.additionalInfo ? entity.additionalInfo.description : '']
62 58 }
63 59 )
64 60 }
... ... @@ -69,11 +65,7 @@ export class TenantComponent extends ContactBasedComponent<Tenant> {
69 65 this.entityForm.patchValue({title: entity.title});
70 66 this.entityForm.patchValue({isolatedTbCore: entity.isolatedTbCore});
71 67 this.entityForm.patchValue({isolatedTbRuleEngine: entity.isolatedTbRuleEngine});
72   - this.entityForm.patchValue({additionalInfo: {
73   - description: entity.additionalInfo ? entity.additionalInfo.description : '',
74   - allowOAuth2Configuration: isDefined(entity?.additionalInfo?.allowOAuth2Configuration) ?
75   - entity.additionalInfo.allowOAuth2Configuration : false
76   - }});
  68 + this.entityForm.patchValue({additionalInfo: {description: entity.additionalInfo ? entity.additionalInfo.description : ''}});
77 69 }
78 70
79 71 updateFormState() {
... ...
... ... @@ -126,7 +126,6 @@
126 126 "add-domain": "Add domain",
127 127 "new-domain": "New domain",
128 128 "add-provider": "Add provider",
129   - "settings": "Settings",
130 129 "oauth2": {
131 130 "oauth2": "OAuth2",
132 131 "registration-id": "Registration ID",
... ... @@ -1715,8 +1714,7 @@
1715 1714 "isolated-tb-core": "Processing in isolated ThingsBoard Core container",
1716 1715 "isolated-tb-rule-engine": "Processing in isolated ThingsBoard Rule Engine container",
1717 1716 "isolated-tb-core-details": "Requires separate microservice(s) per isolated Tenant",
1718   - "isolated-tb-rule-engine-details": "Requires separate microservice(s) per isolated Tenant",
1719   - "allow-oauth2-configuration": "Allow OAuth2 configuration"
  1717 + "isolated-tb-rule-engine-details": "Requires separate microservice(s) per isolated Tenant"
1720 1718 },
1721 1719 "timeinterval": {
1722 1720 "seconds-interval": "{ seconds, plural, 1 {1 second} other {# seconds} }",
... ...