[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[reclaim-ui] 381/459: even more quality of life improvements
From: |
gnunet |
Subject: |
[reclaim-ui] 381/459: even more quality of life improvements |
Date: |
Fri, 11 Jun 2021 23:27:53 +0200 |
This is an automated email from the git hooks/post-receive script.
martin-schanzenbach pushed a commit to branch master
in repository reclaim-ui.
commit 3e47b9ccd2749ab48a62f6e1ac4b4938a350a13b
Author: Martin Schanzenbach <schanzen@gnunet.org>
AuthorDate: Sun Dec 27 14:16:56 2020 +0900
even more quality of life improvements
---
src/app/config.service.ts | 8 +-
src/app/credential.service.ts | 6 +-
src/app/edit-identity/edit-identity.component.html | 80 +++----
src/app/edit-identity/edit-identity.component.ts | 244 ++++++++++++++++++++-
src/locales/de/messages.json | 7 +-
src/locales/en/messages.json | 7 +-
6 files changed, 298 insertions(+), 54 deletions(-)
diff --git a/src/app/config.service.ts b/src/app/config.service.ts
index b08b9a8..7a10c0e 100644
--- a/src/app/config.service.ts
+++ b/src/app/config.service.ts
@@ -9,18 +9,22 @@ export class ConfigService {
defaultConfig: Config;
constructor(private http: HttpClient) {
+ this.config = new Config('',true);
var confString = localStorage.getItem('reclaimSettings');
+ this.config = new Config('',true);
try {
- this.config = JSON.parse(confString);
- if (this.config == null) {
+ var jsonConfig = JSON.parse(confString);
+ if (jsonConfig == null) {
this.loadDefaults();
} else {
+ this.config = jsonConfig;
console.log("Loaded settings: " + confString);
}
} catch(e) {
this.loadDefaults();
console.log("Error loading settings: " + e);
}
+
}
loadDefaults() {
diff --git a/src/app/credential.service.ts b/src/app/credential.service.ts
index 699324f..550f0d3 100644
--- a/src/app/credential.service.ts
+++ b/src/app/credential.service.ts
@@ -23,7 +23,11 @@ export class CredentialService {
var redirectUri;
if (window.location.href.includes('localhost')){
const user = localStorage.getItem('userForCredential');
- redirectUri = 'http://localhost:4200/import-attributes/' + user;
+ if (window.location.href.includes('import-attributes')){
+ redirectUri = 'http://localhost:4200/import-attributes/' + user;
+ } else {
+ redirectUri = 'http://localhost:4200/edit-identity/' + user;
+ }
}
else {
redirectUri = "https://ui.reclaim";
diff --git a/src/app/edit-identity/edit-identity.component.html
b/src/app/edit-identity/edit-identity.component.html
index aa7414c..10d7a68 100644
--- a/src/app/edit-identity/edit-identity.component.html
+++ b/src/app/edit-identity/edit-identity.component.html
@@ -9,36 +9,29 @@
<h2 class="fa-2x"><i class="fa fa-user-circle pr-2"></i> {{
identity.name }}</h2>
</div>
</div>
- <!--IdProvider-Discovery-->
- <div *ngIf="!hasAttributes()" class="alert alert-primary alert-dismissible
fade show my-2" role="alert" >
- <span class="fa fa-info"> </span> <b
class="ml-2">{{getMessage("edit_identity_html@noAttributes")}}</b><br/>
- {{getMessage("edit_identity_html@importInfo")}}<br/>
- <button class="btn btn-primary" [routerLink]="['/import-attributes',
identity.name ]">
- <span class="fa fa-download"></span>
{{getMessage("edit_identity_html@linkAccount")}}
- </button>
- </div>
+ <div class="card-body text-center fa-4x" *ngIf="importInProgress">
+ <i class="fa fa-spinner fa-spin"></i>
+ Please wait
+ </div>
<!-- Attribute table -->
- <div class="card-body">
+ <div class="card-body" *ngIf="!importInProgress">
<div>
- <h3 class="card-subtitle mb-2">
{{getMessage("edit_identity_html@basicInfo")}} <span (click)="showGeneralInfo =
!showGeneralInfo" class="fa fa-question-circle"></span></h3>
+ <h3 class="card-subtitle mb-4">
{{getMessage("edit_identity_html@basicInfo")}} <span (click)="showGeneralInfo =
!showGeneralInfo" class="fa fa-question-circle"></span></h3>
<div class="alert alert-secondary fade show" *ngIf="showGeneralInfo" >
{{getMessage("edit_identity_html@standardScopes")}}
</div>
-
<div class="table pb-1">
- <!-- Standard "profile" claims first -->
+ <!-- Standard "email" claims first -->
<div class="row mb-3" [class.openid]="inOpenIdFlow()"
[class.text-primary]="isClaimRequested(claim) || claim ==
claimInEdit"
[class.alert-danger]="newAttribute.name === claim.name"
- *ngFor="let claim of existingProfileClaims">
+ *ngFor="let claim of existingEmailClaims">
<div class="col-sm"><div style="min-width: 15em">
- <i *ngIf="isClaimRequested(claim)" class="fa
fa-openid"></i><b> {{ getDescription(claim) }}</b>
- </div>
- </div>
+ <i *ngIf="isClaimRequested(claim)" class="fa
fa-openid"></i><b> {{ getDescription(claim) }}</b></div></div>
<div class="col-sm">
<input *ngIf="!isClaimCred(claim) && (claim == claimInEdit)"
placeholder="{{ getMessage('Value') }}" [(ngModel)]="claim.value">
- <span *ngIf="!isClaimCred(claim) && (claim != claimInEdit)">{{
claim.value }} <i class="text-secondary" style="float:right;"><i class="fa
fa-certificate"></i> Self-issued</i></span>
+ <span *ngIf="!isClaimCred(claim) && (claim != claimInEdit)">{{
claim.value }} <i class="text-secondary" style="float:right;"><i class="fa
fa-certificate"></i> {{ getMessage("edit_identity_html@selfissued")
}}</i></span>
<span *ngIf="isClaimCred(claim)" >{{ getCredValue(claim) }} <i
class="text-primary" style="float:right;"><i class="fa fa-certificate"></i> {{
getIssuer(claim) }}</i></span>
</div>
<div class="col-sm">
@@ -48,19 +41,23 @@
<button class="ml-1 btn btn-primary"
(click)="editAttribute(claim)" *ngIf="!isClaimCred(claim) && (claim !=
claimInEdit)">
<span class="fa fa-edit"></span>
</button>
+ <button *ngIf="validImportEmail" class="ml-1 btn btn-primary"
(click)="import()">
+ <span class="fa fa-download"></span>
{{getMessage("edit_identity_html@importFrom", {ISSUERNAME:
getImportIssuerName()})}}
+ </button>
+
</div>
</div>
- <!-- Standard "profile" claims missing on the identity -->
+ <!-- Standard "email" claims missing on the identity -->
<div class="row mb-3" [class.openid]="inOpenIdFlow()"
[class.text-primary]="isClaimRequested(claim) || claim ==
claimInEdit"
[class.alert-danger]="newAttribute.name === claim.name"
- *ngFor="let claim of missingProfileClaims">
+ *ngFor="let claim of missingEmailClaims">
<div class="col-sm"><div style="min-width: 15em">
<i *ngIf="isClaimRequested(claim)" class="fa
fa-openid"></i><b> {{ getDescription(claim) }}</b></div></div>
<div class="col-sm">
<!-- FIXME Allow adding of credential OR plain value -->
<input *ngIf="claim == claimInEdit" placeholder="{{
getMessage('Value') }}" [(ngModel)]="claim.value">
- <span *ngIf="claim != claimInEdit"><i
class="text-secondary">Unset</i></span>
+ <span *ngIf="claim != claimInEdit"><i class="text-secondary">{{
getMessage("edit_identity_html@unset") }}</i></span>
<!--<input *ngIf="!isClaimCred(claim)" placeholder="{{
getMessage('Value') }}" [(ngModel)]="claim.value">
<span *ngIf="isClaimCred(claim)" >{{ getCredValue(claim) }}
issued by <i>{{ getIssuer(claim) }}</i> as attribute for ``{{ claim.value
}}''</span>-->
</div>
@@ -73,18 +70,28 @@
</button>
</div>
</div>
+ <div class="row mb-3" *ngIf="validImportEmail">
+ <!-- Instructions -->
+ <div
+ class="col-sm alert alert-primary alert-dismissible fade show
my-2" role="alert" >
+ {{getMessage("edit_identity_html@importInfo")}}<br/>
+
<i>{{getMessage("Note")}}</i>{{getMessage("edit_credentials_html@linkAccountInfo2")}}
+ </div>
+ </div>
</div>
<div class="table pb-1">
- <!-- Standard "email" claims first -->
+ <!-- Standard "profile" claims first -->
<div class="row mb-3" [class.openid]="inOpenIdFlow()"
[class.text-primary]="isClaimRequested(claim) || claim ==
claimInEdit"
[class.alert-danger]="newAttribute.name === claim.name"
- *ngFor="let claim of existingEmailClaims">
+ *ngFor="let claim of existingProfileClaims">
<div class="col-sm"><div style="min-width: 15em">
- <i *ngIf="isClaimRequested(claim)" class="fa
fa-openid"></i><b> {{ getDescription(claim) }}</b></div></div>
+ <i *ngIf="isClaimRequested(claim)" class="fa
fa-openid"></i><b> {{ getDescription(claim) }}</b>
+ </div>
+ </div>
<div class="col-sm">
<input *ngIf="!isClaimCred(claim) && (claim == claimInEdit)"
placeholder="{{ getMessage('Value') }}" [(ngModel)]="claim.value">
- <span *ngIf="!isClaimCred(claim) && (claim != claimInEdit)">{{
claim.value }} <i class="text-secondary" style="float:right;"><i class="fa
fa-certificate"></i> Self-issued</i></span>
+ <span *ngIf="!isClaimCred(claim) && (claim != claimInEdit)">{{
claim.value }} <i class="text-secondary" style="float:right;"><i class="fa
fa-certificate"></i> {{ getMessage("edit_identity_html@selfissued")
}}</i></span>
<span *ngIf="isClaimCred(claim)" >{{ getCredValue(claim) }} <i
class="text-primary" style="float:right;"><i class="fa fa-certificate"></i> {{
getIssuer(claim) }}</i></span>
</div>
<div class="col-sm">
@@ -96,17 +103,17 @@
</button>
</div>
</div>
- <!-- Standard "email" claims missing on the identity -->
+ <!-- Standard "profile" claims missing on the identity -->
<div class="row mb-3" [class.openid]="inOpenIdFlow()"
[class.text-primary]="isClaimRequested(claim) || claim ==
claimInEdit"
[class.alert-danger]="newAttribute.name === claim.name"
- *ngFor="let claim of missingEmailClaims">
+ *ngFor="let claim of missingProfileClaims">
<div class="col-sm"><div style="min-width: 15em">
<i *ngIf="isClaimRequested(claim)" class="fa
fa-openid"></i><b> {{ getDescription(claim) }}</b></div></div>
<div class="col-sm">
<!-- FIXME Allow adding of credential OR plain value -->
<input *ngIf="claim == claimInEdit" placeholder="{{
getMessage('Value') }}" [(ngModel)]="claim.value">
- <span *ngIf="claim != claimInEdit"><i
class="text-secondary">Unset</i></span>
+ <span *ngIf="claim != claimInEdit"><i class="text-secondary">{{
getMessage("edit_identity_html@unset") }}</i></span>
<!--<input *ngIf="!isClaimCred(claim)" placeholder="{{
getMessage('Value') }}" [(ngModel)]="claim.value">
<span *ngIf="isClaimCred(claim)" >{{ getCredValue(claim) }}
issued by <i>{{ getIssuer(claim) }}</i> as attribute for ``{{ claim.value
}}''</span>-->
</div>
@@ -121,7 +128,6 @@
</div>
</div>
-
<div class="table pb-1">
<!-- Standard "address" claims first -->
<div class="row mb-3" [class.openid]="inOpenIdFlow()"
@@ -132,7 +138,7 @@
<i *ngIf="isClaimRequested(claim)" class="fa
fa-openid"></i><b> {{ getDescription(claim) }}</b></div></div>
<div class="col-sm">
<input *ngIf="!isClaimCred(claim) && (claim == claimInEdit)"
placeholder="{{ getMessage('Value') }}" [(ngModel)]="claim.value">
- <span *ngIf="!isClaimCred(claim) && (claim != claimInEdit)">{{
claim.value }} <i class="text-secondary" style="float:right;"><i class="fa
fa-certificate"></i> Self-issued</i></span>
+ <span *ngIf="!isClaimCred(claim) && (claim != claimInEdit)">{{
claim.value }} <i class="text-secondary" style="float:right;"><i class="fa
fa-certificate"></i> {{ getMessage("edit_identity_html@selfissued")
}}</i></span>
<span *ngIf="isClaimCred(claim)" >{{ getCredValue(claim) }} <i
class="text-primary" style="float:right;"><i class="fa fa-certificate"></i> {{
getIssuer(claim) }}</i></span>
</div>
<div class="col-sm">
@@ -155,7 +161,7 @@
<div class="col-sm">
<!-- FIXME Allow adding of credential OR plain value -->
<input *ngIf="claim == claimInEdit" placeholder="{{
getMessage('Value') }}" [(ngModel)]="claim.value">
- <span *ngIf="claim != claimInEdit"><i
class="text-secondary">Unset</i></span>
+ <span *ngIf="claim != claimInEdit"><i class="text-secondary">{{
getMessage("edit_identity_html@unset") }}</i></span>
<!--<input *ngIf="!isClaimCred(claim)" placeholder="{{
getMessage('Value') }}" [(ngModel)]="claim.value">
<span *ngIf="isClaimCred(claim)" >{{ getCredValue(claim) }}
issued by <i>{{ getIssuer(claim) }}</i> as attribute for ``{{ claim.value
}}''</span>-->
</div>
@@ -180,7 +186,7 @@
<i *ngIf="isClaimRequested(claim)" class="fa
fa-openid"></i><b> {{ getDescription(claim) }}</b></div></div>
<div class="col-sm">
<input *ngIf="!isClaimCred(claim) && (claim == claimInEdit)"
placeholder="{{ getMessage('Value') }}" [(ngModel)]="claim.value">
- <span *ngIf="!isClaimCred(claim) && (claim != claimInEdit)">{{
claim.value }} <i class="text-secondary" style="float:right;"><i class="fa
fa-certificate"></i> Self-issued</i></span>
+ <span *ngIf="!isClaimCred(claim) && (claim != claimInEdit)">{{
claim.value }} <i class="text-secondary" style="float:right;"><i class="fa
fa-certificate"></i> {{ getMessage("edit_identity_html@selfissued")
}}</i></span>
<span *ngIf="isClaimCred(claim)" >{{ getCredValue(claim) }} <i
class="text-primary" style="float:right;"><i class="fa fa-certificate"></i> {{
getIssuer(claim) }}</i></span>
</div>
<div class="col-sm">
@@ -216,12 +222,12 @@
</div>
</div>
<input *ngIf="claim == claimInEdit && claim.flag == '0'"
placeholder="{{ getMessage('Value') }}" [(ngModel)]="claim.value">
- <span *ngIf="claim != claimInEdit"><i
class="text-secondary">Unset</i></span>
+ <span *ngIf="claim != claimInEdit"><i class="text-secondary">{{
getMessage("edit_identity_html@unset") }}</i></span>
<select *ngIf="claim == claimInEdit && claim.flag == '1' &&
hasCredentialSources()" class="custom-select"
(change)="claim.credential=$event.target.value; " >
<option value="">{{
getMessage("edit_identity_html@selectSource") }}</option>
<option *ngFor="let cred of credentials" value={{cred.id}}>
- {{cred.name}}
+ {{getIssuerName(cred)}}
</option>
</select>
<div *ngIf="claim.flag == '1' && !hasCredentialSources()"
class="alert alert-primary" role="alert">
@@ -249,7 +255,7 @@
</div>
- <h3 class="card-subtitle mb-2" >{{
getMessage("edit_identity_html@additionalInfo") }} <span (click)="showExtraInfo
= !showExtraInfo" class="fa fa-question-circle"></span></h3>
+ <h3 class="card-subtitle mb-4" >{{
getMessage("edit_identity_html@additionalInfo") }} <span (click)="showExtraInfo
= !showExtraInfo" class="fa fa-question-circle"></span></h3>
<div class="alert alert-secondary fade show" *ngIf="showExtraInfo" >
{{ getMessage("edit_identity_html@non_standardClaims") }}
</div>
@@ -268,7 +274,7 @@
<select *ngIf="isClaimCredentialRequested(missing) &&
hasCredentialSources()" class="custom-select"
(change)="missing.credential=$event.target.value; ">
<option value="">{{
getMessage("edit_identity_html@selectSource") }}</option>
<option *ngFor="let cred of credentials" value={{cred.id}}>
- {{cred.name}}
+ {{getIssuerName(cred)}}
</option>
</select>
<div *ngIf="isClaimCredentialRequested(missing) &&
!hasCredentialSources()" class="alert alert-primary" role="alert">
@@ -299,7 +305,7 @@
</div>
<div class="col-sm">
<input *ngIf="!isClaimCred(attribute) && (attribute ==
claimInEdit)" placeholder="{{ getMessage('Value') }}"
[(ngModel)]="attribute.value">
- <span *ngIf="!isClaimCred(attribute) && (attribute !=
claimInEdit)">{{ attribute.value }} <i class="text-secondary"
style="float:right;"><i class="fa fa-certificate"></i> Self-issued</i></span>
+ <span *ngIf="!isClaimCred(attribute) && (attribute !=
claimInEdit)">{{ attribute.value }} <i class="text-secondary"
style="float:right;"><i class="fa fa-certificate"></i> {{
getMessage("edit_identity_html@selfissued") }}</i></span>
<span *ngIf="isClaimCred(attribute)" >{{
getCredValue(attribute) }} <i class="text-primary" style="float:right;"><i
class="fa fa-certificate"></i> {{ getIssuer(attribute) }}</i></span>
</div>
<div class="col-sm">
@@ -339,7 +345,7 @@
(change)="newAttribute.credential=$event.target.value; " >
<option value="">{{
getMessage("edit_identity_html@selectSource") }}</option>
<option *ngFor="let cred of credentials" value={{cred.id}}>
- {{cred.name}}
+ {{getIssuerName(cred)}}
</option>
</select>
<div *ngIf="newAttribute.flag == '1' && !hasCredentialSources()"
class="alert alert-primary" role="alert">
diff --git a/src/app/edit-identity/edit-identity.component.ts
b/src/app/edit-identity/edit-identity.component.ts
index 57cbaf0..8c6a060 100644
--- a/src/app/edit-identity/edit-identity.component.ts
+++ b/src/app/edit-identity/edit-identity.component.ts
@@ -4,6 +4,7 @@ import { ReclaimService } from '../reclaim.service';
import { Identity } from '../identity';
import { GnsService } from '../gns.service';
import { NamestoreService } from '../namestore.service';
+import { CredentialService } from '../credential.service';
import { OpenIdService } from '../open-id.service';
import { Attribute } from '../attribute';
import { Credential } from '../credential';
@@ -11,9 +12,11 @@ import { IdentityService } from '../identity.service';
import { finalize } from 'rxjs/operators';
import { from, forkJoin, EMPTY } from 'rxjs';
import { Authorization } from '../authorization';
-import { IdProvider } from '../idProvider';
import { ConfigService } from '../config.service';
import { LanguageService } from '../language.service';
+import { IdProvider } from '../idProvider';
+import { Scope } from '../scope';
+import { OAuthService, LoginOptions } from 'angular-oauth2-oidc';
@Component({
selector: 'app-edit-identity',
@@ -33,7 +36,6 @@ export class EditIdentityComponent implements OnInit {
optionalClaims: Attribute[] = [];
webfingerEmail: string;
authorizations: Authorization[] = [];
- newIdProvider: IdProvider;
emailNotFoundAlertClosed: boolean = true;
existingProfileClaims: Attribute[] = [];
missingProfileClaims: Attribute[] = [];
@@ -50,6 +52,13 @@ export class EditIdentityComponent implements OnInit {
actions: string = '';
claimInEdit: Attribute = null;
+ //Attribute import
+ importIdProvider: IdProvider;
+ validImportEmail: boolean = false;
+ importInProgress: boolean = false;
+ scopes: Scope[];
+ newCredential: Credential;
+
constructor(private reclaimService: ReclaimService,
private identityService: IdentityService,
private gnsService: GnsService,
@@ -58,16 +67,21 @@ export class EditIdentityComponent implements OnInit {
private activatedRoute: ActivatedRoute,
private configService: ConfigService,
private languageService: LanguageService,
+ private credentialService: CredentialService,
+ private oauthService: OAuthService,
private router: Router,) {}
ngOnInit() {
this.credentialValues = {};
this.webfingerEmail = '';
- this.newIdProvider = new IdProvider ('', '');
+ this.importIdProvider = new IdProvider ('', '');
this.loadAuthorizationsFromLocalStorage();
this.identity = new Identity('','');
this.newAttribute = new Attribute('', '', '', '', 'STRING', '0');
this.newCredClaim = new Attribute('', '', '', '', 'STRING', '1');
+ this.newCredential = new Credential('', '', '', 'JWT', '', 0, []);
+ this.loadImportScopesFromLocalStorage()
+ this.loadImportIdProviderFromLocalStorage();
this.activatedRoute.params.subscribe(p => {
if (p['id'] === undefined) {
return;
@@ -79,6 +93,9 @@ export class EditIdentityComponent implements OnInit {
this.identity = ids[i];
this.updateAttributes();
this.updateCredentials();
+ /*if (this.importIdProvider.url !== '') {
+ this.tryImportCredential();
+ }*/
}
}
});
@@ -146,6 +163,7 @@ export class EditIdentityComponent implements OnInit {
this.existingPhoneClaims =
this.cleanupClaimArray(this.existingPhoneClaims);
this.existingAddressClaims =
this.cleanupClaimArray(this.existingAddressClaims);
this.updateMissingAttributes();
+ this.validateEmailForImport();
},
err => {
//this.errorInfos.push("Error retrieving attributes for ``" +
identity.name + "''");
@@ -153,6 +171,7 @@ export class EditIdentityComponent implements OnInit {
});
}
+
inOpenIdFlow() {
return this.oidcService.inOpenIdFlow();
}
@@ -488,13 +507,6 @@ export class EditIdentityComponent implements OnInit {
return this.credentials.length > 0
}
- mapIssuer(iss: string): string {
- if (iss == "https://omejdn.nslab.ch") {
- return "Berner Fachhochschule";
- }
- return iss;
- }
-
//FIXME credentials need an issuer field
getIssuer(attribute: Attribute) {
for (let i = 0; i < this.credentials.length; i++) {
@@ -560,4 +572,216 @@ export class EditIdentityComponent implements OnInit {
editAttribute(claim: Attribute) {
this.claimInEdit = claim;
}
+
+ loadImportScopesFromLocalStorage(){
+ this.scopes = [];
+ var loadedScopes = localStorage.getItem("scopes");
+ if (loadedScopes==null){
+ return
+ }
+ loadedScopes.split(',{').forEach(scopeObject => {
+ var scopeName = scopeObject.split(',')[0];
+ var scopeChosen = scopeObject.split(',')[1].slice(0, -1);
+ const scopeInterface: Scope = {
+ scope: scopeName.split(':')[1].slice(1,-1),
+ chosen: (/true/i).test(scopeChosen.split(':')[1]),
+ }
+ this.scopes.push(scopeInterface)
+ }
+ );
+ }
+
+ loadImportIdProviderFromLocalStorage(){
+ this.importIdProvider.url = localStorage.getItem("importIdProviderURL") ||
'';
+ this.importIdProvider.name = this.importIdProvider.url.split('//')[1];
+ }
+
+ tryImportCredential() {
+ if (this.importIdProvider.url === '') {
+ return;
+ }
+ const loginOptions: LoginOptions = {
+ customHashFragment: "?code="+localStorage.getItem("credentialCode") +
"&state=" + localStorage.getItem("credentialState") + "&session_state="+
localStorage.getItem("credentialSession_State"),
+ }
+ this.configureOauthService();
+ if (!localStorage.getItem("credentialCode")){
+ this.oauthService.loadDiscoveryDocumentAndTryLogin().then(success => {
+ if (!success || (null == this.oauthService.getIdToken())) {
+ this.importInProgress = false;
+ return;
+ }
+ console.log("Login successful: "+this.oauthService.getIdToken());
+ this.newCredential.name = this.importIdProvider.name + "oidcjwt";
+ this.newCredential.value = this.oauthService.getIdToken();
+ this.importAttributesFromCredential();
+ });
+ } else {
+
this.oauthService.loadDiscoveryDocumentAndTryLogin(loginOptions).then(success
=> {
+ if (!success || (null == this.oauthService.getIdToken())) {
+ this.importInProgress = false;
+ return;
+ }
+ console.log("Login successful: "+this.oauthService.getIdToken());
+ this.newCredential.name = this.importIdProvider.name + "oidcjwt";
+ this.newCredential.value = this.oauthService.getIdToken();
+ this.importAttributesFromCredential();
+ });
+ }
+ }
+
+ importAttributesFromCredential() {
+ this.importInProgress = true;
+ this.reclaimService.addCredential(this.identity,
this.newCredential).subscribe(res => {
+ console.log("Stored credential");
+ this.reclaimService.getCredentials(this.identity).subscribe(creds => {
+ this.reclaimService.getAttributes(this.identity).subscribe(attrs => {
+ var promises = [];
+ var cred = null;
+ for (var c of creds) {
+ if (c.name == this.newCredential.name) {
+ cred = c;
+ }
+ }
+ if (null == cred) {
+ console.log("ERROR: credential was not added!");
+ this.importInProgress = false;
+ return;
+ }
+ console.log("Trying to import " + cred.attributes.length + "
attributes");
+
+ for (let attr of cred.attributes) {
+ if ((attr.name == "sub") ||
+ (attr.name == "nonce") ||
+ (attr.name == "email_verified") ||
+ (attr.name == "phone_number_verified")) {
+ continue;
+ }
+ //New attribute with name == claim name
+ var attestation = new Attribute(attr.name, '', cred.id, attr.name,
'STRING', '1');
+ for (let existAttr of attrs) {
+ /* Overwrite existing */
+ if (existAttr.name !== attr.name) {
+ continue;
+ }
+ attestation.id = existAttr.id;
+ break;
+ }
+ promises.push(
+ from(this.reclaimService.addAttribute(this.identity,
attestation)));
+ //promises = promises.concat (this.storeAttribute(attestation));
+ }
+ forkJoin(promises)
+ .pipe(
+ finalize(() => {
+ this.importIdProvider.url = '';
+ this.importIdProvider.name = '';
+ localStorage.removeItem('importIdProviderURL');
+ localStorage.removeItem("credentialCode");
+ this.importInProgress = false;
+ this.oauthService.logOut();
+ this.updateAttributes();
+ this.updateCredentials();
+ })
+ ).subscribe(res => {
+ console.log("Finished attribute import.");
+ },
+ err => {
+ console.log(err);
+ });
+ });
+ });
+ });
+ }
+
+ validateEmailForImport() {
+ var emailAddr = null;
+ for (let attr of this.attributes) {
+ if (attr.name !== 'email') {
+ continue;
+ }
+ console.log("Found email attribute " + attr.value);
+ emailAddr = attr.value;
+ break;
+ }
+ if ((null == emailAddr) ||
+ !emailAddr.includes('@')) {
+ this.validImportEmail = false;
+ return;
+ }
+ if (emailAddr.length - emailAddr.indexOf('@') < 4) {
+ this.validImportEmail = false;
+ return;
+ }
+ this.discoverIdProvider(emailAddr);
+ }
+
+ discoverIdProvider(emailAddr: string) {
+ localStorage.setItem('userForCredential', this.identity.name);
+ let account = emailAddr;
+ if (this.configService.get().experiments) {
+ if (emailAddr.substr(emailAddr.indexOf('@')+1) ===
'aisec.fraunhofer.de') {
+ account = emailAddr.substr(0, emailAddr.indexOf('@')+1) +
'as.aisec.fraunhofer.de';
+ } else if (emailAddr.substr(emailAddr.indexOf('@')+1) === 'bfh.ch') {
+ account = emailAddr.substr(0, emailAddr.indexOf('@')+1) +
'omejdn.nslab.ch';
+ }
+ }
+ this.credentialService.getLink(account).subscribe (idProvider => {
+ this.importIdProvider = new IdProvider((idProvider.links[0]).href,
+
(idProvider.links[0]).href.split('//')[1]);
+ localStorage.setItem('importIdProviderURL', this.importIdProvider.url);
+ this.getImportScopes();
+ console.log(this.importIdProvider.url);
+ this.validImportEmail = true;
+ this.tryImportCredential();
+ },
+ error => {
+ this.validImportEmail = false;
+ console.log (error);
+ });
+ }
+
+ mapIssuer(iss: string): string {
+ if (iss.includes("omejdn.nslab.ch")) {
+ return "Berner Fachhochschule";
+ }
+ return iss;
+ }
+
+
+ getImportIssuerName() {
+ return this.mapIssuer(this.importIdProvider.name);
+ }
+
+ getIssuerName(cred: Credential) {
+ return this.mapIssuer(cred.name);
+ }
+
+ import(){
+ this.configureOauthService();
+ this.oauthService.logOut(); //Make sure we logout before login
+ this.oauthService.loadDiscoveryDocumentAndLogin();
+ }
+
+ configureOauthService(){
+ var authCodeFlowConfig =
this.credentialService.getOauthConfig(this.importIdProvider, this.scopes);
+ this.oauthService.configure(authCodeFlowConfig);
+ }
+
+ getImportScopes(){
+ this.configureOauthService();
+
this.credentialService.getDiscoveryDocument(this.oauthService.issuer).subscribe(openidConfig
=> {
+ this.scopes = [];
+ openidConfig["scopes_supported"].forEach(scope => {
+ const scopeInterface: Scope = {
+ scope: scope,
+ chosen: true,
+ }
+ this.scopes.push(scopeInterface)
+ });
+ localStorage.setItem("scopes", JSON.stringify(this.scopes));
+ });
+ }
+
+
+
}
diff --git a/src/locales/de/messages.json b/src/locales/de/messages.json
index ec2500f..67207c3 100644
--- a/src/locales/de/messages.json
+++ b/src/locales/de/messages.json
@@ -50,8 +50,13 @@
"edit_credentials_ts@noAccount": "Kein Konto mit diese E-Email Addresse
gefunden",
"edit_credentials_ts@errorWrongAddress": "Ein Fehler ist aufgetreten - Der
Grund könnte eine falsche E-Email Adresse sein.",
"edit_identity_html@basicInfo": "Gebräuchliche Informationen",
+ "edit_identity_html@importInfo": "Über den 'Importieren'-Knopf kannst du
gegebenenfalls Attribute aus einem existierenden Konto importieren.",
+ "edit_identity_html@linkAccount": "Attribute importieren",
+
"edit_identity_html@standardScopes": "Die unten stehenden Attribute
entsprechen den standard \"scopes\" von OpenID Connect:\n``profile'',
``email'', ``phone'' and ``address''.",
- "edit_identity_html@claimAsAttribute": "{{CREDVALUE}} ausgestellt von
{{ISSUER}} als Attribut für ``{{CLAIMVALUE}}''",
+ "edit_identity_html@selfissued": "Selbst ausgestellt",
+ "edit_identity_html@importFrom": "Von ``{{ISSUERNAME}}´´ importieren",
+ "edit_identity_html@unset": "Nicht gesetzt",
"edit_identity_html@attribute": "Attribut",
"edit_identity_html@plain": "Text",
"edit_identity_html@credential": "Attestierung",
diff --git a/src/locales/en/messages.json b/src/locales/en/messages.json
index a965f3f..4679ec0 100644
--- a/src/locales/en/messages.json
+++ b/src/locales/en/messages.json
@@ -53,11 +53,12 @@
"edit_credentials_ts@noAccount": "No account found with this email",
"edit_credentials_ts@errorWrongAddress": "An Error has occured - This may
have been caused by a wrong e-mail address.",
"edit_identity_html@basicInfo": "Basic user information",
- "edit_identity_html@noAttributes": "This identity seems to not yet have
any attributes!",
- "edit_identity_html@importInfo": "You can import attributes from an
existing online account or manually add your own below.",
+ "edit_identity_html@importInfo": "You may be able to import attributes
from an existing online account by clicking the 'Import' button.",
"edit_identity_html@linkAccount": "Import attributes",
"edit_identity_html@standardScopes": "The attributes below correspond to
the standard scopes of the\nOpenID Connect specification: ``profile'',
``email'', ``phone'' and ``address''.",
- "edit_identity_html@claimAsAttribute": "{{CREDVALUE}} issued by {{ISSUER}}
as attribute for ``{{CLAIMVALUE}}''",
+ "edit_identity_html@selfissued": "Self-issued",
+ "edit_identity_html@importFrom": "Import from ``{{ISSUERNAME}}´´",
+ "edit_identity_html@unset": "Unset",
"edit_identity_html@attribute": "Attribute",
"edit_identity_html@plain": "Plain",
"edit_identity_html@credential": "Credential",
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
- [reclaim-ui] 373/459: fix credential string lowercase, (continued)
- [reclaim-ui] 373/459: fix credential string lowercase, gnunet, 2021/06/11
- [reclaim-ui] 393/459: display all missing claims, gnunet, 2021/06/11
- [reclaim-ui] 380/459: quality of life improvements, gnunet, 2021/06/11
- [reclaim-ui] 383/459: better credential selection, gnunet, 2021/06/11
- [reclaim-ui] 396/459: relax attribute requirements, gnunet, 2021/06/11
- [reclaim-ui] 388/459: significantly simplify identity edit, gnunet, 2021/06/11
- [reclaim-ui] 418/459: more cleanup, gnunet, 2021/06/11
- [reclaim-ui] 431/459: Added translation using Weblate (Portuguese), gnunet, 2021/06/11
- [reclaim-ui] 430/459: mini fix, gnunet, 2021/06/11
- [reclaim-ui] 405/459: fix search icon, gnunet, 2021/06/11
- [reclaim-ui] 381/459: even more quality of life improvements,
gnunet <=
- [reclaim-ui] 416/459: fix, gnunet, 2021/06/11
- [reclaim-ui] 392/459: fix, gnunet, 2021/06/11
- [reclaim-ui] 411/459: fix, gnunet, 2021/06/11
- [reclaim-ui] 410/459: enable filtering, gnunet, 2021/06/11
- [reclaim-ui] 389/459: update, gnunet, 2021/06/11
- [reclaim-ui] 414/459: replace table, gnunet, 2021/06/11
- [reclaim-ui] 400/459: fix, gnunet, 2021/06/11
- [reclaim-ui] 425/459: fix logo, gnunet, 2021/06/11
- [reclaim-ui] 434/459: Added translation using Weblate (Portuguese (Brazil)), gnunet, 2021/06/11
- [reclaim-ui] 429/459: yarn upgrade, gnunet, 2021/06/11