Commit ae92f065e68d996432823928f2b2a64e532c5f81

Authored by Vladyslav_Prykhodko
1 parent c3407bfd

Add select login provider templated

... ... @@ -20,6 +20,7 @@ import { Observable } from 'rxjs';
20 20 import { HttpClient } from '@angular/common/http';
21 21 import {
22 22 AdminSettings,
  23 + ClientProviderTemplated,
23 24 MailServerSettings,
24 25 OAuth2Settings,
25 26 SecuritySettings,
... ... @@ -63,8 +64,8 @@ export class AdminService {
63 64 return this.http.get<OAuth2Settings>(`/api/oauth2/config`, defaultHttpOptionsFromConfig(config));
64 65 }
65 66
66   - public getOAuth2Template(config?: RequestConfig): Observable<any> {
67   - return this.http.get<any>(`/api/oauth2/config/template`, defaultHttpOptionsFromConfig(config));
  67 + public getOAuth2Template(config?: RequestConfig): Observable<Array<ClientProviderTemplated>> {
  68 + return this.http.get<Array<ClientProviderTemplated>>(`/api/oauth2/config/template`, defaultHttpOptionsFromConfig(config));
68 69 }
69 70
70 71 public saveOAuth2Settings(OAuth2Setting: OAuth2Settings,
... ...
... ... @@ -120,9 +120,9 @@ export class MenuService {
120 120 icon: 'security'
121 121 },
122 122 {
123   - name: 'admin.oauth2.settings',
  123 + name: 'admin.oauth2.oauth2',
124 124 type: 'link',
125   - path: '/settings/oauth2-settings',
  125 + path: '/settings/oauth2',
126 126 icon: 'security'
127 127 }
128 128 ]
... ... @@ -246,13 +246,13 @@ export class MenuService {
246 246 icon: 'settings',
247 247 pages: [
248 248 {
249   - name: 'admin.oauth2.settings',
  249 + name: 'admin.oauth2.oauth2',
250 250 type: 'link',
251   - path: '/settings/oauth2-settings',
  251 + path: '/settings/oauth2',
252 252 icon: 'security'
253 253 }
254 254 ]
255   - })
  255 + });
