Skip to content

Commit 1453dde

Browse files
committed
tweaks
1 parent 5301dc8 commit 1453dde

File tree

10 files changed

+80
-93
lines changed

10 files changed

+80
-93
lines changed

rubberduckvba.Server/Api/Auth/AuthController.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ public IActionResult Index()
4343
var model = new UserViewModel
4444
{
4545
Name = name,
46-
IsAuthenticated = isAuthenticated,
47-
IsAdmin = isAuthenticated && role == configuration.Value.OwnerOrg
46+
IsAuthenticated = true,
47+
IsAdmin = role == configuration.Value.OwnerOrg
4848
};
4949

5050
return Ok(model);

rubberduckvba.Server/GitHubAuthenticationHandler.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,20 @@ protected async override Task<AuthenticateResult> HandleAuthenticateAsync()
2323
try
2424
{
2525
var token = Context.Request.Headers["X-ACCESS-TOKEN"].SingleOrDefault();
26-
if (token is null)
26+
if (string.IsNullOrWhiteSpace(token))
2727
{
2828
return AuthenticateResult.NoResult();
2929
}
3030

3131
var principal = await _github.ValidateTokenAsync(token);
32-
return principal is ClaimsPrincipal
33-
? AuthenticateResult.Success(new AuthenticationTicket(principal, "github"))
34-
: AuthenticateResult.NoResult();
32+
if (principal is ClaimsPrincipal)
33+
{
34+
Context.User = principal;
35+
Thread.CurrentPrincipal = principal;
36+
return AuthenticateResult.Success(new AuthenticationTicket(principal, "github"));
37+
}
38+
39+
return AuthenticateResult.NoResult();
3540
}
3641
catch (InvalidOperationException e)
3742
{

rubberduckvba.Server/Program.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,7 @@ public static void Main(string[] args)
4545
builder.Services.AddAuthentication(options =>
4646
{
4747
options.RequireAuthenticatedSignIn = false;
48-
4948
options.DefaultAuthenticateScheme = "github";
50-
options.DefaultScheme = "anonymous";
5149

5250
options.AddScheme("github", builder =>
5351
{
@@ -99,7 +97,11 @@ public static void Main(string[] args)
9997

10098
app.UseCors(policy =>
10199
{
102-
policy.SetIsOriginAllowed(origin => true).AllowAnyHeader();
100+
policy
101+
.AllowAnyMethod()
102+
.AllowAnyHeader()
103+
.AllowCredentials()
104+
.SetIsOriginAllowed(origin => true);
103105
});
104106

105107
StartHangfire(app);

rubberduckvba.Server/Services/GitHubClientService.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,11 @@ public class GitHubClientService(IOptions<GitHubSettings> configuration, ILogger
4444
var user = await client.User.Current();
4545
var identity = new ClaimsIdentity(new[]
4646
{
47-
new Claim(ClaimTypes.Name, user.Name),
48-
new Claim(ClaimTypes.Email, user.Email),
47+
new Claim(ClaimTypes.Name, user.Login),
4948
new Claim(ClaimTypes.Role, config.OwnerOrg),
49+
new Claim(ClaimTypes.Authentication, token),
5050
new Claim("access_token", token)
51-
});
51+
}, "github");
5252
return new ClaimsPrincipal(identity);
5353
}
5454

rubberduckvba.client/src/app/components/auth-menu/auth-menu.component.html

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,27 @@
11

22
<div *ngIf="!user || !user.isAuthenticated">
33
<button type="button" role="button" class="nav-link text-dark btn-link" title="Sign in with GitHub" (click)="confirm()">
4-
<fa-icon class="mx-1" [icon]="['fab', 'github']"></fa-icon>Sign in
4+
<fa-icon class="mx-1" [icon]="['fab', 'github']"></fa-icon> Sign in
55
</button>
66
</div>
77

88
<div *ngIf="user && user.isAuthenticated">
99
<div ngbDropdown>
10-
<button ngbDropdownToggle class="nav-link" id="authMenu" title="Signed in with GitHub">{{user.name}}</button>
10+
<button ngbDropdownToggle class="nav-link" id="authMenu" title="Signed in with GitHub"><fa-icon class="mx-1" [icon]="['fab', 'github']"></fa-icon> {{user.name}}</button>
1111
<div ngbDropdownMenu="authMenu">
1212
<div ngbDropdownItem>
1313
<button type="button" role="button" class="nav-link text-dark btn-link" title="Sign out" (click)="signout()">
14-
<fa-icon class="mx-1" [icon]="['fab', 'github']"></fa-icon>Sign out
14+
<fa-icon class="mx-1" [icon]="['fas', 'sign-out']"></fa-icon> Sign out
1515
</button>
16-
<div *ngIf="user.isAdmin">
17-
<hr />
16+
</div>
17+
<div *ngIf="user.isAdmin">
18+
<hr />
19+
<div ngbDropdownItem>
1820
<button type="button" role="button" class="nav-link text-dark btn-link" title="" (click)="confirmUpdateTags()">
1921
Update tag metadata
2022
</button>
23+
</div>
24+
<div ngbDropdownItem>
2125
<button type="button" role="button" class="nav-link text-dark btn-link" title="" (click)="confirmUpdateXmldocs()">
2226
Update xmldoc metadata
2327
</button>
@@ -44,7 +48,7 @@ <h6><fa-icon class="mx-1" [icon]="['fas', 'exclamation-triangle']"></fa-icon>Res
4448
</p>
4549
</div>
4650
<div class="modal-footer">
47-
<button id="cancel-login" type="button" class="btn btn-secondary" data-dismiss="modal" aria-label="Close">Close</button>
51+
<button id="cancel-login" type="button" class="btn btn-secondary" data-dismiss="modal" aria-label="Close" (click)="modal.dismiss('cancel')">Close</button>
4852
<button id="accept-login" type="button" class="btn btn-danger" (click)="signin()">Accept</button>
4953
</div>
5054
</div>
@@ -67,7 +71,7 @@ <h6><fa-icon class="mx-1" [icon]="['fas', 'info-circle']"></fa-icon>Confirm</h6>
6771
</p>
6872
</div>
6973
<div class="modal-footer">
70-
<button id="cancel-tags" type="button" class="btn btn-secondary" data-dismiss="modal" aria-label="Close">Close</button>
74+
<button id="cancel-tags" type="button" class="btn btn-secondary" data-dismiss="modal" aria-label="Close" (click)="modal.dismiss('cancel')">Close</button>
7175
<button id="accept-tags" type="button" class="btn btn-primary" (click)="updateTags()">Proceed</button>
7276
</div>
7377
</div>
@@ -90,7 +94,7 @@ <h6><fa-icon class="mx-1" [icon]="['fas', 'info-circle']"></fa-icon>Confirm</h6>
9094
</p>
9195
</div>
9296
<div class="modal-footer">
93-
<button id="cancel-xmldoc" type="button" class="btn btn-secondary" data-dismiss="modal" aria-label="Close">Close</button>
97+
<button id="cancel-xmldoc" type="button" class="btn btn-secondary" data-dismiss="modal" aria-label="Close" (click)="modal.dismiss('cancel')">Close</button>
9498
<button id="accept-xmldoc" type="button" class="btn btn-primary" (click)="updateXmldocs()">Proceed</button>
9599
</div>
96100
</div>

rubberduckvba.client/src/app/components/auth-menu/auth-menu.component.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1+
/// <reference path="../../app.module.ts" />
12
import { Component, OnInit, TemplateRef, ViewChild, inject } from "@angular/core";
23
import { FaIconLibrary } from "@fortawesome/angular-fontawesome";
34
import { BehaviorSubject } from "rxjs";
45
import { UserViewModel } from "../../model/feature.model";
56
import { AuthService } from "src/app/services/auth.service";
67
import { fas } from "@fortawesome/free-solid-svg-icons";
78
import { fab } from "@fortawesome/free-brands-svg-icons";
8-
import { NgbModal } from "@ng-bootstrap/ng-bootstrap";
9+
import { NgbModal, NgbToast } from "@ng-bootstrap/ng-bootstrap";
910
import { AdminApiClientService, ApiClientService } from "../../services/api-client.service";
1011

1112
@Component({
@@ -69,11 +70,11 @@ export class AuthMenuComponent implements OnInit {
6970

7071
public updateTags(): void {
7172
this.modal.dismissAll();
72-
this.api.updateTagMetadata();
73+
this.api.updateTagMetadata().subscribe(jobId => console.log(`UpdateTagMetadata has scheduled job id ${jobId}`));
7374
}
7475

7576
public updateXmldocs(): void {
7677
this.modal.dismissAll();
77-
this.api.updateXmldocMetadata();
78+
this.api.updateXmldocMetadata().subscribe(jobId => console.log(`UpdateXmldocMetadata has scheduled job id ${jobId}`));
7879
}
7980
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
<loading-content [show]="true" label="'redirecting...'"></loading-content>
1+
<loading-content [show]="true" label="redirecting..."></loading-content>

rubberduckvba.client/src/app/services/api-client.service.ts

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -61,19 +61,13 @@ export class AdminApiClientService {
6161
constructor(private data: DataService) {
6262
}
6363

64-
public updateTagMetadata(): void {
64+
public updateTagMetadata(): Observable<number> {
6565
const url = `${environment.apiBaseUrl}admin/update/tags`;
66-
const jwt = sessionStorage.getItem("jwt");
67-
if (jwt) {
68-
this.data.postWithAccessTokenAsync(jwt, url);
69-
}
66+
return this.data.postAsync(url);
7067
}
7168

72-
public updateXmldocMetadata(): void {
69+
public updateXmldocMetadata(): Observable<number> {
7370
const url = `${environment.apiBaseUrl}admin/update/xmldoc`;
74-
const jwt = sessionStorage.getItem("jwt");
75-
if (jwt) {
76-
this.data.postWithAccessTokenAsync(jwt, url);
77-
}
71+
return this.data.postAsync(url);
7872
}
7973
}

rubberduckvba.client/src/app/services/auth.service.ts

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,25 @@ export class AuthService {
1010
private timeout: number = 10000;
1111
constructor(private data: DataService) { }
1212

13+
private sleep(ms: number): Promise<void> {
14+
return new Promise(resolve => setTimeout(resolve, ms));
15+
}
16+
17+
private writeStorage(key: string, value: string): void {
18+
sessionStorage.setItem(key, value);
19+
while (sessionStorage.getItem(key) != value) {
20+
this.sleep(1000);
21+
}
22+
}
23+
1324
public getUser(): Observable<UserViewModel> {
1425
const url = `${environment.apiBaseUrl}auth`;
15-
return this.data.getWithAccessTokenAsync<UserViewModel>(url);
26+
return this.data.getAsync<UserViewModel>(url);
1627
}
1728

1829
public signin(): void {
1930
const vm = AuthViewModel.withRandomState();
20-
sessionStorage.setItem('xsrf:state', vm.state);
31+
this.writeStorage('xsrf:state', vm.state);
2132

2233
const url = `${environment.apiBaseUrl}auth/signin`;
2334
this.data.postAsync<AuthViewModel, string>(url, vm)
@@ -28,30 +39,30 @@ export class AuthService {
2839
sessionStorage.clear();
2940
}
3041

31-
public onGithubCallback(): void {
32-
const urlParams = new URLSearchParams(location.search);
33-
const code: string = urlParams.get('code')!;
34-
const state: string = urlParams.get('state')!;
42+
public onGithubCallback(): void {
43+
const urlParams = new URLSearchParams(location.search);
44+
const code: string = urlParams.get('code')!;
45+
const state: string = urlParams.get('state')!;
3546

36-
if (state === sessionStorage.getItem('xsrf:state')) {
37-
try {
38-
const vm: AuthViewModel = { state, code };
39-
const url = `${environment.apiBaseUrl}auth/github`;
40-
41-
this.data.postAsync<AuthViewModel, AuthViewModel>(url, vm)
42-
.subscribe(result => {
43-
sessionStorage.setItem('github:access_token', result.token!);
44-
location.href = '/';
45-
});
46-
}
47-
catch (error) {
48-
console.log(error);
49-
location.href = '/';
50-
}
47+
if (state === sessionStorage.getItem('xsrf:state')) {
48+
try {
49+
const vm: AuthViewModel = { state, code };
50+
const url = `${environment.apiBaseUrl}auth/github`;
51+
52+
this.data.postAsync<AuthViewModel, AuthViewModel>(url, vm)
53+
.subscribe(result => {
54+
this.writeStorage('github:access_token', result.token!);
55+
location.href = '/';
56+
});
5157
}
52-
else {
53-
console.log('xsrf:state mismatched!');
58+
catch (error) {
59+
console.log(error);
5460
location.href = '/';
5561
}
5662
}
63+
else {
64+
console.log('xsrf:state mismatched!');
65+
location.href = '/';
66+
}
67+
}
5768
}

rubberduckvba.client/src/app/services/data.service.ts

Lines changed: 6 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -12,43 +12,13 @@ export class DataService {
1212
}
1313

1414
public getAsync<TResult>(url: string): Observable<TResult> {
15-
const headers = new HttpHeaders()
16-
.append('accept', 'application/json');
17-
18-
return this.http.get(url, { headers })
19-
.pipe(
20-
map(result => <TResult>result),
21-
timeout(this.timeout),
22-
catchError((err: Response) => {
23-
console.log(err);
24-
return throwError(() => err.text);
25-
})
26-
);
27-
}
28-
29-
public postAsync<TContent, TResult>(url: string, content?: TContent): Observable<TResult> {
30-
const headers = new HttpHeaders()
31-
.append('accept', 'application/json')
32-
.append('Content-Type', 'application/json; charset=utf-8');
33-
34-
return (content
35-
? this.http.post(url, content, { headers })
36-
: this.http.post(url, { headers }))
37-
.pipe(
38-
map(result => <TResult>result),
39-
timeout(this.timeout),
40-
catchError((err: Response) => throwError(() => err.text))
41-
);
42-
}
43-
44-
45-
public getWithAccessTokenAsync<TResult>(url: string): Observable<TResult> {
46-
const headers = new HttpHeaders()
15+
let headers = new HttpHeaders()
4716
.append('accept', 'application/json');
4817

4918
const token = sessionStorage.getItem('github:access_token');
5019
if (token) {
51-
headers.append('X-ACCESS-TOKEN', token);
20+
headers = headers.append('X-ACCESS-TOKEN', token)
21+
.append('Access-Control-Allow-Origin', '*');
5222
}
5323

5424
return this.http.get(url, { headers })
@@ -62,14 +32,14 @@ export class DataService {
6232
);
6333
}
6434

65-
public postWithAccessTokenAsync<TContent, TResult>(url: string, content?: TContent): Observable<TResult> {
66-
const headers = new HttpHeaders()
35+
public postAsync<TContent, TResult>(url: string, content?: TContent): Observable<TResult> {
36+
let headers = new HttpHeaders()
6737
.append('accept', 'application/json')
6838
.append('Content-Type', 'application/json; charset=utf-8');
6939

7040
const token = sessionStorage.getItem('github:access_token');
7141
if (token) {
72-
headers.append('X-ACCESS-TOKEN', token);
42+
headers = headers.append('X-ACCESS-TOKEN', token);
7343
}
7444

7545
return (content

0 commit comments

Comments
 (0)