256 256 }
257 257
258 258 return sections;
... ...
... ... @@ -81,14 +81,14 @@ const routes: Routes = [
81 81 }
82 82 },
83 83 {
84   - path: 'oauth2-settings',
  84 + path: 'oauth2',
85 85 component: OAuth2SettingsComponent,
86 86 canDeactivate: [ConfirmOnExitGuard],
87 87 data: {
88 88 auth: [Authority.SYS_ADMIN, Authority.TENANT_ADMIN],
89   - title: 'admin.oauth2.settings',
  89 + title: 'admin.oauth2.oauth2',
90 90 breadcrumb: {
91   - label: 'admin.oauth2.settings',
  91 + label: 'admin.oauth2.oauth2',
92 92 icon: 'security'
93 93 }
94 94 }
... ...
... ... @@ -19,7 +19,7 @@
19 19 <mat-card class="settings-card">
20 20 <mat-card-title>
21 21 <div fxLayout="row">
22   - <span class="mat-headline" translate>admin.oauth2.settings</span>
  22 + <span class="mat-headline" translate>admin.oauth2.oauth2</span>
23 23 <span fxFlex></span>
24 24 <div tb-help="oauth2Settings"></div>
25 25 </div>
... ... @@ -91,7 +91,7 @@
91 91 <ng-template matExpansionPanelContent>
92 92 <section [formGroupName]="j">
93 93 <mat-form-field fxFlex class="mat-block">
94   - <mat-label translate>Login Provider</mat-label>
  94 + <mat-label translate>admin.oauth2.login-provider</mat-label>
95 95 <mat-select formControlName="providerName">
96 96 <mat-option *ngFor="let provider of templateProvider" [value]="provider">
97 97 {{ provider | uppercase }}
... ... @@ -117,223 +117,254 @@
117 117 </mat-form-field>
118 118 </div>
119 119
120   - <mat-tab-group dynamicHeight>
121   - <mat-tab label="General">
122   - <div fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="8px" style="margin-top: 16px;">
123   - <mat-form-field fxFlex class="mat-block">
124   - <mat-label translate>admin.oauth2.access-token-uri</mat-label>
125   - <input matInput formControlName="accessTokenUri" required>
126   - <mat-error *ngIf="registration.get('accessTokenUri').hasError('required')">
127   - {{ 'admin.oauth2.access-token-uri-required' | translate }}
128   - </mat-error>
129   - <mat-error *ngIf="registration.get('accessTokenUri').hasError('pattern')">
130   - {{ 'admin.oauth2.uri-pattern-error' | translate }}
131   - </mat-error>
132   - </mat-form-field>
133   -
134   - <mat-form-field fxFlex class="mat-block">
135   - <mat-label translate>admin.oauth2.authorization-uri</mat-label>
136   - <input matInput formControlName="authorizationUri" required>
137   - <mat-error *ngIf="registration.get('authorizationUri').hasError('required')">
138   - {{ 'admin.oauth2.authorization-uri-required' | translate }}
139   - </mat-error>
140   - <mat-error *ngIf="registration.get('authorizationUri').hasError('pattern')">
141   - {{ 'admin.oauth2.uri-pattern-error' | translate }}
142   - </mat-error>
143   - </mat-form-field>
144   - </div>
145   -
146   - <div fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="8px">
147   - <mat-form-field fxFlex class="mat-block">
148   - <mat-label translate>admin.oauth2.jwk-set-uri</mat-label>
149   - <input matInput formControlName="jwkSetUri" required>
150   - <mat-error *ngIf="registration.get('jwkSetUri').hasError('required')">
151   - {{ 'admin.oauth2.jwk-set-uri-required' | translate }}
152   - </mat-error>
153   - <mat-error *ngIf="registration.get('jwkSetUri').hasError('pattern')">
154   - {{ 'admin.oauth2.uri-pattern-error' | translate }}
155   - </mat-error>
156   - </mat-form-field>
157   -
158   - <mat-form-field fxFlex class="mat-block">
159   - <mat-label translate>admin.oauth2.user-info-uri</mat-label>
160   - <input matInput formControlName="userInfoUri" required>
161   - <mat-error *ngIf="registration.get('userInfoUri').hasError('required')">
162   - {{ 'admin.oauth2.user-info-uri-required' | translate }}
163   - </mat-error>
164   - <mat-error *ngIf="registration.get('userInfoUri').hasError('pattern')">
165   - {{ 'admin.oauth2.uri-pattern-error' | translate }}
166   - </mat-error>
167   - </mat-form-field>
168   - </div>
169   -
170   - <mat-form-field fxFlex class="mat-block">
171   - <mat-label translate>admin.oauth2.client-authentication-method</mat-label>
172   - <mat-select formControlName="clientAuthenticationMethod">
173   - <mat-option *ngFor="let clientAuthenticationMethod of clientAuthenticationMethods"
174   - [value]="clientAuthenticationMethod">
175   - {{ clientAuthenticationMethod | uppercase }}
176   - </mat-option>
177   - </mat-select>
178   - </mat-form-field>
179   -
180   - <div fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="8px" *ngIf="registration.get('providerName').value === 'Custom'">
181   - <mat-form-field fxFlex class="mat-block">
182   - <mat-label translate>admin.oauth2.login-button-label</mat-label>
183   - <input matInput formControlName="loginButtonLabel" required>
184   - <mat-error
185   - *ngIf="registration.get('loginButtonLabel').hasError('required')">
186   - {{ 'admin.oauth2.login-button-label-required' | translate }}
187   - </mat-error>
188   - </mat-form-field>
189   -
190   - <mat-form-field fxFlex class="mat-block">
191   - <mat-label translate>admin.oauth2.login-button-icon</mat-label>
192   - <input matInput formControlName="loginButtonIcon">
193   - </mat-form-field>
194   - </div>
195   -
196   - <mat-form-field fxFlex class="mat-block">
197   - <mat-label translate>admin.oauth2.scope</mat-label>
198   - <mat-chip-list #scopeList>
199   - <mat-chip *ngFor="let scope of registration.get('scope').value; let k = index;"
200   - removable (removed)="removeScope(k, registration)">
201   - {{scope}}
202   - <mat-icon matChipRemove>cancel</mat-icon>
203   - </mat-chip>
204   - <input [matChipInputFor]="scopeList"
205   - [matChipInputSeparatorKeyCodes]="separatorKeysCodes"
206   - matChipInputAddOnBlur
207   - (matChipInputTokenEnd)="addScope($event, registration)">
208   - </mat-chip-list>
209   - <mat-error *ngIf="registration.get('scope').hasError('required')">
210   - {{ 'admin.oauth2.jwk-set-uri-required' | translate }}
211   - </mat-error>
212   - </mat-form-field>
213   -
214   - </mat-tab>
215   - <mat-tab label="Mapper">
216   - <mat-form-field class="mat-block" style="margin-top: 16px;">
217   - <mat-label translate>admin.oauth2.user-name-attribute-name</mat-label>
218   - <input matInput formControlName="userNameAttributeName" required>
219   - <mat-error *ngIf="registration.get('userNameAttributeName').hasError('required')">
220   - {{ 'admin.oauth2.user-name-attribute-name-required' | translate }}
221   - </mat-error>
222   - </mat-form-field>
223   -
224   - <section formGroupName="mapperConfig">
225   - <div fxLayout="column" fxLayoutGap="8px">
226   - <mat-checkbox formControlName="allowUserCreation">
227   - {{ 'admin.oauth2.allow-user-creation' | translate }}
228   - </mat-checkbox>
229   - <mat-checkbox formControlName="activateUser">
230   - {{ 'admin.oauth2.activate-user' | translate }}
231   - </mat-checkbox>
232   - </div>
233   -
234   - <mat-form-field fxFlex class="mat-block">
235   - <mat-label translate>admin.oauth2.type</mat-label>
236   - <mat-select formControlName="type">
237   - <mat-option *ngFor="let converterTypeExternalUser of converterTypesExternalUser"
238   - [value]="converterTypeExternalUser">
239   - {{ converterTypeExternalUser }}
240   - </mat-option>
241   - </mat-select>
242   - </mat-form-field>
243   -
244   - <section formGroupName="basic"
245   - *ngIf="registration.get('mapperConfig.type').value === 'BASIC'">
246   - <mat-form-field class="mat-block">
247   - <mat-label translate>admin.oauth2.email-attribute-key</mat-label>
248   - <input matInput formControlName="emailAttributeKey" required>
249   - <mat-error
250   - *ngIf="registration.get('mapperConfig.basic.emailAttributeKey').hasError('required')">
251   - {{ 'admin.oauth2.email-attribute-key-required' | translate }}
252   - </mat-error>
253   - </mat-form-field>
254   -
255   - <div fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="8px">
  120 + <mat-expansion-panel class="mat-elevation-z0 custom-settings"
  121 + [disabled]="registration.get('providerName').value === 'Custom'"
  122 + [expanded]="registration.get('providerName').value === 'Custom'">
  123 + <mat-expansion-panel-header [fxHide]="registration.get('providerName').value === 'Custom'">
  124 + <mat-panel-description fxLayoutAlign="end center">
  125 + {{ 'admin.oauth2.custom-setting' | translate }}
  126 + </mat-panel-description>
  127 + </mat-expansion-panel-header>
  128 + <ng-template matExpansionPanelContent>
  129 + <mat-tab-group dynamicHeight>
  130 + <mat-tab label="{{ 'admin.oauth2.general' | translate }}">
  131 + <div fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="8px" style="margin-top: 16px;">
256 132 <mat-form-field fxFlex class="mat-block">
257   - <mat-label translate>admin.oauth2.first-name-attribute-key</mat-label>
258   - <input matInput formControlName="firstNameAttributeKey">
  133 + <mat-label translate>admin.oauth2.access-token-uri</mat-label>
  134 + <input matInput formControlName="accessTokenUri" required>
  135 + <button mat-icon-button matSuffix
  136 + type="button"
  137 + (click)="toggleEditMode(registration, 'accessTokenUri')"
  138 + *ngIf="registration.get('providerName').value !== 'Custom'">
  139 + <mat-icon class="material-icons">create</mat-icon>
  140 + </button>
  141 + <mat-error *ngIf="registration.get('accessTokenUri').hasError('required')">
  142 + {{ 'admin.oauth2.access-token-uri-required' | translate }}
  143 + </mat-error>
  144 + <mat-error *ngIf="registration.get('accessTokenUri').hasError('pattern')">
  145 + {{ 'admin.oauth2.uri-pattern-error' | translate }}
  146 + </mat-error>
259 147 </mat-form-field>
260 148
261 149 <mat-form-field fxFlex class="mat-block">
262   - <mat-label translate>admin.oauth2.last-name-attribute-key</mat-label>
263   - <input matInput formControlName="lastNameAttributeKey">
  150 + <mat-label translate>admin.oauth2.authorization-uri</mat-label>
  151 + <input matInput formControlName="authorizationUri" required>
  152 + <button mat-icon-button matSuffix
  153 + type="button"
  154 + (click)="toggleEditMode(registration, 'authorizationUri')"
  155 + *ngIf="registration.get('providerName').value !== 'Custom'">
  156 + <mat-icon class="material-icons">create</mat-icon>
  157 + </button>
  158 + <mat-error *ngIf="registration.get('authorizationUri').hasError('required')">
  159 + {{ 'admin.oauth2.authorization-uri-required' | translate }}
  160 + </mat-error>
  161 + <mat-error *ngIf="registration.get('authorizationUri').hasError('pattern')">
  162 + {{ 'admin.oauth2.uri-pattern-error' | translate }}
  163 + </mat-error>
264 164 </mat-form-field>
265 165 </div>
266 166
267 167 <div fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="8px">
268   - <mat-form-field fxFlex class="mat-block">
269   - <mat-label translate>admin.oauth2.tenant-name-strategy</mat-label>
270   - <mat-select formControlName="tenantNameStrategy">
271   - <mat-option *ngFor="let tenantNameStrategy of tenantNameStrategies"
272   - [value]="tenantNameStrategy">
273   - {{ tenantNameStrategy }}
274   - </mat-option>
275   - </mat-select>
  168 + <mat-form-field fxFlex class="mat-block" appearance="legacy">
  169 + <mat-label translate>admin.oauth2.jwk-set-uri</mat-label>
  170 + <input matInput formControlName="jwkSetUri">
  171 + <button mat-icon-button matSuffix
  172 + type="button" aria-label="Clear"
  173 + (click)="toggleEditMode(registration, 'jwkSetUri')"
  174 + *ngIf="registration.get('providerName').value !== 'Custom'">
  175 + <mat-icon class="material-icons">create</mat-icon>
  176 + </button>
  177 + <mat-error *ngIf="registration.get('jwkSetUri').hasError('pattern')">
  178 + {{ 'admin.oauth2.uri-pattern-error' | translate }}
  179 + </mat-error>
276 180 </mat-form-field>
277 181
278   - <mat-form-field fxFlex class="mat-block" *ngIf="registration.get('mapperConfig.basic.tenantNameStrategy').value === 'CUSTOM'">
279   - <mat-label translate>admin.oauth2.tenant-name-pattern</mat-label>
280   - <input matInput
281   - formControlName="tenantNamePattern"
282   - [required]="registration.get('mapperConfig.basic.tenantNameStrategy').value === 'CUSTOM'">
283   - <mat-error
284   - *ngIf="registration.get('mapperConfig.basic.tenantNamePattern').hasError('required')">
285   - {{ 'admin.oauth2.tenant-name-pattern-required' | translate }}
  182 + <mat-form-field fxFlex class="mat-block">
  183 + <mat-label translate>admin.oauth2.user-info-uri</mat-label>
  184 + <input matInput formControlName="userInfoUri" required>
  185 + <button mat-icon-button matSuffix
  186 + type="button"
  187 + (click)="toggleEditMode(registration, 'userInfoUri')"
  188 + *ngIf="registration.get('providerName').value !== 'Custom'">
  189 + <mat-icon class="material-icons">create</mat-icon>
  190 + </button>
  191 + <mat-error *ngIf="registration.get('userInfoUri').hasError('required')">
  192 + {{ 'admin.oauth2.user-info-uri-required' | translate }}
  193 + </mat-error>
  194 + <mat-error *ngIf="registration.get('userInfoUri').hasError('pattern')">
  195 + {{ 'admin.oauth2.uri-pattern-error' | translate }}
286 196 </mat-error>
287 197 </mat-form-field>
288 198 </div>
289 199
290 200 <mat-form-field fxFlex class="mat-block">
291   - <mat-label translate>admin.oauth2.customer-name-pattern</mat-label>
292   - <input matInput formControlName="customerNamePattern">
  201 + <mat-label translate>admin.oauth2.client-authentication-method</mat-label>
  202 + <mat-select formControlName="clientAuthenticationMethod">
  203 + <mat-option *ngFor="let clientAuthenticationMethod of clientAuthenticationMethods"
  204 + [value]="clientAuthenticationMethod">
  205 + {{ clientAuthenticationMethod | uppercase }}
  206 + </mat-option>
  207 + </mat-select>
293 208 </mat-form-field>
294 209
295   - <div fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="8px">
  210 + <div fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="8px" *ngIf="registration.get('providerName').value === 'Custom'">
296 211 <mat-form-field fxFlex class="mat-block">
297   - <mat-label translate>admin.oauth2.default-dashboard-name</mat-label>
298   - <input matInput formControlName="defaultDashboardName">
  212 + <mat-label translate>admin.oauth2.login-button-label</mat-label>
  213 + <input matInput formControlName="loginButtonLabel" required>
  214 + <mat-error
  215 + *ngIf="registration.get('loginButtonLabel').hasError('required')">
  216 + {{ 'admin.oauth2.login-button-label-required' | translate }}
  217 + </mat-error>
299 218 </mat-form-field>
300 219
301   - <mat-checkbox fxFlex formControlName="alwaysFullScreen" class="checkbox-row">
302   - {{ 'admin.oauth2.always-fullscreen' | translate}}
303   - </mat-checkbox>
  220 + <mat-form-field fxFlex class="mat-block">
  221 + <mat-label translate>admin.oauth2.login-button-icon</mat-label>
  222 + <input matInput formControlName="loginButtonIcon">
  223 + </mat-form-field>
304 224 </div>
305   - </section>
306   -
307   - <section formGroupName="custom"
308   - *ngIf="registration.get('mapperConfig.type').value === 'CUSTOM'">
309   - <mat-form-field class="mat-block">
310   - <mat-label translate>admin.oauth2.url</mat-label>
311   - <input matInput formControlName="url" required>
312   - <mat-error
313   - *ngIf="registration.get('mapperConfig.custom.url').hasError('required')">
314   - {{ 'admin.oauth2.url-required' | translate }}
315   - </mat-error>
316   - <mat-error
317   - *ngIf="registration.get('mapperConfig.custom.url').hasError('pattern')">
318   - {{ 'admin.oauth2.url-pattern' | translate }}
  225 +
  226 + <section formGroupName="mapperConfig">
  227 + <div fxLayout="column" fxLayoutGap="8px" style="margin-bottom: 8px;">
  228 + <mat-checkbox formControlName="allowUserCreation">
  229 + {{ 'admin.oauth2.allow-user-creation' | translate }}
  230 + </mat-checkbox>
  231 + <mat-checkbox formControlName="activateUser">
  232 + {{ 'admin.oauth2.activate-user' | translate }}
  233 + </mat-checkbox>
  234 + </div>
  235 + </section>
  236 +
  237 + <mat-form-field fxFlex class="mat-block">
  238 + <mat-label translate>admin.oauth2.scope</mat-label>
  239 + <mat-chip-list #scopeList>
  240 + <mat-chip *ngFor="let scope of registration.get('scope').value; let k = index;"
  241 + removable (removed)="removeScope(k, registration)">
  242 + {{scope}}
  243 + <mat-icon matChipRemove>cancel</mat-icon>
  244 + </mat-chip>
  245 + <input [matChipInputFor]="scopeList"
  246 + [matChipInputSeparatorKeyCodes]="separatorKeysCodes"
  247 + matChipInputAddOnBlur
  248 + (matChipInputTokenEnd)="addScope($event, registration)">
  249 + </mat-chip-list>
  250 + </mat-form-field>
  251 +
  252 + </mat-tab>
  253 + <mat-tab label="{{ 'admin.oauth2.mapper' | translate }}">
  254 + <mat-form-field class="mat-block" style="margin-top: 16px;">
  255 + <mat-label translate>admin.oauth2.user-name-attribute-name</mat-label>
  256 + <input matInput formControlName="userNameAttributeName" required>
  257 + <mat-error *ngIf="registration.get('userNameAttributeName').hasError('required')">
  258 + {{ 'admin.oauth2.user-name-attribute-name-required' | translate }}
319 259 </mat-error>
320 260 </mat-form-field>
321 261
322   - <div fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="8px">
  262 + <section formGroupName="mapperConfig">
323 263 <mat-form-field fxFlex class="mat-block">
324   - <mat-label translate>common.username</mat-label>
325   - <input matInput formControlName="username" autocomplete="new-username">
  264 + <mat-label translate>admin.oauth2.type</mat-label>
  265 + <mat-select formControlName="type">
  266 + <mat-option *ngFor="let converterTypeExternalUser of converterTypesExternalUser"
  267 + [value]="converterTypeExternalUser">
  268 + {{ converterTypeExternalUser }}
  269 + </mat-option>
  270 + </mat-select>
326 271 </mat-form-field>
327 272
328   - <mat-form-field fxFlex class="mat-block">
329   - <mat-label translate>common.password</mat-label>
330   - <input matInput type="password" formControlName="password" autocomplete="new-password">
331   - </mat-form-field>
332   - </div>
333   - </section>
334   - </section>
335   - </mat-tab>
336   - </mat-tab-group>
  273 + <section formGroupName="basic"
  274 + *ngIf="registration.get('mapperConfig.type').value === 'BASIC'">
  275 + <mat-form-field class="mat-block">
  276 + <mat-label translate>admin.oauth2.email-attribute-key</mat-label>
  277 + <input matInput formControlName="emailAttributeKey" required>
  278 + <mat-error
  279 + *ngIf="registration.get('mapperConfig.basic.emailAttributeKey').hasError('required')">
  280 + {{ 'admin.oauth2.email-attribute-key-required' | translate }}
  281 + </mat-error>
  282 + </mat-form-field>
  283 +
  284 + <div fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="8px">
  285 + <mat-form-field fxFlex class="mat-block">
  286 + <mat-label translate>admin.oauth2.first-name-attribute-key</mat-label>
  287 + <input matInput formControlName="firstNameAttributeKey">
  288 + </mat-form-field>
  289 +
  290 + <mat-form-field fxFlex class="mat-block">
  291 + <mat-label translate>admin.oauth2.last-name-attribute-key</mat-label>
  292 + <input matInput formControlName="lastNameAttributeKey">
  293 + </mat-form-field>
  294 + </div>
  295 +
  296 + <div fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="8px">
  297 + <mat-form-field fxFlex class="mat-block">
  298 + <mat-label translate>admin.oauth2.tenant-name-strategy</mat-label>
  299 + <mat-select formControlName="tenantNameStrategy">
  300 + <mat-option *ngFor="let tenantNameStrategy of tenantNameStrategies"
  301 + [value]="tenantNameStrategy">
  302 + {{ tenantNameStrategy }}
  303 + </mat-option>
  304 + </mat-select>
  305 + </mat-form-field>
  306 +
  307 + <mat-form-field fxFlex class="mat-block" *ngIf="registration.get('mapperConfig.basic.tenantNameStrategy').value === 'CUSTOM'">
  308 + <mat-label translate>admin.oauth2.tenant-name-pattern</mat-label>
  309 + <input matInput
  310 + formControlName="tenantNamePattern"
  311 + [required]="registration.get('mapperConfig.basic.tenantNameStrategy').value === 'CUSTOM'">
  312 + <mat-error
  313 + *ngIf="registration.get('mapperConfig.basic.tenantNamePattern').hasError('required')">
  314 + {{ 'admin.oauth2.tenant-name-pattern-required' | translate }}
  315 + </mat-error>
  316 + </mat-form-field>
  317 + </div>
  318 +
  319 + <mat-form-field fxFlex class="mat-block">
  320 + <mat-label translate>admin.oauth2.customer-name-pattern</mat-label>
  321 + <input matInput formControlName="customerNamePattern">
  322 + </mat-form-field>
  323 +
  324 + <div fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="8px">
  325 + <mat-form-field fxFlex class="mat-block">
  326 + <mat-label translate>admin.oauth2.default-dashboard-name</mat-label>
  327 + <input matInput formControlName="defaultDashboardName">
  328 + </mat-form-field>
  329 +
  330 + <mat-checkbox fxFlex formControlName="alwaysFullScreen" class="checkbox-row">
  331 + {{ 'admin.oauth2.always-fullscreen' | translate}}
  332 + </mat-checkbox>
  333 + </div>
  334 + </section>
  335 +
  336 + <section formGroupName="custom"
  337 + *ngIf="registration.get('mapperConfig.type').value === 'CUSTOM'">
  338 + <mat-form-field class="mat-block">
  339 + <mat-label translate>admin.oauth2.url</mat-label>
  340 + <input matInput formControlName="url" required>
  341 + <mat-error
  342 + *ngIf="registration.get('mapperConfig.custom.url').hasError('required')">
  343 + {{ 'admin.oauth2.url-required' | translate }}
  344 + </mat-error>
  345 + <mat-error
  346 + *ngIf="registration.get('mapperConfig.custom.url').hasError('pattern')">
  347 + {{ 'admin.oauth2.url-pattern' | translate }}
  348 + </mat-error>
  349 + </mat-form-field>
  350 +
  351 + <div fxLayout="row" fxLayout.xs="column" fxLayoutGap.gt-xs="8px">
  352 + <mat-form-field fxFlex class="mat-block">
  353 + <mat-label translate>common.username</mat-label>
  354 + <input matInput formControlName="username" autocomplete="new-username">
  355 + </mat-form-field>
  356 +
  357 + <mat-form-field fxFlex class="mat-block">
  358 + <mat-label translate>common.password</mat-label>
  359 + <input matInput type="password" formControlName="password" autocomplete="new-password">
  360 + </mat-form-field>
  361 + </div>
  362 + </section>
  363 + </section>
  364 + </mat-tab>
  365 + </mat-tab-group>
  366 + </ng-template>
  367 + </mat-expansion-panel>
337 368
338 369 </section>
339 370 </ng-template>
... ...
... ... @@ -21,9 +21,32 @@
21 21 .registration-card{
22 22 margin-bottom: 8px;
23 23 border: 1px solid rgba(0, 0, 0, 0.2);
  24 +
  25 + .custom-settings{
  26 + font-size: 16px;
  27 + .mat-expansion-panel-header{
  28 + padding: 0 2px;
  29 + }
  30 + }
24 31 }
25 32
26 33 .container{
27 34 margin-bottom: 16px;
28 35 }
29 36 }
  37 +
  38 +:host ::ng-deep{
  39 + .registration-card{
  40 + .custom-settings{
  41 + .mat-expansion-panel-body{
  42 + padding: 0 2px 16px;
  43 + }
  44 + .mat-tab-label{
  45 + text-transform: none;
  46 + }
  47 + .mat-form-field-suffix .mat-icon-button .mat-icon{
  48 + font-size: 18px;
  49 + }
  50 + }
  51 + }
  52 +}
... ...
... ... @@ -18,6 +18,7 @@ import { ChangeDetectorRef, Component, Inject, OnDestroy, OnInit, ViewContainerR
18 18 import { AbstractControl, FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms';
19 19 import {
20 20 ClientAuthenticationMethod,
  21 + ClientProviderTemplated,
21 22 ClientRegistration,
22 23 DomainParams,
23 24 MapperConfigType,
... ... @@ -50,9 +51,24 @@ import {
50 51 })
51 52 export class OAuth2SettingsComponent extends PageComponent implements OnInit, HasConfirmForm, OnDestroy {
52 53
53   - private URL_REGEXP = /^[A-Za-z][A-Za-z\d.+-]*:\/*(?:\w+(?::\w+)?@)?[^\s/]+(?::\d+)?(?:\/[\w#!:.?+=&%@\-/]*)?$/;
  54 + private URL_REGEXP = /^[A-Za-z][A-Za-z\d.+-]*:\/*(?:\w+(?::\w+)?@)?[^\s/]+(?::\d+)?(?:\/[\w#!:.,?+=&%@\-/]*)?$/;
54 55 private subscriptions: Subscription[] = [];
55   - private templates = [];
  56 + private templates = new Map<string, ClientProviderTemplated>();
  57 + private defaultProvider = {
  58 + providerName: 'Custom',
  59 + clientAuthenticationMethod: 'Post',
  60 + userNameAttributeName: 'email',
  61 + mapperConfig: {
  62 + allowUserCreation: true,
  63 + activateUser: false,
  64 + type: 'BASIC',
  65 + basic: {
  66 + emailAttributeKey: 'email',
  67 + tenantNameStrategy: 'DOMAIN',
  68 + alwaysFullScreen: false
  69 + }
  70 + }
  71 + };
56 72
57 73 readonly separatorKeysCodes: number[] = [ENTER, COMMA];
58 74
... ... @@ -99,9 +115,9 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
99 115 });
100 116 }
101 117
102   - private initTemplates(templates: any): void {
103   - this.templates = templates;
104   - templates.map(provider => this.templateProvider.push(provider.name));
  118 + private initTemplates(templates: ClientProviderTemplated[]): void {
  119 + templates.map(provider => this.templates.set(provider.name, provider));
  120 + this.templateProvider.push(...Array.from(this.templates.keys()));
105 121 this.templateProvider.sort();
106 122 }
107 123
... ... @@ -118,7 +134,7 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
118 134 tenantNamePattern: [null],
119 135 customerNamePattern: [null],
120 136 defaultDashboardName: [null],
121   - alwaysFullScreen: [false],
  137 + alwaysFullScreen: [false]
122 138 });
123 139
124 140 this.subscriptions.push(basicGroup.get('tenantNameStrategy').valueChanges.subscribe((domain) => {
... ... @@ -209,7 +225,7 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
209 225 accessTokenUri: ['', [Validators.required, Validators.pattern(this.URL_REGEXP)]],
210 226 authorizationUri: ['', [Validators.required, Validators.pattern(this.URL_REGEXP)]],
211 227 scope: this.fb.array([], [Validators.required]),
212   - jwkSetUri: ['', [Validators.required, Validators.pattern(this.URL_REGEXP)]],
  228 + jwkSetUri: ['', [Validators.pattern(this.URL_REGEXP)]],
213 229 userInfoUri: ['', [Validators.required, Validators.pattern(this.URL_REGEXP)]],
214 230 clientAuthenticationMethod: ['POST', [Validators.required]],
215 231 userNameAttributeName: ['email', [Validators.required]],
... ... @@ -233,6 +249,27 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
233 249 }
234 250 }));
235 251
  252 + this.subscriptions.push(clientRegistration.get('providerName').valueChanges.subscribe((provider) => {
  253 + (clientRegistration.get('scope') as FormArray).clear();
  254 + if (provider === 'Custom') {
  255 + clientRegistration.reset(this.defaultProvider, {emitEvent: false});
  256 + clientRegistration.get('accessTokenUri').enable();
  257 + clientRegistration.get('authorizationUri').enable();
  258 + clientRegistration.get('jwkSetUri').enable();
  259 + clientRegistration.get('userInfoUri').enable();
  260 + } else {
  261 + const template = this.templates.get(provider);
  262 + template.scope.forEach(() => {
  263 + (clientRegistration.get('scope') as FormArray).push(this.fb.control(''));
  264 + });
  265 + clientRegistration.get('accessTokenUri').disable();
  266 + clientRegistration.get('authorizationUri').disable();
  267 + clientRegistration.get('jwkSetUri').disable();
  268 + clientRegistration.get('userInfoUri').disable();
  269 + clientRegistration.patchValue(this.templates.get(provider), {emitEvent: false});
  270 + }
  271 + }));
  272 +
236 273 if (registrationData) {
237 274 registrationData.scope.forEach(() => {
238 275 (clientRegistration.get('scope') as FormArray).push(this.fb.control(''));
... ... @@ -366,4 +403,8 @@ export class OAuth2SettingsComponent extends PageComponent implements OnInit, Ha
366 403 }
367 404 });
368 405 }
  406 +
  407 + toggleEditMode(control: AbstractControl, path: string) {
  408 + control.get(path).disabled ? control.get(path).enable() : control.get(path).disable();
  409 + }
369 410 }
... ...
... ... @@ -14,6 +14,9 @@
14 14 /// limitations under the License.
15 15 ///
16 16
  17 +import { EntityId } from '@shared/models/id/entity-id';
  18 +import { TenantId } from '@shared/models/id/tenant-id';
  19 +
17 20 export const smtpPortPattern: RegExp = /^([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$/;
18 21
19 22 export interface AdminSettings<T> {
... ... @@ -75,6 +78,17 @@ export interface DomainParams {
75 78 clientRegistrations: ClientRegistration[];
76 79 }
77 80
  81 +export interface ClientProviderTemplated extends ClientRegistration{
  82 + additionalInfo: string;
  83 + comment: string;
  84 + createdTime: number;
  85 + helpLink: string;
  86 + id: EntityId;
  87 + name: string;
  88 + providerId: string;
  89 + tenantId: TenantId;
  90 +}
  91 +
78 92 export interface ClientRegistration {
79 93 loginButtonLabel: string;
80 94 loginButtonIcon: string;
... ...
... ... @@ -128,7 +128,7 @@
128 128 "add-provider": "Add provider",
129 129 "settings": "Settings",
130 130 "oauth2": {
131   - "settings": "OAuth2 Settings",
  131 + "oauth2": "OAuth2",
132 132 "registration-id": "Registration ID",
133 133 "registration-id-required": "Registration ID is required.",
134 134 "registration-id-unique": "Registration ID need to unique for the system.",
... ... @@ -145,7 +145,6 @@
145 145 "redirect-uri-template": "Redirect URI template",
146 146 "redirect-uri-template-required": "Redirect URI template is required.",
147 147 "jwk-set-uri": "JSON Web Key URI",
148   - "jwk-set-uri-required": "JSON Web Key URI is required.",
149 148 "user-info-uri": "User info URI",
150 149 "user-info-uri-required": "User info URI is required.",
151 150 "client-authentication-method": "Client authentication method",
... ... @@ -173,7 +172,11 @@
173 172 "delete-domain-title": "Are you sure you want to delete the domain '{{domainName}}'?",
174 173 "delete-domain-text": "Be careful, after the confirmation a domain and all registration data will be unavailable.",
175 174 "delete-registration-title": "Are you sure you want to delete the registration '{{name}}'?",
176   - "delete-registration-text": "Be careful, after the confirmation a registration data will be unavailable."
  175 + "delete-registration-text": "Be careful, after the confirmation a registration data will be unavailable.",
  176 + "login-provider": "Login provider",
  177 + "custom-setting": "Custom settings",
  178 + "general": "General",
  179 + "mapper": "Mapper"
177 180 }
178 181 },
179 182 "alarm": {
... ...